I have a shader where I’m trying to clip() every other pixel, to create a checkerdbox pattern.
The problem is, the main forward pass of my shader isn’t clipping always the same pixels as the shadowcaster pass is. And yet, as far as I can tell, they use identical code for determining which pixels to clip.
But often the shadow pass will clip every wrong pixel (meaning all its pixels are shifted by 1). And if I adjust the vertical size of the game view window, it screws around with it as I move the vertical size of the window, so that on some frames the shadow pass clips all the same pixels as the forward pass is clipping, and on other frames it clips all the wrong pixels (the pixels that the forward pass didn’t clip). Which makes no sense since they use the same code, they should always clip the same pixels?
For the forward pass vertex:
o.screenPosition = mul(UNITY_MATRIX_MVP, v.vertex);
For the shadow pass vertex:
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.screenPos = o.pos;
Then, the clip in the forward pass:
float checkerdBox(float2 screenUVs) {
float2 px = floor(_ScreenParams.xy * screenUVs);
return (fmod(px.x + px.y, 2) == 1) ? 0 : 1;
}
surf (...)
{
#if UNITY_UV_STARTS_AT_TOP
float grabSign = -_ProjectionParams.x;
#else
float grabSign = _ProjectionParams.x;
#endif
IN.screenPosition = float4(IN.screenPosition.xy / IN.screenPosition.w, 0, 0);
IN.screenPosition.y *= _ProjectionParams.x;
float2 screenUVs = float2(1, grabSign)*IN.screenPosition.xy*0.5 + 0.5;
clip(checkerdBox(screenUVs) - 0.5);
}
And the clip in the shadow pass (should be identical):
float checkerdBox(float2 screenUVs) {
float2 px = floor(_ScreenParams.xy * screenUVs);
return (fmod(px.x + px.y, 2) == 1) ? 0 : 1;
}
frag (...)
{
#if UNITY_UV_STARTS_AT_TOP
float grabSign = -_ProjectionParams.x;
#else
float grabSign = _ProjectionParams.x;
#endif
IN.screenPos = float4(IN.screenPos.xy / IN.screenPos.w, 0, 0);
IN.screenPos.y *= _ProjectionParams.x;
float2 screenUVs = float2(1, grabSign)*IN.screenPos.xy*0.5 + 0.5;
clip(checkerdBox(screenUVs) - 0.5);
}
My theory is that the issue has something to do with the fact that my forward pass is a SURFACE shader, whereas my shadow pass is a vert / frag shader. And I’m assuming that somewhere, Unity’s surface code generator thing is messing with my screenPos or screenPosition math, so that they are not identical.
If I comment out the line “IN.screenPos.y *= _ProjectionParams.x” from the shadow pass, then it works almost perfectly… only very rarely is there a single pixel here or there that isn’t clipped identically between the two passes (see second image below). But commenting out that line in the shadow pass, but leaving it in the forward, deeply disturbs me. Something is wrong and I don’t feel like that’s the correct solution. Anyone know what I’m doing wrong here?

