- Home /
Problem with Normal Maps
Hey,
So I'm working on a procedural terrain and Standard Shader simply doesn't work for me. Instead I have created my own shader (evaluated from standard surface shader) that doesn't require UV and It works great with textures, however, when I try to add normal maps (more accurately I add "o.Normal = stuff") everything breaks (e.g. object becomes perfect black) so how do I add normal map support?
Here is shader in the albedo state:
Shader "Custom/Terrain" {
Properties {
_TopTexture ("Top Texture", 2D) = "white" {}
_TopNormal ("Top NormalMap", 2D) = "bump" {}
_TopTexScale ("Top Texture Scale", float) = 0
_Glossiness ("Smoothness", Range(0,1)) = 0.0
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
struct Input {
float3 worldPos;
float3 worldNormal; INTERNAL_DATA
};
half _Glossiness;
half _Metallic;
float _TopTexScale;
sampler2D _TopTexture;
sampler2D _TopNormal;
void surf (Input IN, inout SurfaceOutputStandard o) {
float3 scaledWorldPos = IN.worldPos / _TopTexScale;
float3 blendAxes = abs(IN.worldNormal);
blendAxes /= blendAxes.x + blendAxes.y + blendAxes.z;
float3 xProjection = tex2D(_TopTexture, scaledWorldPos.yz) * blendAxes.x;
float3 yProjection = tex2D(_TopTexture, scaledWorldPos.xz) * blendAxes.y;
float3 zProjection = tex2D(_TopTexture, scaledWorldPos.xy) * blendAxes.z;
o.Albedo = xProjection + yProjection + zProjection;
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
}
ENDCG
}
FallBack "Diffuse"
}
I don't really understand what you are trying to achieve with your shader... Normally for normal mapping you should have a normal map UV in your Input structure and then you simply do something like
o.Normal = text2D(_TopNormal, input.normalUV);
$$anonymous$$aybe you can have a look here and start with the provided example of normal mapping shader and try to make the effect you want. Step by step you could isolate the problem that renders your object completely black.
Hope it helps ;)
Well, this helped atleast a bit, It seems like #pragma surface surf Standard fullforwardshadows
doesn't like normal maps, but is there any documentation on what I can choose? #pragma surface surf Lambert
that appears in examples seems kinda outdated...
Yes the documentation on pragma tag is here
EDIT : Did you find the solution to your problem ?
Answer by Namey5 · Apr 24, 2017 at 10:29 AM
There are some problems with using triplanar texturing for normal maps, although from memory the shader I created for this works perfectly fine;
Shader "Custom/Triplanar" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_Scale ("Scale", Float) = 2.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows vertex:vert
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
sampler2D _BumpMap;
struct Input {
float3 coords;
float3 normal;
};
half _Glossiness;
half _Metallic;
half _Scale;
fixed4 _Color;
void vert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT (Input, o);
o.coords = mul (unity_ObjectToWorld, v.vertex) * _Scale;
o.normal = mul ((float3x3)unity_ObjectToWorld, v.normal);
}
void surf (Input IN, inout SurfaceOutputStandard o) {
float3 blend = abs (IN.normal);
blend /= dot (blend, 1.0);
fixed4 bx = tex2D (_BumpMap, IN.coords.zy);
fixed4 bz = tex2D (_BumpMap, IN.coords.xy);
fixed4 by = tex2D (_BumpMap, IN.coords.xz);
fixed4 b = bx * blend.x + bz * blend.z + by * blend.y;
o.Normal = UnpackNormal (b);
// Albedo comes from a texture tinted by color
fixed4 cx = tex2D (_MainTex, IN.coords.zy);
fixed4 cz = tex2D (_MainTex, IN.coords.xy);
fixed4 cy = tex2D (_MainTex, IN.coords.xz);
fixed4 c = cx * blend.x + cz * blend.z + cy * blend.y;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
I think it's down to using the default surface shader normal value. From memory you have to pass your own values in order for it to work, because the default values are overwritten when you write to o.Normal.
Your answer
Follow this Question
Related Questions
Surface Shader apply normal map to object normal without pluggin it into o.Normal 1 Answer
Referencing the current pixel's world coordinates in the SURF block of a shader 1 Answer
How to add "fat" feature to the Standard.shader? 1 Answer
How to add Bump/Normal Map to surface shader? (CG) 0 Answers
How to blend color when using shadergraph wich uses normals? 0 Answers