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.


///////////////////////////////////////////////////////////////////////////////
// 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



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.
핑백: Stylized toon Urp update. – MY NAME IS JP