- Home /
Can I render a single render but only with the objects that are not occluded by other objects (on other layers)?
I'm currently working on the visuals for my game. Currently, it looks like this:
.
Using a composite shader, I am able to colour the light and dark areas of the objects on the default layer. Now I would like to be able to add pure white objects to the scene as well. As can be seen on the image, this seems to work at first glance, but my current solution has one major flaw: The white objects are not occluded by the other geometry.
Now, as I understand, with a camera's culling mask only set to one layer, this camera will exclusively render the objects of that layer, not taking into account any geometry on other layers, correct?
Is there a way to get that information back in, so I can make highlights that are occluded by the other geometry?
The current code looks like this (Disclaimer: It's a solution I got from a colleague which I slightly adapted while I can find my way around C#, I'm always stumped when it comes to Shaderlab):
CompositeEffect.cs:
using UnityEngine; using System.Collections;
[ExecuteInEditMode] [AddComponentMenu("Image Effects/Composite")] public class CompositeEffect : MonoBehaviour {
public Camera lightCamera; public Camera darkCamera; public Camera highlightsCamera;
public Shader compositeShader;
public float contrast = 0.8f;
Material _material; Material material { get { if (_material == null) _material = new Material (compositeShader); _material.hideFlags = HideFlags.HideAndDontSave; return _material; } }
Vector2 renderScreenSize = Vector2.zero;
RenderTexture lightTex; RenderTexture darkTex; RenderTexture highlightTex;
// []
// Called by the camera to apply the image effect void OnRenderImage (RenderTexture source, RenderTexture destination) {
if (!lightCamera || !darkCamera)
return;
contrast = Mathf.Clamp01 (contrast);
Vector2 currScreenSize = new Vector2 (Screen.width, Screen.height);
if (!lightCamera.targetTexture || !lightCamera.targetTexture ||
!lightTex || !darkTex || !highlightsCamera.targetTexture || !highlightTex || renderScreenSize != currScreenSize)
{
RecreateTextures (currScreenSize);
AssignTextures ();
}
lightCamera.Render ();
darkCamera.Render ();
highlightsCamera.Render ();
// assign textures for blending
material.SetTexture ("_Tex1", lightCamera.targetTexture);
material.SetTexture ("_Tex2", darkCamera.targetTexture);
material.SetTexture("_Tex3", highlightsCamera.targetTexture);
material.SetFloat("_Contrast", contrast * 0.5f);
// blend maintexture and blendtexture using blendmap
Graphics.Blit(source,destination,material);
} }
Shader:
Shader "Hidden/Composite" { Properties { _MainTex ("Main Texture (RGBA)", RECT) = "transparent" {} _Tex1 ("Texture 1 (RGB)", RECT) = "white" {} _Tex2 ("Texture 2 (RGB)", RECT) = "white" {} _Tex3 ("Texture 2 (RGB)", RECT) = "transparent" {} _Contrast ("Contrast", Range (0,0.5)) = 0.4 }
Category {
SubShader {
Pass {
ZTest Off
Cull Off
ZWrite Off
Fog { Mode Off }
CGPROGRAM // profiles arbfp1 #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_fog_exp2 #pragma fragmentoption ARB_precision_hint_fastest #include "UnityCG.cginc"
float _Contrast; sampler2D _MainTex : register(s0); sampler2D _Tex1 : register(s1); sampler2D _Tex2 : register(s2); sampler2D _Tex3 : register(s3);
struct v2f { float4 pos : POSITION; float2 uvMainTex : TEXCOORD0; float2 uvTex1 : TEXCOORD1; float2 uvTex2 : TEXCOORD2; float2 uvTex3 : TEXCOORD3; };
v2f vert( appdata_img v ) { v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.uvMainTex = MultiplyUV( UNITY_MATRIX_TEXTURE0, v.texcoord); o.uvTex1 = MultiplyUV( UNITY_MATRIX_TEXTURE1, v.texcoord); o.uvTex2 = MultiplyUV( UNITY_MATRIX_TEXTURE2, v.texcoord); o.uvTex3 = MultiplyUV( UNITY_MATRIX_TEXTURE3, v.texcoord); return o; }
float4 frag (v2f i) : COLOR { float4 col0 = tex2D(_Tex1, i.uvTex1); // Colour overlay (paints dark parts of model) float4 col1 = tex2D(_Tex2, i.uvTex2); // Background colour (paints light parts of model) float4 col2 = tex2D(_Tex3, i.uvTex3); // Highlights float4 mainCol = tex2D(_MainTex, i.uvMainTex);
float lum = Luminance( mainCol.rgb ); // get _MainTex luminance
lum = smoothstep(0+_Contrast,1-_Contrast,lum); // set contrast
// float4 output = col0 (1-lum) + col1 lum ; // blend _Tex1 and _Tex2 by luminance of _MainTex float4 output = col0 (1-lum) + col1 lum + col2; // All three textures // float4 output = col0 + col1 lum; // add second texture on top let's try that. //float4 output = col0 col1; // multiply (untested)
return output;
} ENDCG
SetTexture [_MainTex] {}
SetTexture [_Tex1] {}
SetTexture [_Tex2] {}
SetTexture [_Tex3] {}
}
}
}
Fallback off
}
Edit: Would it be possible to create a shaders for such objects and define a specific RenderType
tag (like "highlight") in them so I could use a replacement shader in the camera that renders those objects and leaves everything else black? How would I do that?
Answer by xeophin · Mar 29, 2011 at 07:55 AM
Using the idea outlined above and finding the "Show Render Types" example, I was able to construct the replacement shader:
Shader "Hidden/Show Render Types" { Properties { _MainTex ("Base", 2D) = "white" {} _Cutoff ("Cutoff", float) = 0.5 _Color ("Color", Color) = (1,1,1,1) } Category { Fog { Mode Off }
// First all objects that occlude other objects ...
SubShader { Tags { "RenderType"="Opaque" } Pass { Lighting On Material { Diffuse (0.0,0.0,0.0,0) Ambient (0.0,0.0,0.0,0) } } }
SubShader { Tags { "RenderType"="Transparent" } Pass { Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Color (0.0,0.0,0.0,0.5) } }
SubShader { Tags { "RenderType"="TransparentCutout" } Pass { AlphaTest Greater [_Cutoff] SetTexture[_MainTex] { constantColor(0.3,0.3,1.0,0.5) combine constant, texture } } }
// [...]
// All shaders that need to be rendered normally
SubShader { Tags { "RenderType"="HighlightOpaque" } UsePass "Highlight/Diffuse/FORWARD" }
SubShader { Tags { "RenderType" = "HighlightTransparentParticle"} UsePass "Highlight/Particles/Additive (Soft)/BASE" }
//[...]
} }
All objects that need to be white need to use special versions of the normal shaders that have the correct RenderType
tag set.
By using the composite shader above, I can add the highlights and voil: iPod ad look.