- Home /
_Projector, Projector shader and CG
Trying to improve the visual quality of our projectors, I wanted to modify the shader we use for the projectors material.
This is what we and probably most people are using:
Shader "Projector/Projector Multiply"
{
Properties
{
_Color ("Main Colour", Color) = (1,1,1,0)
_ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
}
Subshader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent+100"}
Pass
{
ZWrite Off
Offset -1, -1
Fog { Mode Off }
//AlphaTest Greater .1
AlphaTest Less 1
ColorMask RGB
Blend One SrcAlpha
SetTexture [_ShadowTex]
{
constantColor [_Color]
combine texture * constant, One - texture
Matrix [_Projector]
}
}
}
}
We slightly modified it so that it can take a color and removed the falloff texture, but that's pretty much what you'll find in the Projectors package BlobShadow prefab shader.
Since I want way better control about the way this is all rendered, and since like every sane person I hate fixed-functions shader programming, I wanted to move it to CG code. My puny and failed attempt at simply reproducing what the fixed function shader was doing looks like this:
Shader "Projector/Projector Multiply"
{
Properties
{
_Color ("Main Colour", Color) = (1,1,1,0)
_ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
}
Subshader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent+100"}
Pass
{
ZWrite Off
Offset -1, -1
Fog { Mode Off }
//AlphaTest Greater .1
AlphaTest Less 1
ColorMask RGB
Blend One SrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float2 uv_Main : TEXCOORD0;
};
sampler2D _ShadowTex;
float4 _Color;
float4x4 _Projector;
v2f vert(appdata_tan v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.uv_Main = mul (_Projector, v.texcoord).xy;
return o;
}
half4 frag (v2f i) : COLOR
{
half4 tex = tex2D(_ShadowTex, i.uv_Main) * _Color;
tex.a = 1-tex.a;
return tex;
}
ENDCG
}
}
}
This doesn't work, it looks like the projection is being done wrong, as it seems to take only a very little part of the texture I'm passing in:
(I didn't use the same texture since the other one was simply giving invisible results, whereas this one shows a little gradient on the right coming from the texture, God knows from what part of it though) (The receiving geometry in the back is a Terrain in both cases)
Anyone knows projectors in great details?
Thanks.
Answer by Aras · Jan 03, 2011 at 03:12 PM
Your Cg version is missing the fixed function texture generation - note "TexGen ObjectLinear" in the fixed function shader. Which means the UV used by the projector is object-space vertex position. So, typing out of my head (might not work):
half2 uv = mul (_Projector, v.vertex).xy;
Also, if you need a perspective projector, you'll need to compute half4 UV in the vertex shader, and then use something like this in the pixel shader:
half4 col = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uv));
That works brilliantly! I'd have never made it without your help :) $$anonymous$$ostly because I indeed stupidly totally overlooked "TexGen ObjectLinear" :p
This is what I made of it, based on this answer:
Shader "Projector/$$anonymous$$ultiply"
{
Properties
{
_ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
_FalloffTex ("FallOff", 2D) = "white" { TexGen ObjectLinear }
}
Subshader
{
Tags { "RenderType"="Transparent-1" }
Pass
{
ZWrite Off
Fog { Color (1, 1, 1) }
AlphaTest Less 1
Color$$anonymous$$ask RGB
Blend DstColor Zero
Offset -1, -1
CGPROGRA$$anonymous$$
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_fog_exp2
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 uv_$$anonymous$$ain : TEXCOORD0;
float4 uv_Clip : TEXCOORD1;
};
sampler2D _ShadowTex;
sampler2D _FalloffTex;
float4x4 _Projector;
float4x4 _ProjectorClip;
v2f vert(appdata_tan v)
{
v2f o;
o.pos = mul (UNITY_$$anonymous$$ATRIX_$$anonymous$$VP, v.vertex);
o.uv_$$anonymous$$ain = mul (_Projector, v.vertex);
o.uv_Clip = mul (_ProjectorClip, v.vertex);
return o;
}
half4 frag (v2f i) : COLOR
{
half4 tex = tex2Dproj(_ShadowTex, i.uv_$$anonymous$$ain);
half4 falloff = tex2D(_FalloffTex, i.uv_Clip.xy);
tex = lerp(float4(1,1,1,1),tex,falloff.a);
return tex;
}
ENDCG
}
}
}
//Shader "Projector/$$anonymous$$ultiply" {
// Properties {
// _ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
// _FalloffTex ("FallOff", 2D) = "white" { TexGen ObjectLinear }
// }
//
// Subshader {
// Tags { "RenderType"="Transparent-1" }
// Pass {
// ZWrite Off
// Fog { Color (1, 1, 1) }
// AlphaTest Greater 0
// Color$$anonymous$$ask RGB
// Blend DstColor Zero
// Offset -1, -1
// SetTexture [_ShadowTex] {
// combine texture, ONE - texture
// $$anonymous$$atrix [_Projector]
// }
// SetTexture [_FalloffTex] {
// constantColor (1,1,1,0)
// combine previous lerp (texture) constant
// $$anonymous$$atrix [_ProjectorClip]
// }
// }
// }
//}
How could I translate this code into an additive projection? The only ones i've found were applying the texture to the whole terrain.
Hi Thyrandaal,
Firstly make sure to make the wrapmode to clamped on the texture. The shaders in Unity5 are found standard if you import Packages>Effects. Check the folders there itll have the Projectors (:
Your answer
Follow this Question
Related Questions
Modify Light Projector Shader to be Additive 0 Answers
Cutting "holes" using projector/shader? 0 Answers
Is projecting programmatically generated shapes using a projector possible? 0 Answers
Weird Lines When Using Projector Unity 2020.3 0 Answers
Projector + custom fragment shader = endless texture draw 2 Answers