Hello I have this shader that I'm trying to port into Unity, I need some help getting it to work, I don't know why its not working though. No errors are given so I tried to restart Unity and nothing really happened. The compiler says now though that "OUT" not being completely initialized but I don't see how. More Info: http://graphics.cs.brown.edu/games/SteepParallax/ http://www.chandlerprall.com/2011/09/steep-parallax-shader/ Code (csharp): Shader "Advanced/Steep Parrallax Occ Mapping" { Properties { _Color ("Color", Color) = (0.5,0.5,0.5,1) _MainTex("Base (RGB)", 2D) = "white" {} _NormalMap("Normal Map", 2D) = "bump" {} _Scale ("Normalmap Bumpiness", Range(0.0, 2.0)) = 0.04 _Shininess("Shininess", Range(0.0, 5.0)) = 1.5 _Shadow("Shadow On/Off - Set to 1 to Enable", Range(0.0, 1.0)) = 1.0 } SubShader { Pass { Tags {"RenderType" = "Opaque"} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 4.0 //Samplers uniform sampler2D _MainTex; uniform sampler2D _NormalMap; //Float4's uniform float4 _Color; uniform float4 _SpecColor; //Floats uniform float _Scale; uniform float _Shininess; uniform float _Shadow; //Pre-defined uniform float4 _LightColor0; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; //Output struct struct vertexOutput { float4 pos : SV_POSITION; float4 col : COLOR; float4 tex : TEXCOORD0; float3 posTangent : TEXCOORD1; float3 camTangent : TEXCOORD2; float3 lightTangent : TEXCOORD3; float3 normalDir : TEXCOORD4; float3 tangentDir : TEXCOORD5; float3 binormalDir : TEXCOORD6; }; //Vertex shader vertexOutput vert(vertexInput IN) { vertexOutput OUT; OUT.tex = IN.texcoord; OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex); float3 camPos = normalize(_WorldSpaceCameraPos.xyz - OUT.posTangent.xyz); // Find normalize the plane's normal, tangent, and binormal vectors OUT.normalDir = normalize(IN.normal); OUT.tangentDir = normalize(IN.tangent).xyz; OUT.binormalDir = normalize(cross(OUT.normalDir, OUT.tangentDir) * IN.tangent.w ); // Convert vertice, camera, and light vector positions into tangent space float3x3 tangentSpaceConverter = float3x3(OUT.tangentDir, OUT.binormalDir, OUT.normalDir); OUT.posTangent = mul(OUT.pos.xyz, tangentSpaceConverter); OUT.camTangent = mul(camPos, tangentSpaceConverter); OUT.lightTangent = mul(normalize(_WorldSpaceLightPos0.xyz), tangentSpaceConverter); return OUT; } //Pixel shader float4 frag(vertexOutput i) : COLOR { //Steep Parallax float bumpScale = _Scale; //Normalize the other tangent space vectors float3 viewVector = normalize(i.camTangent - i.posTangent); float3 lightVector = normalize(i.lightTangent - i.posTangent); float3 tsE = normalize(i.camTangent); const float numSteps = 30.0f; // How many steps the UV ray tracing should take float height = 1.0; float step = 1.0 / numSteps; float2 offset = float2(0.0, 0.0); float4 NormalMap = tex2D(_NormalMap, offset); float2 delta = float2(-tsE.x, -tsE.y) * bumpScale / (tsE.z * numSteps); // find UV offset for (float i = 0.0f; i < numSteps; i++) { if (NormalMap.a < height) { height -= step; offset += delta; NormalMap = tex2D(_NormalMap, offset); } else { break; } } float3 DiffuseTex = tex2D(_MainTex, offset).rgb; float3 NormalTex = tex2D(_NormalMap, offset).rgb * 2.0 - 1.0f; //N*L float NdotL = max(0.0f, dot(NormalTex.rgb, lightVector.xyz ) ); //Calculate this pixel's lighting float nxDir = max(0.0, dot(NormalTex.rgb, lightVector.xyz)); float specularPower = 0.0; float specularColor = _SpecColor; if(nxDir != 0.0) { float3 halfVector = normalize(lightVector + viewVector); float nxHalf = max(0.0, dot(NormalTex, halfVector)); specularPower = pow(nxHalf, _Shininess); } float3 specular = specularColor * specularPower; float3 pixel_color = UNITY_LIGHTMODEL_AMBIENT + specular + (_Color.rgb * float3(nxDir,nxDir,nxDir) * DiffuseTex); //Find shadowing if enabled if (_Shadow == 1.0) { float2 shadow_offset = offset; float3 tsH = normalize(lightVector + tsE); float selfShadow = 0.0; if (NdotL > 0.0) { const float numShadowSteps = 10.0; step = 1.0 / numShadowSteps; delta = float2(lightVector.x, lightVector.y) * bumpScale / (numShadowSteps * lightVector.z); height = NormalMap.a + step * 0.1; for (float i = 0.0; i < numShadowSteps; i++) { if (NormalMap.a < height height < 1.0) { height += step; shadow_offset += delta; NormalMap = tex2D(_NormalMap, shadow_offset); } else { break; } } selfShadow = float(NormalMap.a < height); } if (selfShadow == 0.0) { pixel_color *= 0.5; } } //if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) return float4(pixel_color, 1.0); } ENDCG } } //Fallbacks //Fallback "VertexLit" }
It's right... You forgot to set some value to OUT.col. (Or remove it altogether... it seems like you're not using it in the fragment shader.)
I've knocked it down to just one error (got rid of the implicit casting from floatx to floaty) but I'm not exactly sure why it won't compile, I've look at my other shaders and they work just fine not pulling all information into the fragment shader. Kinda stuck now Current Code: Code (csharp): Shader "Advanced/Steep Parrallax Occ Mapping" { Properties { _Color ("Color", Color) = (0.5,0.5,0.5,1) _MainTex("Base (RGB)", 2D) = "white" {} _NormalMap("Normal Map", 2D) = "bump" {} _Scale ("Normalmap Bumpiness", Range(0.0, 2.0)) = 0.04 _Shininess("Shininess", Range(0.0, 5.0)) = 1.5 _Shadow("Shadow On/Off - Set to 1 to Enable", Range(0.0, 1.0)) = 1.0 } SubShader { Pass { //Tags {"RenderType" = "Opaque"} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 4.0 //Samplers uniform sampler2D _MainTex; uniform sampler2D _NormalMap; //Float4's uniform float4 _Color; uniform float4 _SpecColor; //Floats uniform float _Scale; uniform float _Shininess; uniform float _Shadow; //Pre-defined uniform float4 _LightColor0; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; //Output struct struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float3 posTangent : TEXCOORD1; float3 camTangent : TEXCOORD2; float3 lightTangent : TEXCOORD3; float3 normalDir : TEXCOORD4; float3 tangentDir : TEXCOORD5; float3 binormalDir : TEXCOORD6; }; //Vertex shader vertexOutput vert(vertexInput IN) { vertexOutput OUT; OUT.tex = IN.texcoord; OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex); float3 camPos = normalize(_WorldSpaceCameraPos.xyz - OUT.posTangent.xyz); // Find normalize the plane's normal, tangent, and binormal vectors OUT.normalDir = normalize(IN.normal); OUT.tangentDir = normalize(IN.tangent).xyz; OUT.binormalDir = normalize(cross(OUT.normalDir, OUT.tangentDir) * IN.tangent.w ); // Convert vertice, camera, and light vector positions into tangent space float3x3 tangentSpaceConverter = float3x3(OUT.tangentDir, OUT.binormalDir, OUT.normalDir); OUT.posTangent = mul(OUT.pos.xyz, tangentSpaceConverter); OUT.camTangent = mul(camPos, tangentSpaceConverter); OUT.lightTangent = mul(normalize(_WorldSpaceLightPos0.xyz), tangentSpaceConverter); return OUT; } //Pixel shader float4 frag(vertexOutput i) : COLOR { //Steep Parallax float bumpScale = _Scale; //Normalize the other tangent space vectors float3 viewVector = normalize(i.camTangent - i.posTangent); float3 lightVector = normalize(i.lightTangent - i.posTangent); float3 tsE = normalize(i.camTangent); const float numSteps = 30.0f; // How many steps the UV ray tracing should take float height = 1.0; float step = 1.0 / numSteps; float2 offset = i.tex.xy; float4 NormalMap = tex2D(_NormalMap, offset); float2 delta = float2(-tsE.x, -tsE.y) * bumpScale / (tsE.z * numSteps); // find UV offset for (float i = 0.0f; i < numSteps; i++) { if (NormalMap.a < height) { height -= step; offset += delta; NormalMap = tex2D(_NormalMap, offset); } else { break; } } float3 DiffuseTex = tex2D(_MainTex, offset).rgb; float3 NormalTex = tex2D(_NormalMap, offset).rgb * 2.0 - 1.0f; //N*L float NdotL = max(0.0f, dot(NormalTex.rgb, lightVector.xyz ) ); //Calculate this pixel's lighting float nxDir = max(0.0, dot(NormalTex.rgb, lightVector.xyz)); float specularPower = 0.0; //float specularColor = _SpecColor; if(nxDir != 0.0) { float3 halfVector = normalize(lightVector + viewVector); float nxHalf = max(0.0, dot(NormalTex, halfVector)); specularPower = pow(nxHalf, _Shininess); } float3 specular = specularPower; float3 pixel_color = UNITY_LIGHTMODEL_AMBIENT.xyz + specular + (_Color.rgb * float3(nxDir,nxDir,nxDir) * DiffuseTex); //Find shadowing if enabled if (_Shadow == 1.0) { float2 shadow_offset = offset; float3 tsH = normalize(lightVector + tsE); float selfShadow = 0.0; if (NdotL > 0.0) { const float numShadowSteps = 10.0; step = 1.0 / numShadowSteps; delta = float2(lightVector.x, lightVector.y) * bumpScale / (numShadowSteps * lightVector.z); height = NormalMap.a + step * 0.1; for (float i = 0.0; i < numShadowSteps; i++) { if (NormalMap.a < height height < 1.0) { height += step; shadow_offset += delta; NormalMap = tex2D(_NormalMap, shadow_offset); } else { break; } } selfShadow = float(NormalMap.a < height); } if (selfShadow == 0.0) { pixel_color *= 0.5; } } //if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) return float4(pixel_color, 1.0); } ENDCG } } //Fallbacks //Fallback "VertexLit" }
DX11 is enabled (because I'm using SM4.0) My GPU is a GTX 460 which is a DX11 SM5.0 graphics card The compiled shader doesn't tell me anything either.
Pretty sure that out is a reserved word in cg. Have you try just using a different variable name instead. It shouldn't be an issue since you cased the spelling of "OUT" differently but it is something to try.
camPos in your vertex shader is using an uninitialized value. No idea about the first error though... SM4.0 should work with DX11 "out" is a reserved keyword, but "OUT" isn't... I'm using it myself.
It compiles now but I don't get anything close too Steep Parallax Mapping, what am I supposed to return exactly gl_FragColor is like return right but how do I return the right value to get the right effect? Current code : Code (csharp): Shader "Advanced/Steep Parrallax Occ Mapping" { Properties { _Color ("Color", Color) = (0.5,0.5,0.5,1) _MainTex("Base (RGB)", 2D) = "white" {} _NormalMap("Normal Map", 2D) = "bump" {} _Scale ("Normalmap Bumpiness", Range(0.0, 2.0)) = 0.04 _Shininess("Shininess", Range(0.0, 5.0)) = 1.5 _Shadow("Shadow On/Off - Set to 1 to Enable", Range(0.0, 1.0)) = 1.0 } SubShader { Pass { Tags {"RenderType" = "Opaque"} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 4.0 //Samplers uniform sampler2D _MainTex; uniform sampler2D _NormalMap; //Float4's uniform float4 _Color; uniform float4 _SpecColor; //Floats uniform float _Scale; uniform float _Shininess; uniform float _Shadow; //Pre-defined uniform float4 _LightColor0; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; //Output struct struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float3 posTangent : TEXCOORD1; float3 camTangent : TEXCOORD2; float3 lightTangent : TEXCOORD3; float3 normalDir : TEXCOORD4; float3 tangentDir : TEXCOORD5; float3 binormalDir : TEXCOORD6; }; //Vertex shader vertexOutput vert(vertexInput IN) { vertexOutput OUT; OUT.tex = IN.texcoord; OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex); float3 camPos = normalize(_WorldSpaceCameraPos.xyz); // Find normalize the plane's normal, tangent, and binormal vectors OUT.normalDir = normalize(IN.normal); OUT.tangentDir = normalize(IN.tangent).xyz; OUT.binormalDir = normalize(cross(OUT.normalDir, OUT.tangentDir) * IN.tangent.w ); // Convert vertice, camera, and light vector positions into tangent space float3x3 tangentSpaceConverter = float3x3(OUT.tangentDir, OUT.binormalDir, OUT.normalDir); OUT.posTangent = mul(OUT.pos.xyz, tangentSpaceConverter); OUT.camTangent = mul(camPos, tangentSpaceConverter); OUT.lightTangent = mul(normalize(_WorldSpaceLightPos0.xyz), tangentSpaceConverter); return OUT; } //Pixel shader float4 frag(vertexOutput i) : COLOR { //Steep Parallax float bumpScale = _Scale; //Normalize the other tangent space vectors float3 viewVector = normalize(i.camTangent - i.posTangent); float3 lightVector = normalize(i.lightTangent - i.posTangent); float3 tsE = normalize(i.camTangent); const float numSteps = 40.0f; // How many steps the UV ray tracing should take float height = 1.0; float step = 1.0 / numSteps; float2 offset = i.tex.xy; float4 NormalMap = tex2D(_NormalMap, offset); float2 delta = float2(-tsE.x, -tsE.y) * bumpScale / (tsE.z * numSteps); // find UV offset for (float i = 0.0f; i < numSteps; i++) { if (NormalMap.a < height) { height -= step; offset += delta; NormalMap = tex2D(_NormalMap, offset); } else { break; } } float3 DiffuseTex = tex2D(_MainTex, offset).rgb; float3 NormalTex = tex2D(_NormalMap, offset).rgb * 2.0 - 1.0f; //N*L float NdotL = max(0.0f, dot(NormalTex.rgb, lightVector.xyz ) ); //Calculate this pixel's lighting float nxDir = max(0.0, dot(NormalTex.rgb, lightVector.xyz)); float specularPower = 0.0; //float specularColor = _SpecColor; if(nxDir != 0.0) { float3 halfVector = normalize(lightVector + viewVector); float nxHalf = max(0.0, dot(NormalTex, halfVector)); specularPower = pow(nxHalf, _Shininess); } float3 specular = specularPower; float3 pixel_color = UNITY_LIGHTMODEL_AMBIENT.xyz + specular + float3(nxDir,nxDir,nxDir); //Find shadowing if enabled if (_Shadow == 1.0) { float2 shadow_offset = offset; float3 tsH = normalize(lightVector + tsE); float selfShadow = 0.0; if (NdotL > 0.0) { const float numShadowSteps = 10.0; step = 1.0 / numShadowSteps; delta = float2(lightVector.x, lightVector.y) * bumpScale / (numShadowSteps * lightVector.z); height = NormalMap.a + step * 0.1; for (float i = 0.0; i < numShadowSteps; i++) { if (NormalMap.a < height height < 1.0) { height += step; shadow_offset += delta; NormalMap = tex2D(_NormalMap, shadow_offset); } else { break; } } selfShadow = float(NormalMap.a < height); } if (selfShadow == 0.0) { pixel_color *= 0.5; } } //if (offset.x < 0.0 || offset.x > 1.0 || offset.y < 0.0 || offset.y > 1.0) return float4(pixel_color, 1.0); } ENDCG } } //Fallbacks //Fallback "VertexLit" } Picture Example: http://postimg.org/image/9rk4cjesx/full/
You are returning the correct thing, but there can be problems elsewhere. Porting stuff like that is not easy... I suggest debugging it part by part, checking whether each variable contains what it should. If you copy-pasted the fragment shader, there's probably something wrong with the inputs, so I'd start there. From a brief look, I can see a few bugs: OUT.pos does NOT contain world space position. But you shouldn't work with world space at all! The normals, tangents and vertex positions are all in object space, but you're mixing them with world space camera and light positions. So, use IN.vertex for object space position, IN.normal and IN.tangent like you do now. You could also replace camera and light positions with _ObjectSpaceCameraPos and _ObjectSpaceLightPos0, buuut stuff is complicated. You are using directional light, which passes a direction instead of position to _ObjectSpaceLightPos0. Unity already has a fancy function to help you out with that, ObjSpaceLightDir(v). You can also safely move the vector computation to the vertex shader. To save you some frustration, it should look like this: Code (csharp): //Output struct struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float3 camTangent : TEXCOORD1; float3 viewVector : TEXCOORD2; float3 lightVector : TEXCOORD3; float3 normalDir : TEXCOORD4; float3 tangentDir : TEXCOORD5; float3 binormalDir : TEXCOORD6; }; //Vertex shader vertexOutput vert(vertexInput IN) { vertexOutput OUT; OUT.tex = IN.texcoord; OUT.pos = mul(UNITY_MATRIX_MVP, IN.vertex); // Find normalize the plane's normal, tangent, and binormal vectors OUT.normalDir = normalize(IN.normal); OUT.tangentDir = normalize(IN.tangent).xyz; OUT.binormalDir = normalize(cross(OUT.normalDir, OUT.tangentDir) * IN.tangent.w ); // Convert vertice, camera, and light vector positions into tangent space float3x3 tangentSpaceConverter = float3x3(OUT.tangentDir, OUT.binormalDir, OUT.normalDir); OUT.camTangent = mul(tangentSpaceConverter, _ObjectSpaceCameraPos); OUT.viewVector = mul(tangentSpaceConverter, ObjSpaceViewDir(IN.vertex)); OUT.lightVector = mul(tangentSpaceConverter, ObjSpaceLightDir(IN.vertex)); return OUT; } //Pixel shader float4 frag(vertexOutput i) : COLOR { //Steep Parallax float bumpScale = _Scale; //Normalize the other tangent space vectors float3 viewVector = normalize(i.viewVector); float3 lightVector = normalize(i.lightVector); float3 tsE = normalize(i.camTangent); ...
Ahh ok thanks! I can't believe I didn't know about that stuff, there should be much more documentation on shaders, and I will see what I can do. I completely missed this page : http://docs.unity3d.com/Documentation/Components/SL-BuiltinIncludes.html