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.
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.
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?
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.
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.
Simple vertex Fetch shader Code (csharp): Shader "ncp/VertexFetch/VertexFetch_FX" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _HeightMap ("HeightMap", 2D) = "white" {} _HeightMod ("HeightMod", float) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert vertex:VertexFetchFunct noforwardadd nolightmap // Specific Pragma Settings // Texture fetch relies on SM3 and for opengl to be built using glsl #pragma target 3.0 #pragma glsl // Optional Pragma Settings: // #pragma only_renderers d3d9 // Only use if not for opengl and disable #pragma glsl above. // #pragma debug // Useful for debug log of surface shaders compiles. float _HeightMod; sampler2D _MainTex; sampler2D _HeightMap; struct Input { float2 uv_MainTex; }; void VertexFetchFunct (inout appdata_full v) { float nativeHeight = tex2Dlod( _HeightMap, float4(v.texcoord.xy, 0, 0)).r ; v.vertex.y = v.vertex.y*(nativeHeight*_HeightMod); } void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
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.
I'm also trying to get results back from computeshaders without the help of rendertexture. It's theorically possible with buffer.getData. I asked for help here : http://forum.unity3d.com/threads/165501-ComputeBuffer.GetData?p=1131551#post1131551 Any idea ?