Ray marched soft shadows

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.

Controls: Mouselook and WASD.

Attachments

raymarch1.blend (506 KB)

Nice work!

So you could use this to make force field type effects as well? A bubble of light around a object?

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.

Well, I think it may be easier , to use the outline Gsl filter, and somehow specific to use white rather then black on a single item…

So all items are outlined black, except the item currently under the mouse

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.

Sorry to go off topic, but yes I meant to make a glow value rather then a shadow from a object (negative shadow)

or - Highlight using shading rather then object.color or adding a mesh with it’s normal flipped etc

Hey Jackii, It appears these errors:

What’s your gpu? the errors are too picky … Updated the blend in first post.

Edit: oh and remove the “.rgb” in line 92 making it:

    gl_FragColor = texture2D(bgl_RenderedTexture, texCoord)*(shadowcol);

Intel® G41 Express Chipset, with the updated blend appears only one error:

Updated again. Troubleshooting is hard as I’m not seeing these errors…

It works perfectly now, The effect look very good!

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. :slight_smile:

I’m impressed by this, it runs at 60fps on my 4 years-old Intel ® HD Graphics!
I’ll ask @tristan if we can implement this in UpBGE :slight_smile: