Sphere Tracing and Materials
category: code [glöplog]
Let's discuss techniques.
How would you apply two different colors to two different objects?
How would you apply two different colors to two different objects?
err.....
????????
what's the question really? How to optimize it?
how to make it GPU firendly?
or what is it?
Of course, if you don't care aesthetics and go for codecolors yo can always go for
You probably want to lookup for specular, diffuse, bump, sss and all other sort of other parameters too, not only a color, though.
But again, what is the question here?
Code:
if( objectID==0 )
color = cuteColor1;
else if( objectID==1 )
color = cuteColor2;
else
color = black;
????????
what's the question really? How to optimize it?
Code:
color = niceTableOfColros[ objectID ];
how to make it GPU firendly?
Code:
color = texture1D( paletteTexture, float(objectID)/256.0 );
or what is it?
Of course, if you don't care aesthetics and go for codecolors yo can always go for
Code:
color = randomMagic( objectID );
You probably want to lookup for specular, diffuse, bump, sss and all other sort of other parameters too, not only a color, though.
But again, what is the question here?
inouts ;)
initialize and declare colors in main() and set em accordingly to your desireness in the dist(), so it´ll have the correct value once you need it in the getNormal()
...yes you need to have an inout in every func/dist()
... in the getNormal() you can set it to whatever you want tho ;) ( no inout here! just call the dist() with a "0" for color there )
dunno shit about oGL, so if you dont know what i mean with "inout", google it against oGL-instruction-set :p
initialize and declare colors in main() and set em accordingly to your desireness in the dist(), so it´ll have the correct value once you need it in the getNormal()
...yes you need to have an inout in every func/dist()
... in the getNormal() you can set it to whatever you want tho ;) ( no inout here! just call the dist() with a "0" for color there )
dunno shit about oGL, so if you dont know what i mean with "inout", google it against oGL-instruction-set :p
Code:
pseudo:
dist(float3 p, inout colorSwitch)
{
colorSwitch = 0; // needs to be set in every dist()-func atleast once, better just set it just once you know which sort of object got hit accordingly ;) the hit object is to be found via the dist-Function itself, depends on every object tho, so no deeper insights here, sorry ;) makes no sense, but if you know what you are doing you know how to set this flag for your distance-function!!
[...]
}
getNormal(float3 p)
{
int colorSwitch = 0; // doesnt matter, no changing inout used, just here to call dist() 4-6 times ;) --> dist(p, colorSwitch);
[...]
}
main()
{
float4 colors[2];
colors[0] = float4(1. ,0. ,0., 1.);
colors[1] = float4(0. ,1. ,0., 1.);
int colorSwitch = 0;
float n, d=1.;
[...]
d = dist(p, colorSwitch);
[...]
n = getNormal(p);
[...]
// finalColor = colors[colorSwitch]...
return colors[colorSwitch]...
}
Gargaj: can we has [PseudoCode][/PseudoCode] already?
its a lot of pseudo-code to be written here ;)
its a lot of pseudo-code to be written here ;)
i think you win the price for longest rant in a code comment.
Sorry if it wasn't clear. I was looking for techniques for getting obj ids using dist fields.
I've just been returning a packed vector from the field funtion. I currently only use three elements to return four values, so there's scope for more material data to be packed in there.
// return: result.x = distance, result.y = shininess.hue, result.z = diff_lightness
This lets you do more funky things than just one material per object. It also doesn't seem to impact the frame rate on my (simple) scenes. It does make my field function more complex though.
// return: result.x = distance, result.y = shininess.hue, result.z = diff_lightness
This lets you do more funky things than just one material per object. It also doesn't seem to impact the frame rate on my (simple) scenes. It does make my field function more complex though.
I think the main thing is to know which object you hit, then there's all kinds of ways to handle it. For now I'm just returning a vec2 from the field function, with distance and material id.
Instead of something like:
i do something like:
Then you have both distance, and a material/object id. I've just used it for colour so far. But it's quite easy to use it to change lighting, or turn on/off shadows/reflections/SSS/etc too, which might even help with speed.
On the downside, it could be faster.. I've not optimised much yet.
Instead of something like:
Code:
float f(vec3 p){
return min(
cube(cubePos, p),
sphere(spherePos,p)
);
}
i do something like:
Code:
vec2 f(vec3 p){
float c = cube(cubePos, p);
float s = sphere(spherePos,p);
return c < s ? vec2(c, 0.) : vec2(s, 1.);
}
Then you have both distance, and a material/object id. I've just used it for colour so far. But it's quite easy to use it to change lighting, or turn on/off shadows/reflections/SSS/etc too, which might even help with speed.
On the downside, it could be faster.. I've not optimised much yet.
evilpaul: the fps counter is telling you to use a shader :D
I do something like psonice too...
But I use a global float.
Care has to be taken then in the "main", you have to save your "m" locally before calling e.g. calcNormals.
Another possible ways:
- Encode the material in the lower 3 bits of the mantissa of the distance.
- Generate a second field function for material determination (you only need that one time after you have found your hit).
But I use a global float.
Code:
float m; // <-- contains the final ID
float f(vec3 p) {
m = 0.; // <-- init
R(p.yz, pi/6.);
p.y+=1.9;
vec3 q=p;
R(p.xz, t);
float d = spikeball(p)+fsn(p*100.0)*0.01;
float nd = dot(q+vec3(0.,3., 0.), vec3(0., 1.,0.));
m = mix(m,1.,step(nd, d)); // if nd closer, set to 1. else keep previous value, for this case m = step(nd, d)...
return min(d,nd);
}
Care has to be taken then in the "main", you have to save your "m" locally before calling e.g. calcNormals.
Another possible ways:
- Encode the material in the lower 3 bits of the mantissa of the distance.
- Generate a second field function for material determination (you only need that one time after you have found your hit).
that's the prettiest YMCA-cube i've ever seen, paul!
i probably should have removed the hud, the fps counter isn't accurate..
psonice: what makes you think that i'm not using a shader?
psonice: what makes you think that i'm not using a shader?
Your stuff is too slow ;)
paul: all your processing stuff from twitter, and the framerate? :D Or is that something else, and the fps is a lie? Or is it just running on a bad GPU? (I've tried my own stuff on my intel based laptop... i gave up waiting for the first frame to render)
yeah, as i said above, the fps isn't accurate in those shots and this is all standard-ray-marching-on-the-gpu stuff. i'm not really seeing any difference in speed when i'm using this technique but i do have fairly simple scenes. the last picture gives me about 10-20fps on a hig-spec but old laptop. that's better than most of the ray marching demos i've run from the past couple of years but, again, these are simple scenes
the processing stuff i've done is something else completely - it's just something i did for kicks
the processing stuff i've done is something else completely - it's just something i did for kicks
ah right. Just assumed it was the same stuff :)
Anyway, you'll hate me for this, but somebody just left a 3ds on my desk :D Strange thing to happen at work. I didn't order it, and it had somebody else's name on the box, but he didn't order it either. So now we have a 3ds and no idea who its for or why it's here.
Still, cool 3d effect :D Not sure I'd want to use it for any period of time, but I'd love to code demos on it!
Anyway, you'll hate me for this, but somebody just left a 3ds on my desk :D Strange thing to happen at work. I didn't order it, and it had somebody else's name on the box, but he didn't order it either. So now we have a 3ds and no idea who its for or why it's here.
Still, cool 3d effect :D Not sure I'd want to use it for any period of time, but I'd love to code demos on it!
Danguafer look @:
http://www.opengl.org/resources/faq/technical/color.htm#0040
More than two object here.
Qui peut le plus peu le moins.
http://www.opengl.org/resources/faq/technical/color.htm#0040
More than two object here.
Qui peut le plus peu le moins.
orace: we're talking sphere tracing, not regular rasterised objects.
In fact there is only one 'object' on the opengl side that you could assign a colour to, a single quad. The scene gets rendered entirely inside the shader, and it's not simple to separate the objects.
In fact there is only one 'object' on the opengl side that you could assign a colour to, a single quad. The scene gets rendered entirely inside the shader, and it's not simple to separate the objects.
for primary rays you could trace each object for its own and let the zbuffer make the occlusion.. that way for instance you could use boundingrectangles to get more performance and could do several optimizations per object.
Using the zbuffer is an interesting suggestion.
For bounding boxes - I already do something like this. If I have a 'ground' with some stuff on it, and I know nothing is higher than say 2, I start the ray at the intersection with that. And if the ground itself is at 0, I find the length of the ray to that, and use that as a bailout point. That saves a ton of iterations in some cases, especially when the camera is parallel to the ground (which it usually is).
For bounding boxes - I already do something like this. If I have a 'ground' with some stuff on it, and I know nothing is higher than say 2, I start the ray at the intersection with that. And if the ground itself is at 0, I find the length of the ray to that, and use that as a bailout point. That saves a ton of iterations in some cases, especially when the camera is parallel to the ground (which it usually is).
I can't see how to gain anything from the depthbuffer.
You could render all bounding boxes of objects to the depthbuffer in the first pass and then use that in the second pass to get a safe "first step distance". I don't really know if that's worth the effort as you could also check bounding boxes first when raymarching...
Is it possible to write to depth and read back again? Might be possible to save some min() functions ( but what about max(a, -b)?)
Possible with FBOs, but needs special extensions.
if you render every "object" for its own you can easily give every object a different material at no costs in the renderer (like the topic suggested).. but i didn't understand iqs post, i mean how to easy get an objectid with the normal approach?