Post processing effects on unity (CommandBuffer)

Good afternoon.
I would like help to make a post processing system.
I don’t understand much about commandBuffer so I’m not getting it to work.

I need to do the following.
Render the first effect on the camera image and the next one on top of the first image and then play the second effect image on the camera.

using UnityEngine;
using UnityEngine.Rendering;
using System.Collections;
using System.Collections.Generic;
public partial class PostProcessingStack
{

    const string bufferName = "PostProcessingEffects";
    int fxSourceId = Shader.PropertyToID("_PostFXSource");
    CommandBuffer buffer = new CommandBuffer
    {
        name = bufferName
    };

    ScriptableRenderContext context;

    Camera camera;

    public bool IsActive = true;

    public void Setup(ScriptableRenderContext context, Camera camera)
    {
        this.context = context;
        this.camera = camera;
    }

    public void PostProcessingDrawing(PostProcessingCamera PPC, int sourceId)
    {
        //Drawing(sourceId, to, material, pass);
        createStack(PPC, sourceId);
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }

    void Drawing(RenderTargetIdentifier from, RenderTargetIdentifier to, Material material, int pass)
    {
        //BuiltinRenderTextureType.CameraTarget
        buffer.SetGlobalTexture(fxSourceId, from);
        buffer.SetRenderTarget(to, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
        buffer.DrawProcedural(Matrix4x4.identity, material, pass,MeshTopology.Triangles, 3);
      
        buffer.ReleaseTemporaryRT(fxSourceId);
    }
    void createStack(PostProcessingCamera PPC, int sourceId)
    {

        int source = sourceId;
        int toID = (int)BuiltinRenderTextureType.CameraTarget;

        buffer.BeginSample("ProcessingEffects");
        List<Effect> effects = PPC.getMaterialList();
        for (int i = 0;i < effects.Count;i++ )
        {

                for (int pass = 0; pass < effects[i].passNumber; pass++)
                {

                buffer.GetTemporaryRT(source, camera.pixelWidth, camera.pixelHeight, 32, FilterMode.Bilinear, RenderTextureFormat.DefaultHDR);
                if (i ==0 && pass == 0)
                    Drawing(source, BuiltinRenderTextureType.CameraTarget, effects[i].material, pass);
                else
                    Drawing(source, BuiltinRenderTextureType.CameraTarget, effects[i].material, pass);

                    // buffer.Blit(source, toID);
                    source = source + 1;
                    toID += 1;
                    if (PPC.ConsoleDebug)
                        Debug.Log(effects[i].material.name +" | Pass: " + pass);
                }
            //}//
            //PPC.resetMaterialList();
        }

        buffer.EndSample("ProcessingEffects");
    }


}

Render effect:

void createStack(PostProcessingCamera PPC, int sourceId)
    {

        int source = sourceId;
        int toID = (int)BuiltinRenderTextureType.CameraTarget;

        buffer.BeginSample("ProcessingEffects");
        List<Effect> effects = PPC.getMaterialList();
        for (int i = 0;i < effects.Count;i++ )
        {

                for (int pass = 0; pass < effects[i].passNumber; pass++)
                {

                buffer.GetTemporaryRT(source, camera.pixelWidth, camera.pixelHeight, 32, FilterMode.Bilinear, RenderTextureFormat.DefaultHDR);
                if (i ==0 && pass == 0)
                    Drawing(source, BuiltinRenderTextureType.CameraTarget, effects[i].material, pass);
                else
                    Drawing(source, BuiltinRenderTextureType.CameraTarget, effects[i].material, pass);

                    // buffer.Blit(source, toID);
                    source = source + 1;
                    toID += 1;
                    if (PPC.ConsoleDebug)
                        Debug.Log(effects[i].material.name +" | Pass: " + pass);
                }
            //}//
            //PPC.resetMaterialList();
        }

        buffer.EndSample("ProcessingEffects");
    }

Draw the effect:

void Drawing(RenderTargetIdentifier from, RenderTargetIdentifier to, Material material, int pass)
    {
        //BuiltinRenderTextureType.CameraTarget
        buffer.SetGlobalTexture(fxSourceId, from);
        buffer.SetRenderTarget(to, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
        buffer.DrawProcedural(Matrix4x4.identity, material, pass,MeshTopology.Triangles, 3);
      
        buffer.ReleaseTemporaryRT(fxSourceId);
    }

You should really ask this on the Unity Forums, it is off-topic here and I would think you are much more likely to get an answer there as well.
However, consider what you are asking; you’ve basically given us a bunch of code (which is incomplete as PostProcessingStack is a partial class, so there are parts of it elsewhere), told us its doesn’t work (almost never a problem description that allows giving useful advice), and asked “can you fix it for me” (I’m paraphrasing and exaggerating for effect, of course). You may get lucky and someone gives you a useful answer, but take a look at the forum posting guidelines, there is advice in there on how to ask questions that have high probability of getting answered.

All that being said, are you aware of Unity’s Post-Processing Package? It comes with a number of built-in effects and allows writing your own.

I asked more than once on the unity forum and got no answer.
It is a partial class but it is not divided yet (This is the complete code).
The error e: One effect is applied on top of the other instead of rendering in the image of the other, as it was to happen in a post processing stack.

Also, I can’t use the Unity Api because I’m using an SRP, which is why I can’t just use the OnCameraRender () method or something like that.

What I need and an idea of ​​how to make the image (Camera + first effect) enter the Shader of the second effect.
Render the second in this image.
And play the result on the screen.

Unfortunately, I doubt you’ll get an answer here either. While many of the users on this forum are knowledgeable regarding OpenGL, I don’t see any OpenGL calls in the code you’ve posted, and there’s no reason to assume that any of us know anything about the Unity API.

Unity may be using OpenGL internally (or it may be using D3D or Vulkan), but that doesn’t mean that knowledge of OpenGL is going to help figure out what is ultimately a Unity question.

1 Like

I’m afraid I don’t know what is wrong.

The Post-Processing Package I linked above claims to support the built-in render pipeline, Universal Render Pipeline (URP) with some limitations, and Scriptable Render Pipelines (SRP).

As much as the forum is not about that, I managed to solve the problem and I have to share the solution for those who need it in the future.
Basically I had not correctly addressed my post processing effects and therefore I was unable to get the images from it.

The code looks like this:

	int effectsID;
	void createPostProcessingStack(PostProcessingCamera PPC)
	{
		effectsID = Shader.PropertyToID("_Effect0");
		for (int i = 1; i < PPC.getMaterialList().Count; i++)
		{
			Shader.PropertyToID("_Effect" + i);
		}
	}

Code:

using UnityEngine;
using UnityEngine.Rendering;
using System.Collections;
using System.Collections.Generic;
public class PostProcessingStack
{

	const string bufferName = "PostProcessingEffects";
	int fxSourceId = Shader.PropertyToID("_PostFXSource");
	CommandBuffer buffer = new CommandBuffer
	{
		name = bufferName
	};

	ScriptableRenderContext context;

	Camera camera;

	public bool IsActive = true;
	int effectsID;
	void createPostProcessingStack(PostProcessingCamera PPC)
	{
		effectsID = Shader.PropertyToID("_Effect0");
		for (int i = 1; i < PPC.getMaterialList().Count; i++)
		{
			Shader.PropertyToID("_Effect" + i);
		}
	}

	public void Setup(ScriptableRenderContext context, Camera camera)
	{
		this.context = context;
		this.camera = camera;
	}

	public void PostProcessingDrawing(PostProcessingCamera PPC, int sourceId)
	{
		createStack(PPC, sourceId);
		context.ExecuteCommandBuffer(buffer);
		buffer.Clear();
	}

    void Drawing(RenderTargetIdentifier from, RenderTargetIdentifier to, Material material, int pass)
	{
		buffer.SetGlobalTexture(fxSourceId, from);
		buffer.SetRenderTarget(to, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
		buffer.DrawProcedural(Matrix4x4.identity, material, pass,MeshTopology.Triangles, 3);
		
		buffer.ReleaseTemporaryRT(fxSourceId);
	}

	void createStack(PostProcessingCamera PPC, int sourceId)
    {
		createPostProcessingStack(PPC);

		buffer.BeginSample("ProcessingEffects");
		List<Effect> effects = PPC.getMaterialList();

		int fromId = sourceId, toId = effectsID;
		int i;
		for (i = 0;i < effects.Count;i++ )
		{
			buffer.GetTemporaryRT(toId, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear, RenderTextureFormat.Default);
			for (int pass = 0; pass < effects[i].passNumber; pass++)
		    Drawing(fromId, toId, effects[i].material, pass);
			fromId = toId;
			toId += 1;
		}

		Drawing(fromId, BuiltinRenderTextureType.CameraTarget, new Material(Shader.Find("Hidden/Standard")), 0);

		for (i -= 1; i >= 0; i--)
		{
			buffer.ReleaseTemporaryRT(effectsID + i);
		}

		buffer.EndSample("ProcessingEffects");
	}


}