Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How do you make Custom Shaders write to GBuffers?

Discussion in 'Shaders' started by kingofmyworld324, May 22, 2016.

  1. kingofmyworld324

    kingofmyworld324

    Joined:
    Sep 24, 2013
    Posts:
    10
    I'm trying to use the specular data in BuiltinRenderTextureType.GBuffer1 in an image effect but objects that use shaders with custom lighting models don't appear in the texture. Only objects that use BlinnPhong appear to be included.

    The documentation says this:
    My question has to do with what I underlined in the documentation. How do you actually write to the buffer in your own custom shaders?

    Thanks!
     
    ModLunar likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,248
    Standard, blinn phong, and lambert work with deferred, mainly because the later two are converted into the standard shader when deferred is enabled. Specifically the default deferred rendering path can only render using the standard lighting model, so Lambert is approximated with a standard lighting model with no specular and blinn phong is approximated by roughly converting the specular power to the standards glossiness.

    Look at the built in shader source and look for SV_Target3 to find places where it's writing to the gbuffers using a shader pass with a "lightmode" = "deferred"

    One frustration Ive had is if you have a shader with a deferred pass and a forward pass there's no way to get Unity to render both at the same time. Instead shaders with a deferred pass ignore all forward passes if the deferred rendering path is enabled. If no deferred pass exists it renders opaque materials into the gbuffers using the shadow caster pass which has no normals which tends to cause problems with post process effects.

    Anyways, if you actually want to write stuff into the gbuffers and still use a custom shader you'll either need to make those shaders conform to the standard lighting model, or render those objects twice, as two completely separate objects and materials/shaders.
     
    Last edited: May 23, 2016
  3. kingofmyworld324

    kingofmyworld324

    Joined:
    Sep 24, 2013
    Posts:
    10
    So basically you can write to the buffers in a custom shader as long as you don't use a custom lighting model, right?
    I tried using the finalgbuffer function to write to the buffers but it had no effect (I'm assuming its because of the same reason even though the finalcolor function does work).

    I'm not willing to convert my shaders to standard lighting because I need my own lighting models and I would rather not have two materials for each object.

    I guess my last question is: is it possible to make my own buffer or texture and write to it from within my custom shaders?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,248
    So you can render using a replacement shader pass, and I think you can setup a second camera that has multiple render targets that you can write to like the deferred setup, but these don't mix well with the existing rendering paths with out a lot of work. Using replacement shaders is basically the same thing as having two shaders, but it's more expensive.

    I think some of the stuff they're working on for 5.4 or 5.5 will make this easier, but I have no idea when or really if they'll ever release those changes.
     
  5. Tudor

    Tudor

    Joined:
    Sep 27, 2012
    Posts:
    150
    Bgolus, I've been trying to write a custom shader that writes to multiple render targets. If I understand it correctly, I should just be able to have a "fixed4 frag(v2f I) : SV_Target2 { }" to for example write to the normal gbuffer? That doesn't do anything though.

    Am I to understand that you can only write to MRTs in unity if you use the "lightmode" = "deferred" tag? If I try to add that tag, the emission just goes black and still I don't register any of my SV_Target2 changes...
     
    Last edited: May 26, 2016
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,248
    I've never tried to render to a single render target when multiple render targets are enabled, so it might just end up writing black to everything, I have no idea. And yes, you can only write to the built in deferred render path MRTs using the deferred lightmode, otherwise it'll get rendered during the forward pass which no longer has multiple render targets. You should be able to do completely custom MRTs by assigning your own render targets to a camera and shaders, but that probably doesn't help you.

    If you want to render to a specific gbuffer target you should looked at the decals thread from a few weeks ago.
    http://forum.unity3d.com/threads/ho...added-unity-5-2-finalgbuffer-modifier.356644/

    They're writing these with surface shaders, but you can look at the generated vertex fragment shader to see what it's actually doing.
     
    Tudor likes this.