6.5 Specular effects in the Ice Cave demo

Specular effects in the Ice Cave demo are implemented using the Blinn technique. This is a very efficient technique that produces good results.

The following code shows how to implement specular effects with the Blinn technique:
// Returns intensity of a specular effect without taking into account shadows
float SpecularBlinn(float3 vert2Light, float3 viewDir, float3 normalVec, float4 power)
{
    float3 floatDir = normalize(vert2Light - viewDir);
    float specAngle = max(dot(floatDir, normalVec), 0.0);
    return pow(specAngle, power);
}
A downside of the Blinn technique is that it can produce incorrect results in certain circumstances. For example, specular effects can appear in regions that are in shadow.
The following figure shows an example of a shadowed region with no specular effects:
Figure 6-42 Shadowed region

The following figure shows an example of specular effects in a shadowed region. These are incorrect:
Figure 6-43 Shadowed region with incorrect specular effects

The following figure shows an example of specular effects in a lit region. This is correct:
Figure 6-44 Lit region with correct specular effects

The shadows should make the specular effects intensity either stronger or weaker, depending on the light reaching the specular surface. All the information required to correct the intensity of the specular effects is already in the Ice Cave demo, so fixing it is relatively simple. The environment cubemap texture that is used for reflection and shadow effects contains two types of information. The RGB channels contain environment colors that are used for reflections. The alpha channel contains opacity and this is used for shadows. You can use the alpha channel to determine the specular intensity because the alpha channel represents holes in the cave that let light in to the environment. The alpha channel is therefore used to ensure the specular effect is applied only to surfaces that are lit.
To do this, calculate a corrected reflection vector in a fragment shader to make the reflection effect. For more information about creating the corrected reflection vector see 6.2 Implementing reflections with a local cubemap. Use this vector to fetch the RGBA texel from a cubemap texture:
// Locally corrected static reflections
 const half4 reflColor = SampleCubemapWithLocalCorrection(
        ReflDirectionWS,
        _ReflBBoxMinWorld,
        _ReflBBoxMaxWorld,
        input.vertexInWorld,
        _ReflCubePosWorld,
        _ReflCube);
For more information about what the SampleCubemapWithLocalCorrection() function, see 6.2 Implementing reflections with a local cubemap.
reflColor is in RGBA format where the RGB components contain color data for reflections and the alpha channel contains the intensity of the specular effect. In the Ice Cave demo, the alpha channel is multiplied by the specular color, that is calculated with the Blinn technique:
half3 specular = _SpecularColor.rgb *
		SpecularBlinn(
			input.vertexToLight01InWorld,
			viewDirInWorld,
			normalInWorld,
			_SpecularPower) *
		reflColor.a;
The specular value represents the final specular color. You can add this to your lighting model.
Non-ConfidentialPDF file icon PDF versionARM 100140_0201_00_en
Copyright © 2014, 2015 ARM. All rights reserved.