195 lines · 5.2 KB · Text
RawDownload
//  Generated on <$_SCRIBE_DATE$>////  Created by Sam Gateau on 6/8/16.//  Copyright 2016 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//<@if not SUBSURFACE_SCATTERING_SLH@><@def SUBSURFACE_SCATTERING_SLH@> <@include render-utils/ShaderConstants.h@> <@func declareSubsurfaceScatteringProfileSource()@> float gaussian(float v, float r) {    const float _PI = 3.14159265358979523846;    return (1.0 / sqrt(2.0 * _PI * v)) * exp(-(r*r) / (2.0 * v));} vec3 scatter(float r) {    // r is the distance expressed in millimeter    // returns the scatter reflectance    // Values from GPU Gems 3 "Advanced Skin Rendering".    // Originally taken from real life samples.    const vec4 profile[6] = vec4[6](        vec4(0.0064, 0.233, 0.455, 0.649),        vec4(0.0484, 0.100, 0.336, 0.344),        vec4(0.1870, 0.118, 0.198, 0.000),        vec4(0.5670, 0.113, 0.007, 0.007),        vec4(1.9900, 0.358, 0.004, 0.000),        vec4(7.4100, 0.078, 0.000, 0.000)        );    const int profileNum = 6;     vec3 ret = vec3(0.0);    for (int i = 0; i < profileNum; i++) {        float v = profile[i].x * 1.414;        float g = gaussian(v, r);        ret += g * profile[i].yzw;    }     return ret;} <@endfunc@> <@func declareSubsurfaceScatteringGenerateProfileMap()@><$declareSubsurfaceScatteringProfileSource()$> vec3 generateProfile(vec2 uv) {    return scatter(uv.x * 2.0);} <@endfunc@> <@func declareSubsurfaceScatteringProfileMap()@> TEXTURE(RENDER_UTILS_TEXTURE_SSSC_PROFILE, sampler2D, scatteringProfile); vec3 scatter(float r) {    return texture(scatteringProfile, vec2(r * 0.5, 0.5)).rgb;} <@endfunc@>  <@func declareSubsurfaceScatteringIntegrate(NumIntegrationSteps)@>  vec3 integrate(float cosTheta, float skinRadius) {    // Angle from lighting direction.    float theta = acos(cosTheta);    vec3 totalWeights = vec3(0.0);    vec3 totalLight = vec3(0.0);     const float _PI = 3.14159265358979523846;    const float step = 2.0 * _PI / float(<$NumIntegrationSteps$>);    float a = -(_PI);      while (a <= (_PI)) {        float sampleAngle = theta + a;        float diffuse = clamp(cos(sampleAngle), 0.0, 1.0);         // Distance.        float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5));         // Profile Weight.        vec3 weights = scatter(sampleDist);         totalWeights += weights;        totalLight += diffuse * weights;        a += step;    }     vec3 result = (totalLight / totalWeights);    return clamp(result, vec3(0.0), vec3(1.0)); }<@endfunc@> <@func declareSubsurfaceScatteringResource()@> TEXTURE(RENDER_UTILS_TEXTURE_SSSC_LUT, sampler2D, scatteringLUT); vec3 fetchBRDF(float LdotN, float curvature) {    return texture(scatteringLUT, vec2( clamp(LdotN * 0.5 + 0.5, 0.0, 1.0), clamp(2.0 * curvature, 0.0, 1.0))).xyz;} vec3 fetchBRDFSpectrum(vec3 LdotNSpectrum, float curvature) {    return vec3(        fetchBRDF(LdotNSpectrum.r, curvature).r,        fetchBRDF(LdotNSpectrum.g, curvature).g,        fetchBRDF(LdotNSpectrum.b, curvature).b);} // Subsurface Scattering parametersstruct ScatteringParameters {    vec4 normalBendInfo; // R, G, B, factor    vec4 curvatureInfo;// Offset, Scale, level    vec4 debugFlags;}; UNIFORM_BUFFER(RENDER_UTILS_BUFFER_SSSC_PARAMS, subsurfaceScatteringParametersBuffer) {    ScatteringParameters parameters;}; vec3 getBendFactor() {    return parameters.normalBendInfo.xyz * parameters.normalBendInfo.w;} float getScatteringLevel() {    return parameters.curvatureInfo.z;} bool showBRDF() {    return parameters.curvatureInfo.w > 0.0;} bool showCurvature() {    return parameters.debugFlags.x > 0.0;}bool showDiffusedNormal() {    return parameters.debugFlags.y > 0.0;}  float tuneCurvatureUnsigned(float curvature) {    return abs(curvature) * parameters.curvatureInfo.y + parameters.curvatureInfo.x;} float unpackCurvature(float packedCurvature) {    return (packedCurvature * 2.0 - 1.0);} vec3 evalScatteringBentNdotL(vec3 normal, vec3 midNormal, vec3 lowNormal, vec3 lightDir) {    vec3 bendFactorSpectrum = getBendFactor();    // vec3 rN = normalize(mix(normal, lowNormal, bendFactorSpectrum.x));    vec3 rN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.x));    vec3 gN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.y));    vec3 bN = normalize(mix(midNormal, lowNormal, bendFactorSpectrum.z));     vec3 NdotLSpectrum = vec3(dot(rN, lightDir), dot(gN, lightDir), dot(bN, lightDir));     return NdotLSpectrum;}   <@endfunc@> <@func declareSubsurfaceScatteringBRDF()@><$declareSubsurfaceScatteringResource()$> vec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, float curvature) {    if (showDiffusedNormal()) {        return lowNormal * 0.5 + vec3(0.5);    }    if (showCurvature()) {        float check = float(curvature > 0.0);        return vec3(check * curvature, 0.0, (1.0 - check) * -curvature);    }     vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir);     float tunedCurvature = tuneCurvatureUnsigned(curvature);     vec3 brdf = fetchBRDFSpectrum(bentNdotL, tunedCurvature);    return brdf;} <@endfunc@> <@endif@>