Hello,
I have been working on a custom DepthPass for my objects to correctly blend to my procedural Skybox in based on Depth. I had issues on calculating depth on my water surfaces since they are transparent so i created my own DepthPass.
It all works out fine except for the fact that i now also need to calculate the correct depth on my billboard trees that are based on a geometry shader. When adding an additional SubShader to my overrideMaterial I noticed that the RenderPass just did not care at all about the different SubShaders for the different RenderTypes(“Transparent, TransparentCutout, etc.”). It just always takes the very first SubShader defined in the overrideMaterial (which is “Opaque”) regardless of what the objects original SubShader RenderType is defined as.
How can i now tell the overrideMaterial to take the RenderType into account since the old way of handling ReplaceShaders did take that into account if I am not mistaken?
Here is the code for my custom DepthPass for reference
public class DepthWithTransparentsFeature : ScriptableRendererFeature
{
class DepthWithTransparentsPass : ScriptableRenderPass
{
int kDepthBufferBits = 32;
private RenderTargetHandle depthAttachmentHandle { get; set; }
internal RenderTextureDescriptor descriptor { get; private set; }
private Material DepthWithTransparentsMaterial = null;
private FilteringSettings m_FilteringSettings;
string m_ProfilerTag = "DepthWithTransparents Prepass";
public DepthWithTransparentsPass(RenderQueueRange renderQueueRange, LayerMask layerMask, Material material)
{
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
DepthWithTransparentsMaterial = material;
}
public void Setup(RenderTextureDescriptor baseDescriptor, RenderTargetHandle depthAttachmentHandle)
{
this.depthAttachmentHandle = depthAttachmentHandle;
baseDescriptor.colorFormat = RenderTextureFormat.ARGB32;
baseDescriptor.depthBufferBits = kDepthBufferBits;
descriptor = baseDescriptor;
}
// This method is called before executing the render pass.
// It can be used to configure render targets and their clear state. Also to create temporary render target textures.
// When empty this render pass will render to the active camera render target.
// You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
// The render pipeline will ensure target setup and clearing happens in an performance manner.
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
cmd.GetTemporaryRT(depthAttachmentHandle.id, descriptor, FilterMode.Point);
ConfigureTarget(depthAttachmentHandle.Identifier());
ConfigureClear(ClearFlag.All, Color.black);
}
// Here you can implement the rendering logic.
// Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
// https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
// You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
using (new ProfilingSample(cmd, m_ProfilerTag))
{
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
List<ShaderTagId> shaderTagIdList = new List<ShaderTagId>();
shaderTagIdList.Add(new ShaderTagId("DepthOnly"));
var drawSettings = CreateDrawingSettings(shaderTagIdList, ref renderingData, SortingCriteria.RenderQueue);
drawSettings.perObjectData = PerObjectData.None;
drawSettings.overrideMaterial = DepthWithTransparentsMaterial;
drawSettings.overrideMaterialPassIndex = 0;
context.DrawRenderers(renderingData.cullResults, ref drawSettings,
ref m_FilteringSettings);
cmd.SetGlobalTexture("_CameraDepthWithTransparentsTexture", depthAttachmentHandle.id);
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
/// Cleanup any allocated resources that were created during the execution of this render pass.
public override void FrameCleanup(CommandBuffer cmd)
{
if (depthAttachmentHandle != RenderTargetHandle.CameraTarget)
{
cmd.ReleaseTemporaryRT(depthAttachmentHandle.id);
depthAttachmentHandle = RenderTargetHandle.CameraTarget;
}
}
}
DepthWithTransparentsPass depthWithTransparentsPass;
RenderTargetHandle depthWithTransparentsTexture;
Material depthWithTransparentsMaterial;
public override void Create()
{
depthWithTransparentsMaterial = CoreUtils.CreateEngineMaterial("Hidden/DepthWithTransparents");
depthWithTransparentsPass = new DepthWithTransparentsPass(RenderQueueRange.all, -1, depthWithTransparentsMaterial);
depthWithTransparentsPass.renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;
depthWithTransparentsTexture.Init("_CameraDepthWithTransparentsTexture");
}
// Here you can inject one or multiple render passes in the renderer.
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
depthWithTransparentsPass.Setup(renderingData.cameraData.cameraTargetDescriptor, depthWithTransparentsTexture);
renderer.EnqueuePass(depthWithTransparentsPass);
}
}
Here is the overrideMaterial shader code:
Shader "Hidden/DepthWithTransparents" {
Properties{
_MainTex("", 2D) = "white" {}
_Cutoff("", Float) = 0.5
_Color("", Color) = (1,1,1,1)
}
SubShader{
Tags { "RenderType" = "Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float4 nz : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata_base v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
o.nz.xyz = COMPUTE_VIEW_NORMAL;
o.nz.w = COMPUTE_DEPTH_01;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return EncodeDepthNormal(i.nz.w, i.nz.xyz);
}
ENDCG
}
}
SubShader{
Tags { "RenderType" = "Transparent" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float4 nz : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata_base v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
o.nz.xyz = COMPUTE_VIEW_NORMAL;
o.nz.w = COMPUTE_DEPTH_01;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return EncodeDepthNormal(i.nz.w, i.nz.xyz);
}
ENDCG
}
}
SubShader{
Tags { "RenderType" = "TransparentCutout" }
Cull Off
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 nz : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
uniform float4 _MainTex_ST;
v2f vert(appdata_base v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.nz.xyz = COMPUTE_VIEW_NORMAL;
o.nz.w = COMPUTE_DEPTH_01;
return o;
}
uniform sampler2D _MainTex;
uniform fixed _Cutoff;
uniform fixed4 _Color;
fixed4 frag(v2f i) : SV_Target {
fixed4 texcol = tex2D(_MainTex, i.uv);
clip(texcol.a* _Color.a - _Cutoff);
return EncodeDepthNormal(i.nz.w, i.nz.xyz);
}
ENDCG
}
}
SubShader{
Tags { "RenderType" = "TreeBark" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "UnityBuiltin3xTreeLibrary.cginc"
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 nz : TEXCOORD1;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata_full v) {
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
TreeVertBark(v);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord.xy;
o.nz.xyz = COMPUTE_VIEW_NORMAL;
o.nz.w = COMPUTE_DEPTH_01;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return EncodeDepthNormal(i.nz.w, i.nz.xyz);
}
ENDCG
}
}
........(cutting off the rest to make the post shorter)............
Fallback Off
}
Thanks in advance!