I implemented a "shadow-casting" algorithm which looks like this (the video below):
What I want to achive is to create radial gradient effect in the visible area (or rather say area not shaded). Just like a real light source, of which the intensity decreases when the light propagates farther. Area close to the source point (where the cursor is) should be brighter, and the area farther from the light source (and should be visible) should be dimmer.
The input consists of two parts:
Vec<Point2>
, an ordered vector for the corners of visible area. "Ordered" implies that the angles (from light source to the corner) of all the points in vec are sorted (increasing).Point2
.I am new to OpenGL (related stuffs) and Rust nannou therefore I have no idea how to implement this feature. I tried points_colored
function of nannou, which yielded strange results (by coloring all the corner points according to the distance between them and the light source). I read the code from nannou/example
, and found draw/draw_mesh.rs
most related and useful to my use case. Yet it invovles triangles and tessellation?(I guess?), which totally confuses me, though I think that might just be the way. So I wonder:
Any help is appreciated (it doesn't need to be lib-dependent). The code for shadow casting can be seen at Enigmatisms/ShadowCaster
The exact details of how you implement this will depend on the engine/framework/API you are using, which I'm not familiar with, but broadly speaking, the most straightforward way to make this type of gradient is in a fragment shader.
In any modern graphics API, the color of every pixel drawn on the screen is computed by a fragment shader (unless it is the background cleared to a solid color). So, right now, you have some gray pixels. Find the fragment shader that is being used for this (or if it's built into the engine, create a new one), and modify it:
gl_FragCoord
) from that character position point, and modify the color using some function of that distance.That's all you need to do. As long as only distance influences the color, you will get a circular gradient.
You do not need to compute any new geometry, unless the gray color is in fact the screen clear color — which means no fragment shader is being run, and so you would want to add either a full-screen triangle or some level background geometry (which you would need anyway if you wanted to texture the background).
The same goes for your beige buildings that cast the shadows — they will have been drawn by a fragment shader, and that shader should be made aware of the light source if you want them to be lit by it.
For more elaborate effects, you may wish to take a post-processing approach, where all the buildings and shadows are drawn to a texture (or even several, for different “layers”) and another shader pass takes all those pixel inputs and combines them in some way controlled by factors such as the light distance. This is the same thing you would do if you wanted to have visual effects such as bloom, blur, or chromatic aberration.