Skip to content

Instantly share code, notes, and snippets.

@phi-lira
Created March 19, 2019 14:02
Show Gist options
  • Save phi-lira/46c98fc67640cda47dcd27e9b3765b85 to your computer and use it in GitHub Desktop.
Save phi-lira/46c98fc67640cda47dcd27e9b3765b85 to your computer and use it in GitHub Desktop.
LWRP FullScreenQuad feature example. This can be used to extend LWRP render to render a full screen quad.
namespace UnityEngine.Rendering.LWRP
{
// A renderer feature contains data and logic to enqueue one or more render passes in the LWRP renderer.
// In order to add a render feature to a LWRP renderer, click on the renderer asset and then on the + icon in
// the renderer features list. LWRP uses reflection to list all renderer features in the project as available to be
// added as renderer features.
public class FullScreenQuad : ScriptableRendererFeature
{
[System.Serializable]
public struct FullScreenQuadSettings
{
// The render pass event to inject this render feature.
public RenderPassEvent renderPassEvent;
// Material to render the quad.
public Material material;
}
// Contains settings for the render pass.
public FullScreenQuadSettings m_Settings;
// The actual render pass we are injecting.
FullScreenQuadPass m_RenderQuadPass;
public override void Create()
{
// Caches the render pass. Create method is called when the renderer instance is being constructed.
m_RenderQuadPass = new FullScreenQuadPass(m_Settings);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
// Enqueues the render pass for execution. Here you can inject one or more render passes in the renderer
// AddRenderPasses is called everyframe.
if (m_Settings.material != null)
renderer.EnqueuePass(m_RenderQuadPass);
}
}
}
namespace UnityEngine.Rendering.LWRP
{
// The render pass contains logic to configure render target and perform drawing.
// It contains a renderPassEvent that tells the pipeline where to inject the custom render pass.
// The execute method contains the rendering logic.
public class FullScreenQuadPass : ScriptableRenderPass
{
string m_ProfilerTag = "DrawFullScreenPass";
FullScreenQuad.FullScreenQuadSettings m_Settings;
public FullScreenQuadPass(FullScreenQuad.FullScreenQuadSettings settings)
{
renderPassEvent = settings.renderPassEvent;
m_Settings = settings;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
Camera camera = renderingData.cameraData.camera;
var cmd = CommandBufferPool.Get(m_ProfilerTag);
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_Settings.material);
cmd.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}
}
@jjxtra
Copy link

jjxtra commented Apr 26, 2019

If I try to re-use a command buffer it gets executed 3 times in a row, are you seeing this behavior?

@kronnect
Copy link

Can this be used from endCameraRendering event?
For example:
RenderPipelineManager.endCameraRendering += SRP_Render;

And

void SRP_Render(ScriptableRenderContext context, Camera camera) {
if (cam.cameraType == CameraType.SceneView || cam.cameraType == CameraType.Game) {
var cmd = CommandBufferPool.Get(m_ProfilerTag);
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_Settings.material);
cmd.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}

This doesn't work on my end at least.
If this is expected could you please explain why ExecuteComandBuffer() doesn't work at this stage?
Thanks.

@dimitarcl
Copy link

dimitarcl commented Jul 19, 2019

Can this be used from endCameraRendering event?
For example:
RenderPipelineManager.endCameraRendering += SRP_Render;

And

void SRP_Render(ScriptableRenderContext context, Camera camera) {
if (cam.cameraType == CameraType.SceneView || cam.cameraType == CameraType.Game) {
var cmd = CommandBufferPool.Get(m_ProfilerTag);
cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, m_Settings.material);
cmd.SetViewProjectionMatrices(camera.worldToCameraMatrix, camera.projectionMatrix);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
}

This doesn't work on my end at least.
If this is expected could you please explain why ExecuteComandBuffer() doesn't work at this stage?
Thanks.

@RamiroOliva

Try adding:

context.Submit();

at the end.
According to
https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.Submit.html it will submit the rendering command for execution.

@kronnect
Copy link

kronnect commented Jul 20, 2019

Try adding:

context.Submit();

Thank you! That was the missing bit :)

@noio
Copy link

noio commented Oct 15, 2019

What if I want the Projection matrix to be set to the actual rendering camera's projection matrix? So that the Material's shader can correctly compute things like view direction? What should the matrix in cmd.DrawMesh be then to make sure the quad is still "in front of the camera" ?

Edit: I did it as follows, I did not call cmd.SetViewProjectionMatrices, but instead I did

// Create a transformation that places the Quad 1 unit in front of the camera.
var fullScreenQuadMatrix = Matrix4x4.TRS(camera.transform.TransformPoint(Vector3.forward), camTransform.rotation, Vector3.one);
cmd.DrawMesh(RenderingUtils.fullscreenMesh, fullScreenQuadMatrix, _material, 0, _materialPassIndex);

@0x6c6565
Copy link

The RenderFeature settings are not displayed in the ReorderableList when added to a ForwardRenderer.

@0x6c6565
Copy link

So apparently, m_ in front of the word settings stops the property from displaying. smh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment