I’m trying to write a Surface Shader which can read the Vertex Normals of the Mesh, as well as the NormalMap passed in, however I haven’t found a way to do it, nor any documentation.
basically, here are my doubts:
Shader "Test/MyTest" {
Properties {
_NormalMap ("NormalMap", 2D) = "bump" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Custom vertex:vert
void vert( inout appdata_full v )
{
// I can read v.normal here.. everything ok so far
}
half LightningCustom( SurfaceOutput s, half3 lightDir, half3 vewDir, half atten )
{
// here s.Normal refer's only to the NormalMap (if texture != null) or the interpolated Vertex Normal (if texture == null )
// but not both... uhmm...
}
struct Input
{
float2 uv_NormalMap;
// can I declare here the "VertexNormal" also?... if so how?..
}
sampler2D _NormalMap;
void surf( Input IN, inout SurfaceOutput o )
{
UnpackNormal( text2D( _NormalMap, IN.uv_NormalMap) ); // I can read the NormalMap.. everything ok...
// but... how can I read here the interpolated "VertexNormal"?.. should I declare it as part of "Input"?.. how?
}
}
}
If you read the surface shader documentation you can see the tutorial that tells you how to get the vertex normals into a surface shader (hint: it’s third from the bottom on that page).
You might want to remove the abs() function though.
if I make that multiply of .rgb * dN it just sends an error, if I just keep the .rgb alone it compiles and works without problems… I really can’t figure out why is this happening.
Material doesn’t have a texture property ‘_MainTex’
Material doesn’t have a texture property ‘_NormalMap’
(actually, this is the same error I get most of the time when something is wrong, no matter what the error was)
if you like you can copy-paste the code I wrote above (actually I’d appreciate it, I don’t want to find out 3 weeks later that my pc was crazy), it doesn’t do much, you only need a mesh, and it’s diffuse normal map.
bump, i’m also having a similar problem…
i need the mesh normal BEFORE applying normal map…
tried to do what i’ve read in this thread…
i can read the “before” normals but , then no way to apply the normal map after that (and changed the code several times)
thanks a lot for any help
edit : even removed everythin related to worldnormal and the normal map won’t apply anymore
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float3 worldNormal; INTERNAL_DATA
};
void surf (Input i, inout SurfaceOutputStandardSpecular o) {
fixed4 tex = tex2D (_MainTex, i.uv_MainTex);
o.Albedo = _MainColor * tex.rgb; // main albedo
o.Normal = UnpackNormal (tex2D (_BumpMap, i.uv_BumpMap));
o.Specular = 0;
o.Smoothness = 0;
o.Alpha = 1;
///////////////
// detects if face is pointing up
half faceUp = WorldNormalVector ( i , float3( 0, 0, 1 ) ).y;
For anyone still having trouble with this, I found a workaround.
Here is what I did:
Make shader as usual, but do not put worldNormal in the input structure.
Where you would read/write to o.Normal, comment it out, and read from it like: “IN.nrml” (replace IN with whatever you named your input) Make sure to comment out the IN.nrml part as well.
Save, then select the shader asset in unity.
Click the “show generated code” button in the inspector.
For every copy of your surface shader in the compiled shader, go to the input structure and add “float3 nrml;”
Uncomment the IN.nrml parts and o.Normal parts.
Do ctrl+f to find all places the compiled shader has “normalWorldVertex = IN.worldNormal;” Below that line, add this line: surfIN.nrml = o.Normal;
Save the modified shader to someplace in your unity project.
This workaround can be a real pain though if you have a lot of shader variants.
Hope it helps.