unity-game-enginegraphicshlsllightingcompute-shader

Why are variables not being treated the same as their underlying value in Unity compute shader?


I'm writing a 2D lighting compute shader, where each thread casts 1 ray. What I'm doing is setting numthreads to (1024, 1,1), and defining the angle of the ray cast by a given thread as the x value of the thread id (so, for example, the thread with id.x == 36 will draw a ray at 36 degrees). However, I'm getting some strange behavior in regards to a comparison that filters out unnecessary angles.

Before any computation is done, I use this comparison to filter out unnecessary angles:

if ((id.x >= cur_light.startAngle) && (id.x < cur_light.endAngle))

Where my cur_light is a type LightData, defined as

struct LightDataStruct
{
    float2 uv;
    uint startAngle;
    uint endAngle;
    int intensity;
};

Here's the unexpected behavior: If I set startAngle of the current light to 0 and startAngle of the current light to 1, no ray is drawn at all. I'd expect a single ray to be drawn at angle 0.

However, when it gets weird is if I manually change the comparison to this:

if ((id.x >= 0) && (id.x < 1))

a single ray is drawn at angle 0, as expected. So, comparing to a constant is behaving differently than comparing to the variable.

This seems to indicate that data is not being passed into the compute shader correctly, but the strange thing is I'm nearly 100% sure that cur_light.startAngle == 0 and cur_light.endAngle == 1. I've verified this by outputting the comparison as a color, like so:

outputTexture[id.xy] = float4(cur_light.endAngle == 1, cur_light.startAngle == 0, 0, 0);

And the resulting outputTexture contains the values (1, 1, 0, 0). That is, both conditions evaluate to true.

So the question is, how can cur_light.endAngle == 1, cur_light.startAngle == 0, but

((id.x >= cur_light.startAngle) && (id.x < cur_light.endAngle)) 

is not equal to

((id.x >= 0) && (id.x < 1))

For context, here's the C# code writing to the compute buffer:

LightDataStruct[] data = new LightDataStruct[Lights.Count];

for (int i = 0; i < Lights.Count; i++)
{
    data[i] = new LightDataStruct(Lights[i].uv, Lights[i].startAngle, Lights[i].endAngle,    
    Lights[i].intensity);
}
buffer.SetData(data);

Raycaster.SetBuffer(kernel, "Lights", buffer);

Raycaster.Dispatch(kernel, 1, 1, 1);

Where Lights is a serialized field of monobehaviours, the details aren't important.

I feel like I'm missing something obvious, any ideas?


Solution

  • Resolved - the if statement was passing but the ray wasn't being drawn for some reason.