Hey,
Inspired by the work of unreal engine on shadows and ambient occlusion both using ray marching distance fields, I made nice looking Cycles’ish shadows by ray marching a pre defined cube, based on this article. Here’s how it looks like:
This is a hybrid method, where it marches rays per pixel to produce shadows and combine them with rasterised geometry which makes it run at a great performance. This specific technique can expand easily to generate distance fields from existing geometry, if there was a better way to pass data to the filter system.
Thanks to Martinsh for his per pixel world positions filter, and MarcoIT for helping fix the frame delay by making the camera matrix getting script run in scene pre_draw.
Other stuff like changing the pre defined primitive/moving it or shadow penumbra size are explained in script comments. If you’re facing shadow offsetting issues, use it in the standalone player.
Distance functions provide you with the nearest distance between a point and surface. What ray marching does is begin from a point given it’s line vector, (1) get the closest distance in some direction, and multiply that by the line vector and see if that point is on a surface(>0, object is outside, =0 point is on surface, <0 point is inside), if not then return to (1).
So if you can approximate your surfaces to signed distance functions and have some algorithm that dows what you want to using ray casting, sure is possible for calculating intersections.
I don’t get it, you want to highlight objects on mouseover? Unrelated to distance fields, use python mouse rays that control object color and make a blank material that just uses object color.
Edit: wait so you want to do a sort of glow? sure you can but only with signed primitives as “casters”, though I haven’t really went near volumetric effects yet.
Line 48: getWorldPosition() should return a vec3, but world is vec4. Up to you how you’d want to deal with that. Since we’re multiplying a vector against a Mat4, perhaps we just downgrade at the return statement, like so:
48: return vec3(modelViewMatrixInv*world);
EDIT
I forgot to praise your work. I love it. Thanks for putting time into this wonderful screen space shader, and moreso for sharing it!
One last thing, the shadow is static in its position regardless of the light. Are you still working on dynamics, or is my GPU just picky enough to keep it from working without erroring?
Thanks for the code snippet! going to update it.
About light, you actually need to change light position vector from the glsl script, not just move the lamp. You might also want to apply movement on the plane along the Z to see the shadow nicely fading.
Or you can translate/rotate the cube by multiplying the ray origin with a transformation matrix, or scale it with the built in vec3 b in the map() function.
An interesting method. It would be a nice thing when there is a good and fast way to pass the data of all objects to the filter.
But thank you for the nice work.