trick for 1k raymarchers :: lighting
category: code [glöplog]
I wanned to share something I found today when size-optimizing some code:
Given a potential function "float f(vec3 p)" one tends to do lighting by computing a gradient/normal at point "p" for later doing a dot product with the light vector "vec3 l" for getting some diffuse lighting. Like
I think you probably want replace all that code with this one:
The original code/method produces:
while the new one, produces:
I fyou are still unconfortable with the second method and want to stick to the first, remember that f(p)=0 anyway (or almost, as p is on the surface), so you can at least remove those...
Given a potential function "float f(vec3 p)" one tends to do lighting by computing a gradient/normal at point "p" for later doing a dot product with the light vector "vec3 l" for getting some diffuse lighting. Like
Code:
vec3 n;
vec3 e=vec3(0.1,0,0);
n.x=f(p)-f(p+e.xyy));
n.y=f(p)-f(p+e.yxy));
n.z=f(p)-f(p+e.yyx));
//n = normalize(n);
float d=dot(n,l);
I think you probably want replace all that code with this one:
Code:
float d=f(p+0.1*l);
The original code/method produces:
while the new one, produces:
I fyou are still unconfortable with the second method and want to stick to the first, remember that f(p)=0 anyway (or almost, as p is on the surface), so you can at least remove those...
That is an impressive little size optimization. The only differences I can spot with my naked eye is some contrast differences and a single missing edge in the lower left corner.
Actually the bottom image is a bit smoother aswell. Anal coders will hate this but it's quite the nice little optimization :) Thanks for sharing.
hey, I recognize those blobs :) that's a huge size improvement with minimal fidelity loss, thanks iq!
Ferris is right about the smoothness, look at the color banding in the top right corner on the top image :P
I have never coded a shader, but why do you multiply with 1 ?
float d=f(p+0.1*l);
oh, great, the code tag uses a font where L and 1 is pixel to pixel identical.
float d=f(p+0.1*l);
oh, great, the code tag uses a font where L and 1 is pixel to pixel identical.
the "l" is one pixel difference...but yes, i read a "1" first aswell :/
nice size-optimization, iq :)
i have all the lighting in one line for my 4ks but its still more like the first version, gives more control about light-position, but for 1k its ofcoz very usable :)
nice size-optimization, iq :)
i have all the lighting in one line for my 4ks but its still more like the first version, gives more control about light-position, but for 1k its ofcoz very usable :)
"l" is the light position, so there.
not your fault anyway, iq ;)
maybe garg should change the font for code-boxes !
( if i read sth about code i always just sloppy watch over it, so ofcoz i didnt recognize the 1 being an l on first sight...doing code oneself rulez ! guess Oswald just had an half eye for the code aswell..hehe )
maybe garg should change the font for code-boxes !
( if i read sth about code i always just sloppy watch over it, so ofcoz i didnt recognize the 1 being an l on first sight...doing code oneself rulez ! guess Oswald just had an half eye for the code aswell..hehe )
no difference here:
l and I has always been bad as variable names :-D
Nice code snippet. But that shouldn't just be smaller code if I get that code correctly so is it also a major speed optimization. Going from 6 evaluations of the potential function down to 1 could clearly make a positive performance impact!
Change your browser's default font settings, people.
(Pouet's CSS doesn't specify a font for code blocks, and even if it did, it would have to guess which fonts people have installed, because Courier is probably the only standard monospace one across all platforms.)
(Pouet's CSS doesn't specify a font for code blocks, and even if it did, it would have to guess which fonts people have installed, because Courier is probably the only standard monospace one across all platforms.)
At least enable cleartype ;)
Xetick: The performance boost isn't as big as it might seem at first, as you're already evaluating the distance functions shit-loads of times to find the surface. The lighting is generally done once per pixel, not per ray-step.
"Change your browser's default font settings, people."
I guess pouet should use a default font which doesnt suck.
I guess pouet should use a default font which doesnt suck.
As I view the first post, the first picture has noticeable color banding, while the second does not. Is this just my monitor being crappy, or what?
i guess its due to missing dithering, i.e. most (cheaper) monitors will show color banding for such 'smooth' gradients, as the monitor cannot display full 24bit colors..
Toxie, I think that isn't the case. The theoretical-epsilon in the distance field function is actually not as small as it should be for a pixel-perfect sampling of the field. Hence the distance between two sampling points which is then used to deduce the normal might not be forming a perfect gradient hence creating the banding :).
it is, just take a look at the picture values in a gfxprog.. all smooth (f.e. on the right, an almost perfect gradient), but on my monitor: 'stripes'..
it's true, MOST modern LCD monitors use 16bit colour. Unless you bought a more expensive, higher-end screen, chances are you're looking at 64k colours right now. I have one of each, a decent IPS/24bit screen and a cheapo TN/16bit thing, it's a big difference.
IliI1|
The first render gradients are banded... its not your monitor, its the gradient.
By value its like 10,10,10,10,10,11,12,13,14,15,16,17,17,17,17,17,17
So you see smooth band transition. Even with the best monitor the first image will look really banded.
BTW. 24bit == 256 shade ... Even the best monitor show banding with 256 shades.
And 6bit monitor use trick to render > 64 shades , if they didn't they would look like total crap. and amazingly even the cheapest of the cheapest render 8bit gradient well (Its usually a user error in the monitor calibration when 6bit HW can render 8bit data without banding)
There you have it: Image 1 is banded, and its not your cheap monitor unless you calibrated it badly.
By value its like 10,10,10,10,10,11,12,13,14,15,16,17,17,17,17,17,17
So you see smooth band transition. Even with the best monitor the first image will look really banded.
BTW. 24bit == 256 shade ... Even the best monitor show banding with 256 shades.
And 6bit monitor use trick to render > 64 shades , if they didn't they would look like total crap. and amazingly even the cheapest of the cheapest render 8bit gradient well (Its usually a user error in the monitor calibration when 6bit HW can render 8bit data without banding)
There you have it: Image 1 is banded, and its not your cheap monitor unless you calibrated it badly.
They use tricks to render >64 shades, but not always successfully. On my decent, 24 bit monitor the 2nd image looks better, very little visible banding.
On the cheap 16bit monitor, the 1st image actually looks better. Both show visible banding, not so bad as "true" 16 bit would look, but it's there. The 1st image now looks about the same as the 2nd image looks on my good screen. The 2nd image looks the same, but now there's visible flickering where pixels are swapping between two 16bit colours to make a colour between. It's like the old interlace tricks, but nowhere near so bad fortunately.
And btw, the flickering effect is truly horrible when you set the screen background to the wrong colour ;)
On the cheap 16bit monitor, the 1st image actually looks better. Both show visible banding, not so bad as "true" 16 bit would look, but it's there. The 1st image now looks about the same as the 2nd image looks on my good screen. The 2nd image looks the same, but now there's visible flickering where pixels are swapping between two 16bit colours to make a colour between. It's like the old interlace tricks, but nowhere near so bad fortunately.
And btw, the flickering effect is truly horrible when you set the screen background to the wrong colour ;)
Oh, and back on topic.. awesome bit of optimisation there. Much smaller and much faster.. but why? I don't get why it works at all :) (And I probably won't follow the answer, but I'll still ask)