I am writing my first series of shaders on shadertoy, and can't seem to find an explanation for the following behaviour. I have defined the Hit
struct, and a Union
function which takes two Hit
variables, and returns the one with minimum rayDist
.
In practice, the Hit
returned by the function seems to always have the right rayDist
but not matID
.
struct Hit
{
float rayDist;
float matID;
};
Hit Union(Hit hit1, Hit hit2)
{
if(hit1.rayDist < hit2.rayDist)
{
return hit1;
}
else
{
return hit2;
}
}
The function gets called in the following way:
#define MATERIAL2 2.0
Hit rayHit = Hit(MAXDIST,-1.);
vec3 gridCoord = floor(coord);
for(int i =-1; i <= 1; i++)
for(int j =-1; j <= 1; j++)
for(int k =-1; k <= 1; k++)
{
vec3 cell = gridCoord + vec3(i,j,k);
float matOffset = hash13(cell);
Hit sphereHit = Hit(SDSphere(cell, coord, scale), MATERIAL2);
sphereHit.matID += matOffset;
rayHit = Union( rayHit, sphereHit); // only works when rayHit is used as assigned variable
}
In this example, I am expecting that calling Union
should return the same value, regardless of the order in which the arguments are passed (commutative). However I have found that Union( rayHit, sphereHit);
and Union( sphereHit, rayHit);
yield different results, more specifically different matID
. Both return the correct rayDist
.
Union( rayHit, sphereHit);
returns matID = MATERIAL2 + matOffset
(which is what I am expecting), whilst Union( rayHit, sphereHit);
returns matID = MATERIAL2
.
Confusingly, changing the value which gets assigned the output of Union also alters the results.
Again rayHit = Union( rayHit, sphereHit);
works fine, but
Hit newHit = Union( rayHit, sphereHit);
rayHit = newHit;
gives a result of matID = MATERIAL2
.
I have tried changing the function to use vec2
instead :
vec2 Union(vec2 hit1, vec2 hit2)
{
return hit1.x < hit2.x ? hit1 : hit2;
}
encoding rayDist
in vec2.x
and matID
in vec2.y
. This will always return the minimum object correctly, regardless of the order. It seems to indicate that the struct is the issue.
I am not familiar with how structs work in GLSL, why can't I seem to use them in this way? Thanks!