Search Unity

Help with a basic shader to modify geometry with a sine wave.

Discussion in 'Shaders' started by BlobVanDam, Apr 9, 2011.

  1. BlobVanDam

    BlobVanDam

    Joined:
    Jun 28, 2010
    Posts:
    88
    I hate to ask for help, but I've been at this all day, and all I have gotten for my efforts is a blue screen of death. Methinks I might have taken a wrong turn at Albuquerque! :confused:

    Right now I've got a basic water shader (it's the standard reflective bump diffuse shader that I've modified to add alpha and tweak the reflections a bit), and I want to add a very basic sine wave to give the water plane some simple waves.

    The basic logic for this code is easy enough for me. I know the logic to modify the x and y coordinates of the vertex using a sin/cos wave using _Time as the phase to animate it.
    It's the basic structure of modifying this shader to add the ability to modify the vertices that has caused me some trouble. Could someone please help me?

    Just so people don't think I'm just a noob begging for a shortcut, here you can see I've got a purdy little platformer waiting for some fancy water :D


    Code (csharp):
    1. Shader "Custom/Water" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
    5.     _MainTex ("Base (RGB) RefStrength (A)", 2D) = "white" {}
    6.     _Cube ("Reflection Cubemap", Cube) = "_Skybox" { TexGen CubeReflect }
    7.     _BumpMap ("Normalmap", 2D) = "bump" {}
    8. }
    9.  
    10. SubShader {
    11.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    12.     Cull Off
    13.     LOD 300
    14.    
    15.  
    16. CGPROGRAM
    17. #pragma surface surf Lambert alpha
    18.  
    19. sampler2D _MainTex;
    20. sampler2D _BumpMap;
    21. samplerCUBE _Cube;
    22.  
    23. fixed4 _Color;
    24. fixed4 _ReflectColor;
    25.  
    26. struct Input {
    27.     float2 uv_MainTex;
    28.     float2 uv_BumpMap;
    29.     float3 worldRefl;
    30.     INTERNAL_DATA
    31. };
    32.  
    33. void surf (Input IN, inout SurfaceOutput o) {
    34.     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    35.     fixed4 c = tex * _Color;
    36.     o.Albedo = c.rgb;
    37.    
    38.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    39.    
    40.     float3 worldRefl = WorldReflectionVector (IN, o.Normal);
    41.     fixed4 reflcol = texCUBE (_Cube, worldRefl);
    42. //  reflcol *= 1.0;
    43.     o.Emission = reflcol.rgb * _ReflectColor.rgb;
    44.     o.Alpha = reflcol.a * 0.9;
    45. //  o.Alpha = 0.8;
    46. }
    47. ENDCG
    48. }
    49.  
    50. FallBack "Reflective/VertexLit"
    51. }
    52.  
    Any help is greatly appreciated! Thanks.
     
  2. ivkoni

    ivkoni

    Joined:
    Jan 26, 2009
    Posts:
    978
    to modify the vertices in local coords you would do:
    Code (csharp):
    1.  
    2. void vert (inout appdata_full v) {
    3.          // your logic here
    4.       }
    5.  
    as shown here
     
  3. BlobVanDam

    BlobVanDam

    Joined:
    Jun 28, 2010
    Posts:
    88
    Thanks for your help. That was the page I was looking at before, and haphazardly copy pasting when I BSOD'd my computer. But I've got it working now. Just a little nudge in the right direction like yours was all I needed to get started. :)

    This is what I've got now (a bit messy and needs fixing, but it works how I want at least). It doesn't look like the normals are being updated though. Do I need to do something extra, or am I mistaken?

    Code (csharp):
    1. void vert (inout appdata_full v) {
    2.     float phase = _Time * 20.0;
    3.     float offset = (v.vertex.x + (v.vertex.z * 0.2)) * 0.5;
    4.     v.vertex.y = sin(phase + offset) * 0.2;
    5. }
    6.  
     
    Last edited: Apr 9, 2011
    JustAnotherDude and PrimalCoder like this.
  4. BlobVanDam

    BlobVanDam

    Joined:
    Jun 28, 2010
    Posts:
    88
    I just noticed I have another problem. The problem is that the shader seems to be using local coordinates for the vertices instead of world space, so when I have meshes side by side, they don't line up, because the positions aren't calculated in world space.
    It would be fine if my water was one giant mesh, but it's broken up into squares every so often for performance reasons.

    Here's my full code-

    Code (csharp):
    1. Shader "Custom/Water" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
    5.     _MainTex ("Base (RGB) RefStrength (A)", 2D) = "white" {}
    6.     _Cube ("Reflection Cubemap", Cube) = "_Skybox" { TexGen CubeReflect }
    7.     _BumpMap ("Normalmap", 2D) = "bump" {}
    8. }
    9.  
    10. SubShader {
    11.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    12.     Cull Off
    13.     LOD 300
    14.    
    15.  
    16. CGPROGRAM
    17. #pragma surface surf Lambert alpha vertex:vert
    18.  
    19. sampler2D _MainTex;
    20. sampler2D _BumpMap;
    21. samplerCUBE _Cube;
    22.  
    23. fixed4 _Color;
    24. fixed4 _ReflectColor;
    25.  
    26. struct Input {
    27.     float2 uv_MainTex;
    28.     float2 uv_BumpMap;
    29.     float3 worldRefl;
    30.     INTERNAL_DATA
    31. };
    32.  
    33. void vert (inout appdata_full v) {
    34.     float phase = _Time * 20.0;
    35.     float offset = (v.vertex.x + (v.vertex.z * 0.2)) * 0.5;
    36.     v.vertex.y = sin(phase + offset) * 0.2;
    37. }
    38.  
    39. void surf (Input IN, inout SurfaceOutput o) {
    40.     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    41.     fixed4 c = tex * _Color;
    42.     o.Albedo = c.rgb;
    43.    
    44.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    45.    
    46.     float3 worldRefl = WorldReflectionVector (IN, o.Normal);
    47.     fixed4 reflcol = texCUBE (_Cube, worldRefl);
    48. //  reflcol *= 1.0;
    49.     o.Emission = reflcol.rgb * _ReflectColor.rgb;
    50.     o.Alpha = reflcol.a * 0.9;
    51. //  o.Alpha = 0.8;
    52. }
    53. ENDCG
    54. }
    55.  
    56. FallBack "Reflective/VertexLit"
    57. }
    58.  
     
  5. ivkoni

    ivkoni

    Joined:
    Jan 26, 2009
    Posts:
    978
    untested, but maybe something like this:
    Code (csharp):
    1.  
    2. void vert (inout appdata_full v) {
    3.     float phase = _Time * 20.0;
    4.                 float4 wpos = mul( _Object2World, v.vertex);
    5.     float offset = (wpos.x + (wpos.z * 0.2)) * 0.5;
    6.     wpos.y = sin(phase + offset) * 0.2;
    7.                 v.vertex = mul(_World2Object, wpos);
    8. }
    9.  
     
  6. BlobVanDam

    BlobVanDam

    Joined:
    Jun 28, 2010
    Posts:
    88
    Seems to work a charm! Thank you very much, sir. :D
     
  7. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    I'm curious to see the effect any chance of a video or web player?
     
  8. BlobVanDam

    BlobVanDam

    Joined:
    Jun 28, 2010
    Posts:
    88
    Ok, I'm bad at this. I want to completely disable the lighting, so it's just diffuse + the cubemap affected by the bump map. But I can't work out how to disable the lighting.
    I've tried working at it myself, but it looks like the lighting is automatic using a surf shader? I can see where it's set to Lambert, but I don't know if I can disable it there somehow. Setting "Lighting Off" apparently doesn't affect surf shaders either. All of the unlit shaders I've seen just use "pass", and not "surf", so it seems like a completely different type of shader, so I can't figure out how to adapt one to the other. So I'm not sure it this is a quick fix, or whether it's a rewrite of the basic elements.

    Code (csharp):
    1.  
    2. Shader "Custom/Water" {
    3. Properties {
    4.     _Color ("Main Color", Color) = (1,1,1,1)
    5.     _ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
    6.     _MainTex ("Base (RGB) RefStrength (A)", 2D) = "white" {}
    7.     _Cube ("Reflection Cubemap", Cube) = "_Skybox" { TexGen CubeReflect }
    8.     _BumpMap ("Normalmap", 2D) = "bump" {}
    9. }
    10.  
    11. SubShader {
    12.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    13.     Cull Off Lighting Off
    14.     LOD 300
    15.    
    16.  
    17. CGPROGRAM
    18. #pragma surface surf Lambert alpha vertex:vert
    19.  
    20. sampler2D _MainTex;
    21. sampler2D _BumpMap;
    22. samplerCUBE _Cube;
    23.  
    24. fixed4 _Color;
    25. fixed4 _ReflectColor;
    26.  
    27. struct Input {
    28.     float2 uv_MainTex;
    29.     float2 uv_BumpMap;
    30.     float3 worldRefl;
    31.     INTERNAL_DATA
    32. };
    33.  
    34. void vert (inout appdata_full v) {
    35.     float phase = _Time * 30.0;
    36.     float4 wpos = mul( _Object2World, v.vertex);
    37.     float offset = (wpos.x + (wpos.z * 0.2)) * 0.5;
    38.     wpos.y = sin(phase + offset) * 0.1;
    39.               v.vertex = mul(_World2Object, wpos);
    40. }
    41.  
    42. void surf (Input IN, inout SurfaceOutput o) {
    43.     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    44.     fixed4 c = tex * _Color;
    45.     o.Albedo = c.rgb;
    46.    
    47.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    48.    
    49.     float3 worldRefl = WorldReflectionVector (IN, o.Normal);
    50.     fixed4 reflcol = texCUBE (_Cube, worldRefl);
    51.     o.Emission = reflcol.rgb;
    52.     o.Alpha = 0.9;
    53. }
    54. ENDCG
    55. }
    56.  
    57. FallBack "Reflective/VertexLit"
    58. }
    59.