Home Unity

Unity 3D shader fake uv's

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:
  1. VertexOutput vert (VertexInput i)
  2. {
  3. VertexOutput VOUT;
  4. // create fake vertexes
  5. float4 v1 = i.vertex + float4(0.05,0.0,0.0,0.0) ; // X
  6. float4 v2 = i.vertex + float4(0.0,0.0,0.05,0.0) ; // Z
  7. float fakeUvCoordX = i.texcoord.x + 0.05;
  8. float fakeUvCoordY = i.texcoord.y + 0.05;
  9. // assign the displacement map to uv coords
  10. float4 disp = tex2Dlod(_Displacement, float4(i.texcoord.x + (_Time.x * _Speed), i.texcoord.y + (_Time.x * _Speed),0.0,0.0));
  11. float4 disp2 = tex2Dlod(_Displacement, float4(fakeUvCoordX + (_Time.x * _Speed), i.texcoord.y + (_Time.x * _Speed),0.0,0.0));
  12. float4 disp3 = tex2Dlod(_Displacement, float4(i.texcoord.x + (_Time.x * _Speed), fakeUvCoordY + (_Time.x * _Speed),0.0,0.0));
  13. // offset the main vert
  14. float4 newPos = i.vertex;
  15. newPos.y += _Scale * disp.y;
  16. // offset fake vertexes
  17. v1 += _Scale * disp2.y;
  18. v2 += _Scale * disp3.y;
  19. // calculate the new normal direction
  20. float3 newNor = cross(v2 - newPos, v1 - newPos);
  21. VOUT.posWorld = mul(_Object2World, newPos);
  22. VOUT.pos = mul(UNITY_MATRIX_MVP,newPos);
  23. VOUT.tex = i.texcoord;
  24. VOUT.normalWorld = normalize( mul(float4(newNor,0.0),_World2Object).xyz);
  25. VOUT.tangentWorld = normalize( mul(_Object2World,i.tangent).xyz);
  26. VOUT.binormalWorld = normalize( cross(VOUT.normalWorld, VOUT.tangentWorld) * i.tangent.w);
  27. return VOUT;
  28. }

Thanks in advance!

Replies

  • Lansiculus
    Okay, so I have fixed the problem by using world positions in stead of uv positions. Now you can scale the plane and it will apply the water shader based on world positions so it will just make the ocean area bigger. I made some pictures, and I am already pretty happy with the result, but I am in need for some help because I feel like the water isn't that pretty yet.

    I like this vieuw:

    2hnymg6.jpg

    But I hate this view:

    qxm9td.jpg

    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:
    1. Shader "Custom/NoobShader_04" {
    2. Properties {
    3. _Color ("Color", Color) = (0.21,0.51,0.58,1)
    4. _Displacement ("Displacement Map", 2D) = "white" {}
    5. _Scale ("Wave Scale", float) = 0.05
    6. _Speed ("Speed", float) = 1
    7. _Normal ("Normal Map", 2D) = "bump" {}
    8. _Bumpiness ("Bumpiness", float) = 1
    9. _NormalSpeed ("NormalSpeed", float) = 1.2
    10. _Cube ("Cube Map", cube) = ""{}
    11. _CubeStrength ("Cube Map Strength", float) = 0.3
    12. _SpecColor ("Specular Color", Color) = (0.61,0.61,0.61,1)
    13. _Shininess ("Shininess", float) = 100
    14. }
    15. SubShader {
    16. Pass{
    17. Tags { "LightMode" = "ForwardBase"}
    18. CGPROGRAM
    19. #pragma vertex vert
    20. #pragma fragment frag
    21. float4 _Color;
    22. sampler2D _Displacement;
    23. sampler2D _Normal;
    24. samplerCUBE _Cube;
    25. float4 _SpecColor;
    26. float _Shininess;
    27. float _Bumpiness;
    28. float _CubeStrength;
    29. float _Scale;
    30. float _Speed;
    31. float _NormalSpeed;
    32. float4 _LightColor0;
    33. struct VertexOutput
    34. {
    35. float4 pos : SV_POSITION;
    36. float4 posWorld : TEXCOORD1;
    37. float4 tex : TEXCOORD0;
    38. float3 normalWorld : TEXCOORD2;
    39. float3 tangentWorld : TEXCOORD3;
    40. float3 binormalWorld : TEXCOORD4;
    41. };
    42. struct VertexInput
    43. {
    44. float4 vertex : POSITION;
    45. float3 normal : NORMAL;
    46. float4 texcoord : TEXCOORD0;
    47. float4 tangent : TANGENT;
    48. };
    49. struct FragmentOutput
    50. {
    51. float4 color : COLOR;
    52. };
    53.  
    54. VertexOutput vert (VertexInput i)
    55. {
    56. VertexOutput VOUT;
    57. // put the vert in world space
    58. float4 newVert = mul(_Object2World,i.vertex);
    59. // create fake vertexes
    60. float4 v1 = newVert + float4(0.05,0.0,0.0,0.0) ; // X
    61. float4 v2 = newVert + float4(0.0,0.0,0.05,0.0) ; // Z
    62. // assign the displacement map to uv coords
    63. float4 disp = tex2Dlod(_Displacement, float4(newVert.x + (_Time.x * _Speed), newVert.z + (_Time.x * _Speed),0.0,0.0));
    64. float4 disp2 = tex2Dlod(_Displacement, float4(v1.x + (_Time.x * _Speed), newVert.z + (_Time.x * _Speed),0.0,0.0));
    65. float4 disp3 = tex2Dlod(_Displacement, float4(newVert.x + (_Time.x * _Speed), v2.z + (_Time.x * _Speed),0.0,0.0));
    66. // offset the main vert
    67. newVert.y += _Scale * disp.y;
    68. // offset fake vertexes
    69. v1 += _Scale * disp2.y;
    70. v2 += _Scale * disp3.y;
    71.  
    72. // calculate the new normal direction
    73. float3 newNor = cross(v2 - newVert, v1 - newVert);
    74. // return world position of the vert for frag calculations
    75. VOUT.posWorld = newVert;
    76. // set the vert back in object space
    77. float4 vertObjectSpace = mul(newVert,_World2Object);
    78. // apply unity mvp matrix to the vert
    79. VOUT.pos = mul(UNITY_MATRIX_MVP,vertObjectSpace);
    80.  
    81. //return the tex coords for frag calculations
    82. VOUT.tex = i.texcoord;
    83. // return normal, tangents, and binormal information for frag calculations
    84. VOUT.normalWorld = normalize( mul(float4(newNor,0.0),_World2Object).xyz);
    85. VOUT.tangentWorld = normalize( mul(_Object2World,i.tangent).xyz);
    86. VOUT.binormalWorld = normalize( cross(VOUT.normalWorld, VOUT.tangentWorld) * i.tangent.w);
    87. return VOUT;
    88. }
    89. FragmentOutput frag(VertexOutput v)
    90. {
    91. FragmentOutput FOUT;
    92. // Get the light and vieuw direction
    93. float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    94. float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - v.posWorld.xyz);
    95. // tex coords for the normal map
    96. float4 texN = tex2D(_Normal,float4(v.posWorld.x + (_Time.x * _NormalSpeed),v.posWorld.z + (_Time.x * _NormalSpeed) ,0.0,0.0));
    97. float3 localCoords = float3(2.0 * texN.ag - float2(1.0,1.0), 0.0);
    98. localCoords.z = _Bumpiness;
    99. float3x3 local2WorldTranspose = float3x3(
    100. v.tangentWorld,
    101. v.binormalWorld,
    102. v.normalWorld
    103. );
    104. float3 normalDirection = normalize(mul(localCoords,local2WorldTranspose));
    105. // Calculate the cube map reflection
    106. float3 reflectDir = reflect(viewDirection,v.normalWorld);
    107. float4 cubeRef = texCUBE(_Cube, reflectDir);
    108. float3 diffuseReflection = _LightColor0 * saturate(dot(normalDirection,lightDirection));
    109. float3 specularReflection = _SpecColor.xyz * pow(saturate(dot(reflect(-lightDirection, normalDirection), viewDirection)), _Shininess);
    110. float3 lightFinal = (cubeRef * _CubeStrength) * diffuseReflection + specularReflection;
    111. FOUT.color = UNITY_LIGHTMODEL_AMBIENT + max( 0.0, dot(v.normalWorld, lightDirection)) * (_Color + float4(lightFinal,0.0));
    112. return FOUT;
    113. }
    114. ENDCG
    115. }
    116. }
    117. FallBack "Diffuse"
    118. }
  • Eric Chadwick
    The main difference I see is the specular is invisible in the 2nd shot. If you are using a Directional light, rotate it so the light rays bounce off the water and into the camera. That's how specular reflection works.
Sign In or Register to comment.