You copied the Doc URL to your clipboard.

Combining reflections shader implementation

You can combine static environment reflections, with dynamic planar reflections in a shader.

To combine reflections in the shaders, you must modify the shader code provided in Shader Implementation.

The shader must incorporate the planar reflections, rendered at runtime with the reflection camera. To achieve this, the texture _ReflectionTex from the reflection camera, is passed to the fragment shader as a uniform, and combined with the planar reflection result using a lerp() function.

In addition to the data related to the local correction, the vertex shader also calculates the screen coordinates of the vertex using the built-in function ComputeScreenPos(). It passes these coordinates to the fragment shader:

vertexOutput vert(vertexInput input)
{
	vertexOutput output;
	output.tex = input.texcoord;
	
	// Transform vertex coordinates from local to world.
	float4 vertexWorld = mul(_Object2World, input.vertex);
	
	// Transform normal to world coordinates.
	float4 normalWorld = mul(float4(input.normal,0.0), _World2Object);
	
	// Final vertex output position.
	output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
	
	// ----------- Local correction ------------
	output.vertexInWorld = vertexWorld.xyz;
	output.viewDirInWorld = vertexWorld.xyz - _WorldSpaceCameraPos;
	output.normalInWorld = normalWorld.xyz;
	
	// ----------- Planar reflections ------------
	output.vertexInScreenCoords = ComputeScreenPos(output.pos);
	return output;
}

The planar reflections are rendered to a texture, so the fragment shader is able to access the screen coordinates of the fragment. To enable this, pass the vertex screen coordinates to the fragment shader as a varying.

In the fragment shader:

  • Apply the local correction to the reflection vector.

  • Retrieve the color of the environment reflections staticReflColor from the local cubemap.

The following code shows how to combine static environment reflections, using the local cubemap technique, with dynamic planar reflections, that are rendered at runtime using the mirrored camera technique:

float4 frag(vertexOutput input) : COLOR
{
	float4 staticReflColor = float4(1, 1, 1, 1);

	// Find reflected vector in WS.
	float3 viewDirWS = normalize(input.viewDirInWorld);
	float3 normalWS = normalize(input.normalInWorld);
	float3 reflDirWS = reflect(viewDirWS, normalWS);

	// Working in World Coordinate System.
	float3 localPosWS = input.vertexInWorld;
	float3 intersectMaxPointPlanes = (_BBoxMax - localPosWS) / reflDirWS;
	float3 intersectMinPointPlanes = (_BBoxMin - localPosWS) / reflDirWS;

	// Look only for intersections in the forward direction of the ray.
	float3 largestParams = max(intersectMaxPointPlanes, intersectMinPointPlanes);

	// Smallest value of the ray parameters gives us the intersection.
	float distToIntersect = min(min(largestParams.x, largestParams.y), largestParams.z);

	// Find the position of the intersection point.
	float3 intersectPositionWS = localPosWS + reflDirWS * distToIntersect;

	// Get local corrected reflection vector.
	float3 localCorrReflDirWS = intersectPositionWS - _EnviCubeMapPos;

	// Lookup the environment reflection texture with the right vector.
	float4 staticReflColor = texCUBE(_Cube, localCorrReflDirWS);

	// Lookup the planar runtime texture
	float4 dynReflColor = tex2Dproj(_ReflectionTex,
	UNITY_PROJ_COORD(input.vertexInScreenCoords);

	//Revert the blending with the background color of the reflection camera
	dynReflColor.rgb /= (dynReflColor.a < 0.00392)?1:dynReflColor.a;

	// Combine static environment reflections with dynamic planar reflections
	float4 combinedRefl = lerp(staticReflColor.rgb, dynReflColor.rgb, dynReflColor.a);

	// Lookup the texture color.
	float4 texColor = tex2D(_MainTex, float2(input.tex));
	return _AmbientColor + texColor * _ReflAmount * combinedRefl;
}

Extract the texture color dynReflColor, from the planar runtime reflection texture _ReflectionTex.

Declare _ReflectionTex as a uniform in the shader.

Declare _ReflectionTex in the Property Block. This enables you to see how it looks at runtime and this assists you with debugging while you are developing your game.

For the texture lookup, project the texture coordinates, that is, divide the texture coordinates by the last component of the coordinate vector. You can use the Unity built-in function UNITY_PROJ_COORD() for this.

Use the lerp() function to combine the static environment reflections and the dynamic planar reflections. Combine the following:

  • The reflection color.

  • The texture color of the reflective surface.

  • The ambient color component.
Was this page helpful? Yes No