Search Unity

Compute Shaders - How To?

Discussion in 'Shaders' started by Pedro Afonso, Dec 19, 2012.

  1. Pedro Afonso

    Pedro Afonso

    Joined:
    Mar 13, 2011
    Posts:
    240
    After a quick look at the Unity Docs regarding the new DX11 Compute Shaders in Unity, I decided to ask for some clarification here on the forum.
    Basically, what I'm trying to do is to create a DX11 Compute Shader for water, much like the nvidia sample, however I'm having troubles to understand how to integrate it into unity!

    What I want to do:
    - Have water with reflection based(maybe vertex shader?)
    - Have the compute shader to calculate the fft values
    - Pass the fft values to the render

    My problem is how to call functions inside the shaders, how to pass the values from the shaders to the render and how to animate the ocean plane according to the values of the calculations?

    I know this may sound stupid, but I'm a noob in what matters to shaders so any help is welcome!
    Thank you.
     
  2. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    You can do this without compute shaders. In my water simulation, I pass data from shader to shader by using RenderTextures as both input and output (Although, you might not want to write to the texture you're also reading from). From what I've learned so far about Compute shaders is that you actually have the option to either use Textures as input, or custom data structures. But I haven't learned enough about using DirectCompute in Unity yet, so I can't help you with it yet.

    I'll be learning more about it during the coming days though, because of the DX11 contest, so perhaps I could help you better later.
     
  3. Pedro Afonso

    Pedro Afonso

    Joined:
    Mar 13, 2011
    Posts:
    240
    I guess that maybe by writing the output to the buffer by using the ComputeBuffer.GetData I would be able to get the values from the Compute Shader, but again I'm not an expert and do not know if this might be the right way to do so.

    I was thinking of using the Compute Shader to calculate the FFT algorithm and then get those values and animate the water vertices in the vertex shader, do you think this is right?
     
  4. RC-1290

    RC-1290

    Joined:
    Jul 2, 2012
    Posts:
    639
    Hmmm, I'm guessing it might be easier to output to a RenderTexture, in stead of using the compute buffer, since the data will have to be processed by a regular shader, which is used to working with textures. I also think that will be faster, since the data you need in the vertex shader will already be in GPU memory. While if you read from the compute buffer, it'll be written to system memory, then you have to structure it like a texture, for the shader to use, and then sent back to GPU memory.

    Keep in mind that reading a texture in the vertex shader (also known as VTF, Vertex Texture Fetch), which you probably need to do to displace the vertices, isn't supported by all D3D feature levels. I just learned about shader levels 15 minutes ago, so I can't help you with that yet.

    Luckily the error messages for shaders in Unity 4 seem to a lot more informative than before, especially when it comes to the ones given out by the HLSL compiler, so don't be afraid to experiment a little.
     
  5. Pedro Afonso

    Pedro Afonso

    Joined:
    Mar 13, 2011
    Posts:
    240
    I think that's what I'll try to do.
    I'll try to output to a RenderTexture and then use that in the vertex shader to change the vertices!

    Still not quite sure how to do it, but I guess with a little research I can do so.
    Thank you.
     
  6. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Simple vertex Fetch shader

    Code (csharp):
    1. Shader "ncp/VertexFetch/VertexFetch_FX"
    2. {  
    3.     Properties
    4.     {
    5.         _MainTex    ("Base (RGB)", 2D)      = "white" {}
    6.         _HeightMap  ("HeightMap", 2D)       = "white" {}       
    7.         _HeightMod  ("HeightMod", float)    = 1.0
    8.     }
    9.    
    10.     SubShader
    11.     {
    12.         Tags { "RenderType"="Opaque" }
    13.         LOD 200
    14.        
    15.         CGPROGRAM
    16.             #pragma surface surf Lambert vertex:VertexFetchFunct noforwardadd nolightmap   
    17.        
    18.             // Specific Pragma Settings
    19.             // Texture fetch relies on SM3 and for opengl to be built using glsl
    20.             #pragma target 3.0
    21.             #pragma glsl
    22.  
    23.             // Optional Pragma Settings:
    24.             // #pragma only_renderers d3d9          // Only use if not for opengl and disable #pragma glsl above.
    25.             // #pragma debug                        // Useful for debug log of surface shaders compiles.
    26.            
    27.             float       _HeightMod;
    28.             sampler2D   _MainTex;
    29.             sampler2D   _HeightMap;
    30.  
    31.             struct Input
    32.             {
    33.                 float2 uv_MainTex;
    34.             };
    35.  
    36.             void VertexFetchFunct (inout appdata_full   v)
    37.             {  
    38.                 float nativeHeight = tex2Dlod( _HeightMap, float4(v.texcoord.xy, 0, 0)).r ;
    39.                 v.vertex.y = v.vertex.y*(nativeHeight*_HeightMod);           
    40.             }          
    41.            
    42.             void surf (Input IN, inout SurfaceOutput o)
    43.             {
    44.                 half4 c = tex2D (_MainTex, IN.uv_MainTex);
    45.                 o.Albedo = c.rgb;
    46.                 o.Alpha = c.a;
    47.             }
    48.         ENDCG
    49.     }  
    50.     FallBack "Diffuse"
    51. }
    52.  
     
    Last edited: Dec 21, 2012
  7. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    However I would have thought for simulating and rendering your ocean you'd want to keep this all in dx11 features. Should be no need to go back through using vertex fetch with textures as you should be able to just pass the computeShader output directly.

    Aras has put up a very useful Unity project with examples of dx11 https://dl.dropbox.com/u/1119248/DX11Examples-4.0.0b7.zip.

    If the link doesn't work, try the link from this thread.

    It will take a bit of time to study, but it features, tessellation, mesh Topology, computeShaders, geometry shaders etc. Should have everything you need, but without previous dx11 experience it will take time to digest all the examples and follow the code. Its a great resource but its not a step by step tutorial.
     
  8. sepion

    sepion

    Joined:
    Nov 7, 2012
    Posts:
    12