I’ve got problem with writing depth in fragment program. All fragment programs I saw for ShaderLab write only color, but it seems to be possible to output depth too (as I see in HLSL/Cg forums). I’ve been digging the forum for hours but I still got no idea how to do it. Was trying shader from attachment, but compiler throws such error:
The texture you write to in the fragment program is only a color buffer so writing depth will not work I guess.
Unity 3 renders the depth and normal buffer in a different pass (given you enable the camera to render a depth texture) than the color, but you can potentially access this one.
Thank you, fast and competent reply as usual by dreamora :).
I’ve just analysed compiled version of simple surface shader. Indeed - as far as I see there is only color buffer written. I will have to sort things another way aquiring information from depth texture. The problem is - I want this shader (grass shader) to work on terrains which are usually queued as “geometry-100”. So I’d need to write my material later as it will be alpha masked “transparent”. Are there any known drawbacks when shifting terrain material later in render queue ? Dangerous side effects to be aware of ?
Just a note for those wanting to write to depth in D3D9 shader and getting the ‘D3D shader assembly failed with: (36): error X2022: scalar registers cannot be masked’ error.
Although this bug still remains, the problem is with the cg compiler, something that has been known since 2008 (according to this old cg thread on nvidia forums). So either its never been fixed or Unity is using a pretty old version of cg?
Thankfully it appears from initial testing this issue can be solved by changing the compiled shader code from
mov oDepth.z, r0.z
to
mov oDepth, r0.z
I.e. removing the .z mask, which since its on a scalar doesn’t work and hence the error.
To change the compiled code simply create your shader normally, ignoring the error. Once finished select the shader and click ‘open compiled shader’ button in the inspector. Now copy the entire contents of the compiled shader and paste it into a new shader file. Look through the code and replace the lines causing the bug as above, then save the shader.
It does mean that your original shaderlab/cg shader will never compile or be usable in d3d9 environment so don’t use it or include it in your builds! However your fixed ‘compiled’ version should work fine. At least it does for me in the editor and as a window build.
Shader warning in ‘TestShader’: register type 9 not supported in AGAL (compiling for flash) at line 5
Anyway - it’s big step further and could be useful, however I dropped the idea using this feature completelt for performance reasons (writing into depth buffer is told to be slow, but honestly I’ve never tested it since I couldn’t do it well in Unity).
Good point about Mobile ( where writing to depth buffer is not supported as far as I understand) and Flash.
As for performance, seems fine to me (Windows). I guess it could be slower than normal rendering since the gpu has no idea what depth you are going to set, so normal optimisations (e.g. early outs) can’t be done. However its not likely that you’d use this frequently for many objects, more likely as in my case, you’d want to use it once per frame to populate the depth buffer with specific values.
Depth output from a pixel shader works fine for me in DX9 mode (after upgrading to 4.2 to fix the mask issue described above), but if I put the renderer into DX11 mode the depth output seems to be ignored - I just get the regular geometry depth…
I’m having the same problem with my shader when trying to implement a logarithmic depth buffer (‘Use Direct3D 11’ enabled in Player settings). Using the log calc gives the same output as depth = 0 and depth = 1. Like it ignores the value I set (or more likely I’m doing it wrong!). This is on PC by the way (Win7 x64)
Finally I found the solution - simply we can’t use old semantics with DX11 (DEPTH) - we need to use (SV_Depth as pixel function output and SV_Target instead of COLOR, in case of new deferred we’ve got indexed SV_Target0 to SV_Target3 semantics for MRT output).
Hi Tom,
could you quickly give an example please ? new to shaders and a bit confused.
tried this and couldn’t make it work, nothing in zbuffer.
thanks a lot
Victor
in vertex function use COMPUTE_EYEDEPTH(vertexFunctionOutputStruct.eyeDepth);
the eyeDepth value is passed to fragment function as i.eyeDepth above. You also need to pass world position (posWorld) to frag function. With rayLength variable you can offset resultant depth back and forth in world units. When rayDepth=0 we’ve got not modified depth. Such formula works fine in my shaders, although determining rayDepth (depth offset in world units) may be very tricky when you try to make computations in, for example, tangent space.
hi Tom
your hint looks fine for perspective correction( wich i was also looking for, i’m thankful)
i’m really noobish, but what i don’t get is where and how do you write to zbuffer.
i will use your code as i am trying fo get a very simple fog working (thus persp correction);
what i would really love is write a damn depth to the z buffer so i could write my semi-transparent shader pixels to zbuffer.
i think i must have a look at unity foliage code or so.
thanks very much
victor