Hi, I am writing a shader where I apply a displacement map on a surface. I am using a plane for the surface. The problem is that I want to turn the normals so that they face away from the surface after I apply the displacement map. So I created fake vertexes so I can calculate the normals, but the problem is that they dont have uv's, and without uv's I can't figure out what height I need to place them because the displacement map desides that. How can I fake uv's for my fake vertexes so I can use the displacement map to give them height? This is my vertex function:
VertexOutput vert (VertexInput i)
{
VertexOutput VOUT;
// create fake vertexes
float4 v1 = i.vertex + float4(0.05,0.0,0.0,0.0) ; // X
float4 v2 = i.vertex + float4(0.0,0.0,0.05,0.0) ; // Z
float fakeUvCoordX = i.texcoord.x + 0.05;
float fakeUvCoordY = i.texcoord.y + 0.05;
// assign the displacement map to uv coords
float4 disp = tex2Dlod(_Displacement, float4(i.texcoord.x + (_Time.x * _Speed), i.texcoord.y + (_Time.x * _Speed),0.0,0.0));
float4 disp2 = tex2Dlod(_Displacement, float4(fakeUvCoordX + (_Time.x * _Speed), i.texcoord.y + (_Time.x * _Speed),0.0,0.0));
float4 disp3 = tex2Dlod(_Displacement, float4(i.texcoord.x + (_Time.x * _Speed), fakeUvCoordY + (_Time.x * _Speed),0.0,0.0));
// offset the main vert
float4 newPos = i.vertex;
newPos.y += _Scale * disp.y;
// offset fake vertexes
v1 += _Scale * disp2.y;
v2 += _Scale * disp3.y;
// calculate the new normal direction
float3 newNor = cross(v2 - newPos, v1 - newPos);
VOUT.posWorld = mul(_Object2World, newPos);
VOUT.pos = mul(UNITY_MATRIX_MVP,newPos);
VOUT.tex = i.texcoord;
VOUT.normalWorld = normalize( mul(float4(newNor,0.0),_World2Object).xyz);
VOUT.tangentWorld = normalize( mul(_Object2World,i.tangent).xyz);
VOUT.binormalWorld = normalize( cross(VOUT.normalWorld, VOUT.tangentWorld) * i.tangent.w);
return VOUT;
}
Thanks in advance!
Replies
I like this vieuw:
But I hate this view:
Are there any tips you guys can give me? I think it has somthing to do with the reflection. Keep in mind I am not aiming to make a super realistic water shader, it just has to look good.
This is my code:
Shader "Custom/NoobShader_04" { Properties { _Color ("Color", Color) = (0.21,0.51,0.58,1) _Displacement ("Displacement Map", 2D) = "white" {} _Scale ("Wave Scale", float) = 0.05 _Speed ("Speed", float) = 1 _Normal ("Normal Map", 2D) = "bump" {} _Bumpiness ("Bumpiness", float) = 1 _NormalSpeed ("NormalSpeed", float) = 1.2 _Cube ("Cube Map", cube) = ""{} _CubeStrength ("Cube Map Strength", float) = 0.3 _SpecColor ("Specular Color", Color) = (0.61,0.61,0.61,1) _Shininess ("Shininess", float) = 100 } SubShader { Pass{ Tags { "LightMode" = "ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag float4 _Color; sampler2D _Displacement; sampler2D _Normal; samplerCUBE _Cube; float4 _SpecColor; float _Shininess; float _Bumpiness; float _CubeStrength; float _Scale; float _Speed; float _NormalSpeed; float4 _LightColor0; struct VertexOutput { float4 pos : SV_POSITION; float4 posWorld : TEXCOORD1; float4 tex : TEXCOORD0; float3 normalWorld : TEXCOORD2; float3 tangentWorld : TEXCOORD3; float3 binormalWorld : TEXCOORD4; }; struct VertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 tangent : TANGENT; }; struct FragmentOutput { float4 color : COLOR; }; VertexOutput vert (VertexInput i) { VertexOutput VOUT; // put the vert in world space float4 newVert = mul(_Object2World,i.vertex); // create fake vertexes float4 v1 = newVert + float4(0.05,0.0,0.0,0.0) ; // X float4 v2 = newVert + float4(0.0,0.0,0.05,0.0) ; // Z // assign the displacement map to uv coords float4 disp = tex2Dlod(_Displacement, float4(newVert.x + (_Time.x * _Speed), newVert.z + (_Time.x * _Speed),0.0,0.0)); float4 disp2 = tex2Dlod(_Displacement, float4(v1.x + (_Time.x * _Speed), newVert.z + (_Time.x * _Speed),0.0,0.0)); float4 disp3 = tex2Dlod(_Displacement, float4(newVert.x + (_Time.x * _Speed), v2.z + (_Time.x * _Speed),0.0,0.0)); // offset the main vert newVert.y += _Scale * disp.y; // offset fake vertexes v1 += _Scale * disp2.y; v2 += _Scale * disp3.y; // calculate the new normal direction float3 newNor = cross(v2 - newVert, v1 - newVert); // return world position of the vert for frag calculations VOUT.posWorld = newVert; // set the vert back in object space float4 vertObjectSpace = mul(newVert,_World2Object); // apply unity mvp matrix to the vert VOUT.pos = mul(UNITY_MATRIX_MVP,vertObjectSpace); //return the tex coords for frag calculations VOUT.tex = i.texcoord; // return normal, tangents, and binormal information for frag calculations VOUT.normalWorld = normalize( mul(float4(newNor,0.0),_World2Object).xyz); VOUT.tangentWorld = normalize( mul(_Object2World,i.tangent).xyz); VOUT.binormalWorld = normalize( cross(VOUT.normalWorld, VOUT.tangentWorld) * i.tangent.w); return VOUT; } FragmentOutput frag(VertexOutput v) { FragmentOutput FOUT; // Get the light and vieuw direction float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - v.posWorld.xyz); // tex coords for the normal map float4 texN = tex2D(_Normal,float4(v.posWorld.x + (_Time.x * _NormalSpeed),v.posWorld.z + (_Time.x * _NormalSpeed) ,0.0,0.0)); float3 localCoords = float3(2.0 * texN.ag - float2(1.0,1.0), 0.0); localCoords.z = _Bumpiness; float3x3 local2WorldTranspose = float3x3( v.tangentWorld, v.binormalWorld, v.normalWorld ); float3 normalDirection = normalize(mul(localCoords,local2WorldTranspose)); // Calculate the cube map reflection float3 reflectDir = reflect(viewDirection,v.normalWorld); float4 cubeRef = texCUBE(_Cube, reflectDir); float3 diffuseReflection = _LightColor0 * saturate(dot(normalDirection,lightDirection)); float3 specularReflection = _SpecColor.xyz * pow(saturate(dot(reflect(-lightDirection, normalDirection), viewDirection)), _Shininess); float3 lightFinal = (cubeRef * _CubeStrength) * diffuseReflection + specularReflection; FOUT.color = UNITY_LIGHTMODEL_AMBIENT + max( 0.0, dot(v.normalWorld, lightDirection)) * (_Color + float4(lightFinal,0.0)); return FOUT; } ENDCG } } FallBack "Diffuse" }