# G-Buffer modifing with Command Buffer

**URL:** https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443
**Category:** Shaders & Materials
**Created:** [November 20, 2016, 12:24pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443 "2016-11-20T12:24:46Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [November 20, 2016, 12:24pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/1 "2016-11-20T12:24:46Z")

</div>

Hi guys.

I want to modify G-Buffer Albedo, but it seems not working like I’m expected, and I can’t get why it works like that.  
I started to simplify my code, and now I have a minimal code for reproducing a problem.  
My simple code is just clearing G-Buffer Albedo to yellow color.  
The core of the code:

```csharp
cmdBuffer.SetRenderTarget(BuiltinRenderTextureType.GBuffer0);
cmdBuffer.ClearRenderTarget(false, true, Color.yellow);
cam.AddCommandBuffer(CameraEvent.BeforeLighting, cmdBuffer);

```

In my example, I have a cube with an albedo texture of white dots.  
When I turn on my script, I expect to see just yellow cube without any dots because I overwrite albedo to yellow. There is no information in G-Buffer about dots.  
But what I see, there is a yellow cube with dots. How is it possible? Is there another one pass after lighting pass or what?

Cube without the script influence:

 ![2857914--209048--cube_white.png](https://europe1.discourse-cdn.com/unity/original/4X/8/3/4/83452afe87192c6bbca0e9dde263373813a1a74b.png)

Cube with the script:

 ![2857914--209049--cube_yellow.png](https://europe1.discourse-cdn.com/unity/original/4X/3/e/4/3e42120a772bff237a024c29e40a5ac985807239.png)

Albedo channel looks like yellow as it should be:

 ![2857914--209050--albedo.png](https://europe1.discourse-cdn.com/unity/original/3X/d/2/d26be95d94fb277e55ea4e668bec9580945b155c.png)

Could somebody help me to understand why it works like that?

I’ve attached the project that you could see by your own.  
I use Unity 5.4.3f1.

[2857914–209051–AlbedoIssue.zip](https://discussions.unity.com/uploads/short-url/a367GAS7CiASWlSFCQ3AI0b3dto.zip) (29.9 KB)

---

<div class="post-metadata">

### Author: ![Michal\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/michal_1/32/473494_2.png) [@Michal\_1](https://discussions.unity.com/u/Michal_1)
#### Post date: [November 20, 2016, 1:10pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/2 "2016-11-20T13:10:42Z")

</div>

Well, albedo color is also used to compute ambient lighting. Ambient lighting is computed before individual lights are processed. That’s likely what is happening there. Try to set ambient color to black (Window-\>Lighting-\>Ambient Source). Or you can try to clear the lighting buffer (GBuffer 3 according to docs). It is logarithmically encoded, so you want to clear it to **white** to get rid of ambient lighting (and lightmaps/light probes etc).

---

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [November 20, 2016, 2:41pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/3 "2016-11-20T14:41:50Z")

</div>

Thank you. You are right. It’s ambient. Both solutions are working. The second solution (clear GBuffer3) works only if a camera is not HDR.  
I want to have deferred decals that overwrite albedo in some places. I do want ambient color is working too. Black ambient is not a solution in this case. How should I handle this?

---

<div class="post-metadata">

### Author: ![Michal\_1](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/michal_1/32/473494_2.png) [@Michal\_1](https://discussions.unity.com/u/Michal_1)
#### Post date: [November 20, 2016, 10:12pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/4 "2016-11-20T22:12:22Z")

</div>

I’m not very familiar with the way deferred rendering is implemented in Unity. At least not with the details. But generally speaking you have to override **all** relevant parts of the gbuffer when rendering deferred decals. That means you shouldn’t modify only albedo but also the lighting buffer, normals, specular, roughness etc. Depending on your specific needs. Lighting buffer in Unity contains ambient light, lightmaps, emission etc. Download Standard shader source code from [here](https://unity3d.com/get-unity/download/archive)if you want to know what exactly it contains and how Unity computes it.  
I would also used CameraEvent.AfterGBuffer to render your decals, so that all subsequent passes are using final gbuffer.

---

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [November 21, 2016, 11:47am UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/5 "2016-11-21T11:47:11Z")

</div>

Thanks for helping, Michal.  
I will try to look inside Unity shaders to figure out how it works. Maybe Render Doc could help me also in understanding the render pipeline.

It would be great to hear some words from Unity Tech. graphics engineers. 🙂

---

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [November 26, 2016, 2:32pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/6 "2016-11-26T14:32:03Z")

</div>

I looked at built-in shaders and debugged it with RenderDoc.  
There is fragDeferred shader in UnityStandardCore.cginc.

```csharp
    half3 color = UNITY_BRDF_PBS (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, gi.light, gi.indirect).rgb;
    color += UNITY_BRDF_GI (s.diffColor, s.specColor, s.oneMinusReflectivity, s.oneMinusRoughness, s.normalWorld, -s.eyeVec, occlusion, gi);

    #ifdef _EMISSION
        color += Emission (i.tex.xy);
    #endif

    #ifndef UNITY_HDR_ON
        color.rgb = exp2(-color.rgb);
    #endif

    outDiffuse = half4(s.diffColor, occlusion);
    outSpecSmoothness = half4(s.specColor, s.oneMinusRoughness);
    outNormal = half4(s.normalWorld*0.5+0.5,1);
    outEmission = half4(color, 1);

```

It doesn’t matter what kind of Camera you use. HDR or not you still have Emission RT. Just little bit different information contains in this RT.  
If we look inside of BRDF1\_Unity\_PBS:

```csharp
    half3 color = diffColor * (gi.diffuse + light.color * diffuseTerm)
                    + specularTerm * light.color * FresnelTerm (specColor, lh)
                    + surfaceReduction * gi.specular * FresnelLerp (specColor, grazingTerm, nv);

    return half4(color, 1);

```

It means we should do something like this for the “yellow” pass to have correct data in RT3. Also, we have UNITY\_BRDF\_GI…  
It’s just craziness to repeat the same things before lighting pass.  
Unfortunately, I don’t see a good way to have deferred decals without big render modifications. ☹  
Of course, If we want to close eyes on correctness, we could have it.

---

<div class="post-metadata">

### Author: ![bgolus](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/bgolus/32/391570_2.png) [@bgolus](https://discussions.unity.com/u/bgolus)
#### Post date: [November 27, 2016, 6:30am UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/7 "2016-11-27T06:30:11Z")

</div>

There’s some discussion on this topic here:

> **[How do I write a normal decal shader using a newly added (Unity 5.2)...](https://discussions.unity.com/threads/how-do-i-write-a-normal-decal-shader-using-a-newly-added-unity-5-2-finalgbuffer-modifier.356644/)**
>
> What I’m trying to do should be pretty simple: a decal shader that overlays it’s own normals on top of normals already existing in the deferred GBuffer, instead of overwriting everything on pixels covered by decal faces. It was said to me that what I...

And posted about on Unity’s official blog here:  
[https://blogs.unity3d.com/2015/02/06/extending-unity-5-rendering-pipeline-command-buffers/](https://blogs.unity3d.com/2015/02/06/extending-unity-5-rendering-pipeline-command-buffers/)

It’s come up a few other times as well on the forum. I suggest searching around.

---

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [November 27, 2016, 8:35pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/8 "2016-11-27T20:35:06Z")

</div>

Thanks. I’ll read that thread.  
Deferred Decals from the Unity blog have the same problem as I have. It’s hard to see the problem there because it’s a simple scene and no textures on objects.

---

<div class="post-metadata">

### Author: ![bgolus](https://dub1.discourse-cdn.com/unity/user_avatar/discussions.unity.com/bgolus/32/391570_2.png) [@bgolus](https://discussions.unity.com/u/bgolus)
#### Post date: [November 29, 2016, 10:00pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/9 "2016-11-29T22:00:20Z")

</div>

So what you’re missing is in that bit of code you posted earlier, and you followed a bit of a red herring following the code as you missed a snippet of code a few lines earlier in that function.

```csharp
    // no analytic lights in this pass
    UnityLight dummyLight = DummyLight (s.normalWorld);
    half atten = 1;

```

The result of setting that dummy light, which has a color of zero, is the call to UNITY\_BRDF\_PBS basically does nothing in most cases and just returns black. So why include it at all? Because in the case of directional specular lightmaps it actually decodes a light direction and color and passes that to the BRDF.  
The next line, UNITY\_BRDF\_GI, then does any additional ambient lighting, like realtime precomputed GI or just light probes depending on the object and your lighting settings.

So the final result is the value “color”, and thus “outEmission” is actually the output of the albedo & specular from the ambient or baked lighting. After the gbuffers have been filled the render target for outEmission remains as the main target for the deferred lights.

So, when you apply your yellow deferred decal, the spots remain as they were already rendered out with the ambient lighting pre-applied to the render texture that ends up being what is rendered to the screen.

You might want to try the frame debugger to see what’s happening better as the scene view dropdown isn’t giving you the “full picture” as it were.

---

<div class="post-metadata">

### Author: ![Eksin](https://avatars.discourse-cdn.com/v4/letter/e/a88e4f/32.png) [@Eksin](https://discussions.unity.com/u/Eksin)
#### Post date: [December 7, 2016, 9:42pm UTC](https://discussions.unity.com/t/g-buffer-modifing-with-command-buffer/646443/10 "2016-12-07T21:42:51Z")

</div>

I didn’t notice a dummy light. Thank you for pointing out. It was very helpful.  
I will continue to investigate this when I have some free time. 🙂
