Energy conserved specular blinn-phong.

Energy conserved specular blinn-phong implementation record

Elements of Implementations

  • Energy conserved diffuse with specular.
  • Physically based Fresnel.
  • Environments Reflectance.
  • Ambient lighting adjustment controller.

Energy conserved diffuse with specular.

about energy conserved specular.

Method of Simple energy calculations of shader.
Applied Energy Conservation of blinn-phong specular.
///////////////////////////////////////////////////////////////////////////////
//                      Lighting Functions                                   //
///////////////////////////////////////////////////////////////////////////////
half3 LightingLambert(half3 lightColor, half3 lightDir, half3 normal)
{
    half NdotL = saturate(dot(normal, lightDir));
#ifdef ENERGY_CONSERVED_DIFFUSE
    return (1.0 / PI ) * lightColor * NdotL;
#else
    return lightColor * NdotL;
#endif
}


half3 LightingSpecular(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specular, half smoothness)
{
    
    float3 halfVec = SafeNormalize(float3(lightDir) + float3(viewDir));
    half NdotH = saturate(dot(normal, halfVec)); //specualrDot
    half modifier = 0;
#ifdef ENERGY_CONSERVED_BLINNPHONG_2PI
//PI is already defined location from "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
    half norm = (smoothness + 2 ) / (2 * PI ); //refer document by "http://mathinfo.univ-reims.fr/IMG/pdf/Using_the_modified_Phong_reflectance_model_for_Physically_based_rendering_-_Lafortune.pdf"
    modifier = pow(NdotH, smoothness) * norm;
#else
    modifier = pow(NdotH, smoothness);
#endif

#ifdef ENERGY_CONSERVED_BLINNPHONG_8PI
    half norm = (smoothness + 2)*(smoothness + 4 ) / ((8 * PI )*(2-(smoothness/2) + smoothness)); //refer document by "http://mathinfo.univ-reims.fr/IMG/pdf/Using_the_modified_Phong_reflectance_model_for_Physically_based_rendering_-_Lafortune.pdf"
    modifier = pow(NdotH, smoothness) * norm;
#else
    modifier = pow(NdotH, smoothness);
#endif
    half3 specularReflection = specular.rgb * modifier;
    return lightColor * specularReflection;
}

half3 LightingPhysicallyBased(BRDFData brdfData, half3 lightColor, half3 lightDirectionWS, half lightAttenuation, half3 normalWS, half3 viewDirectionWS)
{
    half NdotL = saturate(dot(normalWS, lightDirectionWS));
    half3 radiance = lightColor * (lightAttenuation * NdotL);
    return DirectBDRF(brdfData, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
}

half3 LightingPhysicallyBased(BRDFData brdfData, Light light, half3 normalWS, half3 viewDirectionWS)
{
    return LightingPhysicallyBased(brdfData, light.color, light.direction, light.distanceAttenuation * light.shadowAttenuation, normalWS, viewDirectionWS);
}

half3 VertexLighting(float3 positionWS, half3 normalWS)
{
    half3 vertexLightColor = half3(0.0, 0.0, 0.0);

#ifdef _ADDITIONAL_LIGHTS_VERTEX
    uint lightsCount = GetAdditionalLightsCount();
    for (uint lightIndex = 0u; lightIndex < lightsCount; ++lightIndex)
    {
        Light light = GetAdditionalLight(lightIndex, positionWS);
        half3 lightColor = light.color * light.distanceAttenuation;
        vertexLightColor += LightingLambert(lightColor, light.direction, normalWS);
    }
#endif

    return vertexLightColor;
}

Energy conserved experimental code block.


Simulate of Specular Reflectance

Applied Ambient Contrast
half3 GlossyEnvironmentReflectionExt(half3 reflectVector, half smoothness, half occlusion)
            {
            #if !defined(_ENVIRONMENTREFLECTIONS_OFF)
                half mip = smoothness;
                half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip);
            
            #if !defined(UNITY_USE_NATIVE_HDR)
                half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
            #else
                half3 irradiance = encodedIrradiance.rbg;
            #endif
            
                return irradiance * occlusion;
            #endif // GLOSSY_REFLECTIONS
                return _GlossyEnvironmentColor.rgb * occlusion;
            }
half4 UniversalFragmentBlinnPhongExtend(InputData inputData, half3 reflectVector,  half3 diffuse, half4 specularGloss, half smoothness, half reflectionRoughness,  half3 emission, half occlusion,half alpha)
            {
                
                Light mainLight = GetMainLight(inputData.shadowCoord);
                MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
            
                half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
                half3 diffuseColor = 1;
            
                diffuseColor = inputData.bakedGI + LightingLambertExt(attenuatedLightColor, mainLight.direction, inputData.normalWS);
                diffuseColor *=occlusion;
                half3 specularColor = LightingSpecularExtend(attenuatedLightColor, mainLight.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
                diffuseColor +=GlossyEnvironmentReflectionExt(reflectVector, reflectionRoughness, occlusion);
            #ifdef _ADDITIONAL_LIGHTS
                uint pixelLightCount = GetAdditionalLightsCount();
                for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
                {
                    Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
                    half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
                    diffuseColor += LightingLambertExt(attenuatedLightColor, light.direction, inputData.normalWS);
                    specularColor += LightingSpecularExtend(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
                }
            #endif
            
            #ifdef _ADDITIONAL_LIGHTS_VERTEX
                diffuseColor += inputData.vertexLighting;
            #endif
                half3 finalColor = diffuseColor * diffuse + emission;
            
            #if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
                finalColor += specularColor;
            #endif
                
                return half4(finalColor, alpha);
            }

Specular Reflectance experimental code block.

Liked it? Take a second to support leegoonz on Patreon!

댓글 남기기

%d 블로거가 이것을 좋아합니다: