So i dont manage to find any example on how to draw to the ShadowMap while doing a DrawMeshInstanced with CommandBuffers inside a CustomPass
All of the “Graphics.DrawMesh…” have overloads specifiyng the ShadowCastingMode & receive shadows, but they dont exist for the CommandBuffer methods. I am guessing this is because we need to do it manually but im confused about how to move forward.
Currently, existing shadows (like the ones casted from a regular MeshRenderer) are being received, but we are not casting any.
I guess i should get a reference to the shadowMap in some moment, then render with CommandBuffer.DrawMeshInstanced specifiying the ShadowCaster pass, but for each light affecting each object? how should i go about that?. can we figure out this together :)?
Hi, have you tried setting the shaderPass below to -1?
DrawMeshInstanced(Mesh mesh, int submeshIndex, Material material, int shaderPass, Matrix4x4[] matrices, int count);
// shaderPass:
// Which pass of the shader to use, or -1 which renders all passes.
If you need to set the render target to shadowmaps and enqueue a custom ShadowCaster pass.
You can use:
ScriptableRenderPass.ConfigureTarget();
// URP does not suggest using this.
CommandBuffer.SetRenderTarget();
For directional light shadow, the shadowmap is called “_MainLightShadowmapTexture”.
URP 12 (and lower) uses “RenderTextureIdentifier” instead of “RTHandle”, so you can set the render target directly by providing RenderTexture’s name. (If it exists)
Yes, -1 should render all passes, but this is not what i want (still, no shadows are drawn).
This is what i understand i should do: (but aint working)
I need a feature with 2 pases, one for UniversalForward, and 1 for ShadowCaster pass.
For and opaque pass, the renderEvt for the UniversalForward pass should be “After Rendering Opaques”, and for the shadowCaster pass it should be “After Rendering Shadows” (im also trying before in both).
The universal pass renders with DrawMeshInstanced with 0 as pass index (or .FindPass(“ForwardLit”))
The shadowPass renders with DrawMeshInstanced, previously having set the “_MainLightShadowmapTexture” as the target with ConfigureTarget().
Feature
public class GrassRenderFeature : ScriptableRendererFeature
{
[SerializeField]
private GrassSettings _settings;
GrassRenderPass _grassPass;
GrassShadowPass _shadowPass;
public override void Create()
{
GrassPositions positions = new GrassPositions(_settings);
_grassPass = new GrassRenderPass(_settings, positions);
_shadowPass = new GrassShadowPass(_settings, positions);
_grassPass.renderPassEvent = _settings.renderPassEvt;
_shadowPass.renderPassEvent = _settings.shadowPassEvt;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(_grassPass);
renderer.EnqueuePass(_shadowPass);
}
It aint working (grass renders, and receives lights & shadows, but doesnt cast shadows) , but it gets me thinking that REALLY what i want to do is render into the shadowmap from each light? do i have to manually render each light into the shadowMap?, i see there is a .AddCommandBuffer() method on to the “Light” class, is this the right direction?
//
// Summary:
// Add a command buffer to be executed at a specified place.
//
// Parameters:
// evt:
// When to execute the command buffer during rendering.
//
// buffer:
// The buffer to execute.
//
// shadowPassMask:
// A mask specifying which shadow passes to execute the buffer for.
public void AddCommandBuffer(LightEvent evt, CommandBuffer buffer);
I never came back here to post what i found out, so in case someone is interested:
To render the Shadows i needed to provided a way to pass my own RenderPass to render using the ShadowCaster pass while unity is rendering its shadows.
Rendering shadows seems to be just render the objects to the propper RT’s while using projection matrices that come from the Light’s position instead of the camera.
Within the UniversalRenderer.cs, unity enqeues the “MainLightShadowCasterPass” and “AdditionalLightsShadowCasterPass”. All the calculations for rendering are done inside them, and you need to render right after unity renders, and before it clears the necessary data.
Modifying the code, It’s easy to provide a way to execute your own commands passing down the prepared commandBuffer in the right moment for both passes. I would just LOVE unity to provide a builtin-way to do it, as for building plugins/packages we cannot rely on users overriding the URP, or us keeping up with the changes on a modified version. And i think there is NO way to actually cast shadows in custom passes when doing custom rendering (avoiding GO’s or “Renderer” Components)
Hi Canijo!
Sorry did you mean on your last post it’s actually not possible to do a shadow pass on command buffer without changing URP code? I’m precisely trying to convert Graphics.RenderMeshIndirect() into command buffers and having the same problem about shadow casting (and actually the same on the layer setting)
Thanks!
(Por cierto parece que eres paisano de Madrid? saludos desde Kioto
It’s been a while since i messed with rendering code, but from what i remember, i could not find a way to do it without modifying code.
Im eyeballing the URP code now (on 2023.2.3f1) and i see that there has been some changes, but i believe that the constraints are the same and there might still not be a builtin way to achieve it.
The problem is that there are many keywords and data that needs to be setup before rendering a ShadowCaster Pass onto anything, and many settings that drive how shadows are actually rendered, like cascading, or softshadows, and depending on those, shadows might be drawn multiple times at different resolutions in different parts of the same texture. Also additional lights are rendered on a different pass than the MainLight shadows. .
The easiest way for me to replicate that behaviour without going all crazy and reimplement everything, was to directly provide a way to expose the command buffer that is being used on those passes right before all that data was “Cleared”. So i created a custom base class for Passes that want to render into Shadows, with a method that accepts the command buffer and the relevant data that i could need from the pass. At the setup stage, i stored those passes into the Main and Additional shadow passes, so i could call them from there each time they render a “ShadowSlice”.
The relevant URP classes are MainLightShadowCasterPass and AdditionalLightsShadowCasterPass,
On the MainLight pass the rendering happens here, and on the additionalLightsShadow pass is quite similar
namespace UnityEngine.Rendering.Universal.Internal
{
public class MainLightShadowCasterPass : ScriptableRenderPass
{
/// ....
void RenderMainLightCascadeShadowmap(RasterCommandBuffer cmd, ref PassData data, ref RenderingData renderingData, bool isRenderGraph)
{
/// ....
for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
{
/// ....
/// Called once per cascade, with different View & Proj matrices
ShadowUtils.RenderShadowSlice(cmd, ref m_CascadeSlices[cascadeIndex], ref shadowRendererList, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].viewMatrix);
}
}
}
Also, check the ShadowUtils.RenderShadowSlice(...) method, as it is there where the “Viewport” (part of the texture) and Proj&View matrices are set. And that very method “Renders” and then calls “DisableScissorRect” and also resets the depth bias values. You might need to modify it so you can render before it does that, so you can manually do it after
PD: Sí ^^, pero yo te saludo desde Canarias, que es donde vivo ahora
Ok I see, so you actually get your command buffer injected into all needed shadow passes
I’m taking note of it so I give it a try a bit later, thank you so much!