News

Abstract

Cover

We propose a novel skin shader which translates the simulation of subsurface scattering from texture space to a screen-space diffusion approximation. It naturally scales well while maintaining a perceptually plausible result. This technique allows us to ensure real-time performance even when several characters may appear on screen at the same time. The visual realism of the resulting images is validated using a subjective psychophysical preference experiment. Our results show that, independent of distance and light position, the images rendered using our novel shader have as high visual realism as a previously developed physically-based shader.

A very efficient implementation is described in the first book of the GPU Pro series. Buy the book!

Downloads

1 Please note that the GPU Pro chapter contains more low-level details on the implementation, including gaussian removal depending on distance and a very efficient alpha blending pipeline. We encorage you to buy the book for getting all the details.

Shader

float4 BlurPS(PassV2P input, uniform float2 step) : SV_TARGET {
    // Gaussian weights for the six samples around the current pixel:
    //   -3 -2 -1 +1 +2 +3
    float w[6] = { 0.006,   0.061,   0.242,  0.242,  0.061, 0.006 };
    float o[6] = {  -1.0, -0.6667, -0.3333, 0.3333, 0.6667,   1.0 };

    // Fetch color and linear depth for current pixel:
    float4 colorM = colorTex.Sample(PointSampler, input.texcoord);
    float depthM = depthTex.Sample(PointSampler, input.texcoord);

    // Accumulate center sample, multiplying it with its gaussian weight:
    float4 colorBlurred = colorM;
    colorBlurred.rgb *= 0.382;

    // Calculate the step that we will use to fetch the surrounding pixels,
    // where "step" is:
    //     step = sssStrength * gaussianWidth * pixelSize * dir
    // The closer the pixel, the stronger the effect needs to be, hence
    // the factor 1.0 / depthM.
    float2 finalStep = colorM.a * step / depthM;

    // Accumulate the other samples:
    [unroll]
    for (int i = 0; i < 6; i++) {
        // Fetch color and depth for current sample:
        float2 offset = input.texcoord + o[i] * finalStep;
        float3 color = colorTex.SampleLevel(LinearSampler, offset, 0).rgb;
        float depth = depthTex.SampleLevel(PointSampler, offset, 0);

        // If the difference in depth is huge, we lerp color back to "colorM":
        float s = min(0.0125 * correction * abs(depthM - depth), 1.0);
        color = lerp(color, colorM.rgb, s);

        // Accumulate:
        colorBlurred.rgb += w[i] * color;
    }

    // The result will be alpha blended with current buffer by using specific
    // RGB weights. For more details, I refer you to the GPU Pro chapter :)
    return colorBlurred;
}

Bibtex

@article{JIMENEZ2009_TAP,
    author = {Jorge Jimenez and Veronica Sundstedt and Diego Gutierrez},
    title = {Screen-space perceptual rendering of human skin},
    journal = {ACM Transactions on Applied Perception},
    volume = {6},
    number = {4},
    year = {2009},
    pages = {23:1--23:15},
}
@inbook{JIMENEZ2010_GPUPRO,
    author = {Jorge Jimenez and Diego Gutierrez},
    editor = {Wolfgang Engel},
    title = {GPU Pro: Advanced Rendering Techniques},
    chapter = {Screen-Space Subsurface Scattering},
    publisher = {{AK} Peters Ltd.},
    year = {2010},
    pages = {335--351},
}
@article{JIMENEZ2010_IEEE,
    author = {Jorge Jimenez and David Whelan and Veronica Sundstedt and Diego Gutierrez},
    title = {Real-Time Realistic Skin Translucency},
    journal = {IEEE Computer Graphics and Applications},
    volume = {30},
    number = {4},
    year = {2010},
    pages = {32--41},
}
@article{JIMENEZ2010_TOG,
    author = {Jorge Jimenez and Timothy Scully and Nuno Barbosa and Craig Donner and Xenxo Alvarez and
              Teresa Vieira and Paul Matts and Verónica Orvalho and Diego Gutierrez and Tim Weyrich},
    title = {A practical appearance model for dynamic facial color},
    journal = {ACM Transactions on Graphics (Proc. SIGGRAPH Asia)},
    year = {2010},
    volume = {29},
    number = {6},
    pages = {141:1--141:10},
}
@inbook{JIMENEZ2011_GPUPRO2B,
    author = {Jorge Jimenez and Jose I. Echevarria and Christopher Oat and Diego Gutierrez},
    editor = {Wolfgang Engel},
    title = {{GPU} Pro 2},
    chapter = {Practical and Realistic Facial Wrinkles Animation},
    publisher = {{AK} Peters Ltd.},
    year = {2011},
}
@article{JIMENEZ2015_CGF,
    author = {Jorge Jimenez and Károly Zsolnai and Adrian Jarabo and Christian Freude and Thomas Auzinger and
              Xian-Chun Wu and Javier von der Pahlen and Michael Wimmer and Diego Gutierrez},
    title = {Separable Subsurface Scattering},
    journal = {Computer Graphics Forum},
    year = {2015},
}

Related

Links