Hi everyone, I read some tutorials about how to add shadow to vertex/fragment shader (e.g. adding-shadows-to-a-unity-vertexfragment-shader-in-7-easy-steps), but it seems not working at all. Please take a look, thanks a lot Code (CSharp): Shader "Custom/ToonCurved" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _QOffset ("Offset", Vector) = (0,0,0,0) _Dist ("Distance", Float) = 100.0 _Alpha ("Alpha", Range(0.0,1.0)) = 1.0 _OutlineColor ("Outline Color", Color) = (0,0,0,1) _Outline ("Outline width", Range (.002, 0.03)) = .005 _Color ("Main Color", Color) = (0.5,0.5,0.5,1) } SubShader { Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} Tags {"LightMode" = "ForwardBase"} LOD 100 Pass { Name "OUTLINE" Cull Front ZWrite On ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float4 _QOffset; float _Dist; float _Alpha; uniform float4 _MainTex_ST; uniform float _Outline; uniform float4 _OutlineColor; struct v2f { float4 pos : SV_POSITION; fixed4 color : COLOR; }; struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; }; v2f vert (appdata v) { v2f o; float4 vPos = mul (UNITY_MATRIX_MV, v.vertex); float zOff = vPos.z/_Dist; vPos += _QOffset*zOff*zOff; o.pos = mul (UNITY_MATRIX_P, vPos); float3 norm = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal)); float2 offset = TransformViewToProjection(norm.xy); o.pos.xy += offset * o.pos.z * _Outline; o.color = _OutlineColor; UNITY_TRANSFER_FOG(o,o.pos); return o; } half4 frag (v2f i) : COLOR { UNITY_APPLY_FOG(i.fogCoord, i.color); return i.color; } ENDCG } // Normal pass Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase #include "AutoLight.cginc" sampler2D _MainTex; float4 _QOffset; float _Dist; float _Alpha; uniform float4 _MainTex_ST; uniform float _Outline; uniform float4 _OutlineColor; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; fixed4 color : COLOR; LIGHTING_COORDS(0,1) }; v2f vert(appdata_base v) { v2f o; float4 vPos = mul(UNITY_MATRIX_MV, v.vertex); float zOff = vPos.z / _Dist; vPos += _QOffset*zOff*zOff; o.pos = mul(UNITY_MATRIX_P, vPos); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.color = _OutlineColor; UNITY_TRANSFER_FOG(o,o.pos); TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } fixed4 frag(v2f i) : COLOR { float attenuation = LIGHT_ATTENUATION(i); return tex2D(_MainTex, i.uv) * float4(1,1,1,_Alpha) * attenuation; } ENDCG } } Fallback "VertexLit" }
What is not working? What are you expecting it to do? Is it giving errors or just not doing what you want?
From your other thread... Could be multiple things: Tags {"LightMode"="ForwardBase"} is a Pass Tag and should be used in a pass, not the subshader. LIGHTING_COORDS(0,1) - you're using 0 for your uv coordinates. use 1 and 2 instead. Are shadows enabled? (see Quality Settings) Are you using a directional light? (other light sources require a different Light mode and #pragma multi_compile_fwdadd instead of #pragma multi_compile_fwdbase) Could be any or all of these things. You can probably also save yourself a lot of trouble by just using a surface shader with the outline pass added to get shadows.
Thanks for the replies! Now I got the shadow but the position is not match becoz the shader is curved. Should I modify the receive shadow part or any other suggestion? Code (CSharp): Shader "MyToon/Toon-Fragment" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Ramp ("Ramp Texture", 2D) = "white" {} _Outline ("Outline", Range(0,1)) = 0.1 _QOffset ("Offset", Vector) = (0,0,0,0) _Dist ("Distance", Float) = 100.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Pass { Tags { "LightMode"="ForwardBase" } Cull Front Lighting Off ZWrite On CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" float _Outline; float4 _QOffset; float _Dist; struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : POSITION; }; v2f vert (a2v v) { v2f o; float4 pos = mul( UNITY_MATRIX_MV, v.vertex); float zOff = pos.z/_Dist; pos += _QOffset*zOff*zOff; float3 normal = normalize(mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal)); normal.z = -0.5; pos = pos + float4(normalize(normal),0) * _Outline; o.pos = mul(UNITY_MATRIX_P, pos); return o; } float4 frag(v2f i) : COLOR { return float4(0, 0, 0, 1); } ENDCG } Pass { Tags { "LightMode"="ForwardBase" } Cull Back Lighting On CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" #include "Lighting.cginc" #include "AutoLight.cginc" #include "UnityShaderVariables.cginc" sampler2D _MainTex; sampler2D _Ramp; float4 _QOffset; float _Dist; float4 _MainTex_ST; float _Tooniness; struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct v2f { float4 pos : POSITION; float2 uv : TEXCOORD0; float3 normal : TEXCOORD1; LIGHTING_COORDS(2,3) }; v2f vert (a2v v) { v2f o; //Transform the vertex to projection space float4 vPos = mul(UNITY_MATRIX_MV, v.vertex); float zOff = vPos.z / _Dist; vPos += _QOffset*zOff*zOff; o.pos = mul(UNITY_MATRIX_P, vPos); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normal = mul((float3x3)_Object2World, SCALED_NORMAL); //Get the UV coordinates // pass lighting information to pixel shader TRANSFER_VERTEX_TO_FRAGMENT(o); return o; } float4 frag(v2f i) : COLOR { //Get the color of the pixel from the texture float4 c = tex2D (_MainTex, i.uv); //Merge the colours //Based on the ambient light float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz; //Work out this distance of the light float atten = LIGHT_ATTENUATION(i); //Angle to the light float diff = dot (normalize(i.normal), normalize(_WorldSpaceLightPos0.xyz)); diff = diff * 0.5 + 0.5; //Perform our toon light mapping diff = tex2D(_Ramp, float2(diff, 0.5)); //Update the colour lightColor += _LightColor0.rgb * (diff * atten); //Product the final color c.rgb = lightColor * c.rgb * 2; return c; } ENDCG } } FallBack "Diffuse" }
I am a shader noob, but hopefully what I am thinking is on the right track...atten is your light shadow information, if your diffuse texture actually has some sort of proces(curving, or pixel scroll or something), you can't just use diffuse * atten, that ofcourse will bend the shadows why not use some kind of additive operation.
The problem lies in the shadow pass. In your curved shader, you modify the vertex positions with a specific offset, but the shadowcaster/receiver passes are done with the normal vertex position (your vertex positions are not saved when altered in the vertex shader). Someone on this forum ha the same problem some time ago, I'm pretty sure you can find it somewhere if you search for it. In theory, you can add an adjusted shadowcaster/receiver pass with the adjusted vertex positions, but I think there were some issues with it, not sure.