- Home /
How can I make a quad render below absolutely everything else?
I tried changing the render queue but no success. I have a quad parented to the main camera. I am trying to have a static background.
Answer by Bunny83 · Jun 17, 2019 at 04:23 PM
Well, the most efficient way would be to render the quad just after all opaque geometry has been rendered. You would render the quad at a far distance with depth testing on but with zwrite off just like most transparent geometry is rendered.
Another option is to render it before anything else with zwrite off. This way the distance from the camera doesn't matter. However it's less efficient since you will use quite a bit of fill rate due to overdraw.
edit
Ok here's an example. To use the second solution you can use the following shader for your plane. This plane can be just right in front of the camera if forward rendering is used. This does not work in deferred rendering. With deferred rendering you need to place it manually far away. Of course the plane would need to be a child of the camera so it always moves and rotates with the camera.
Shader "Unlit/BackgroundPlane"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "Queue" = "Background" }
ZWrite Off
Pass
{
ZWrite Off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
The same shader can be used for the first solution, but you just need to replace
Tags { "Queue" = "Background" }
with
Tags { "Queue" = "Geometry+500" }
This will render the quad after all opaque geometry. Just as mentioned in this case the quad need to be far away and behind everything. So you might want to place it close to the far clipping plane and scale it up to fill the whole screen.
Instead of an actual plane object that is placed as child on the camera we can also draw a fullscreen quad procedurally with a script like this:
//BackgroundPlane.cs
using UnityEngine;
[ExecuteInEditMode]
public class BackgroundPlane : MonoBehaviour
{
public Material mat;
void Point(float x, float y)
{
GL.TexCoord2(x, y);
GL.Vertex3(x, y, -1);
}
private void OnPostRender()
{
mat.SetPass(0);
GL.PushMatrix();
GL.LoadIdentity();
GL.LoadProjectionMatrix(Matrix4x4.Ortho(0,1,0,1,0,1));
GL.Begin(GL.QUADS);
Point(0, 0);
Point(0, 1);
Point(1, 1);
Point(1, 0);
GL.End();
GL.PopMatrix();
}
}
Just attach this script to the camera. It will draw a fullscreen quad at the far clipping plane using the provided material. This would work with both shaders mentioned above. Note that this script will always scale the texture to fit the screen. So it might be stretched depending on the screen aspect ratio.
I cannot thank you enough for this! Do you just know all this shader stuff off the top of your head? I'm still new to shaders and rednering.
If I wanted to make the procedural generated plane not rotate with the camera, is it possible?
Your answer
Follow this Question
Related Questions
Scissor test/early rejection 2 Answers
Render inside of mesh as black 2 Answers
Masking elements with non-rendered layers? Culling masks, camera, render textures 0 Answers
Rendering different shader when camera get near object 1 Answer
Do I have to turn on camera relative rendering in URP? 0 Answers