-
Notifications
You must be signed in to change notification settings - Fork 0
ChickenShadowFunctions
The following are the list of functions used with Shadowy Chickens. It's designed to be very similar to the base Luminous Chickens extension.
Shadowy Chickens adds two more shaders to the mix, shd_cluck_shadows and shd_cluck_unlit_shadows. Use one of those shaders with cluck_apply from the base extension (version 1.7 or later) to render shadows created here in your game.
Returns: shadowmap struct
| Parameter | Type | Description |
|---|---|---|
| resolution | number | The resolution of the shadowmap |
| light_view_mat | Matrix | The view matrix of the shadowmap |
| light_proj_mat | Matrix | The projection matrix of the shadowmap |
Create a shadowmap data structure.
The resolution is the size of the shadowmap. This is up to you, but 2048 seems to be the sweet spot. Use a resolution like 512 to make it look like your game came out in 2004. Use a resolution like 8192 if you like wasting VRAM and fill rate.

Shadowmaps have to be rendered from the point of view of the light in question. It might help to imagine a directional light as an object in space, in which case the view matrix would be the inverse of the light's world matrix. The projection matrix for directional lights should be an orthographic projection with a width and height large enough to encompass what the camera can see, and clipping planes wide enough to encompass the scene.
There's a bit of an art to figuring out how to best fit your shadowmap to the screen (see below).
This creates a surface so you need to call cluck_shadowmap_destroy if you don't want to use it anymore.
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| shadowmap | shadowmap struct | The shadowmap to update |
| resolution | number | The resolution of the shadowmap |
| light_view_mat | Matrix | The view matrix of the shadowmap |
| light_proj_mat | Matrix | The projection matrix of the shadowmap |
Updates an existing shadowmap with the same properties as above. Call this if you ever move the game's main camera and you need shadows to update accordingly.
All parameters are optional and will default to the current values.
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| shadowmap | shadowmap struct | The shadowmap you want to destroy |
Destroy a shadowmap data structure. At least, destroy the surface that goes with it. The struct itself will hang around until it's garbage collected.
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| filter_level | number | Shadowmap filtering level (probably between about 0 and 4) |
Use this function to blur edges around shadows. Usually a small amount of filtering looks better than sharp, pixelated shadows.

Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| bias | number | The shadowmap bias, which should be a very small number |
Shadowmap bias. Setting this too small creates annoying shadow acne. Setting this too high creates an effect called "peter panning" (yes, I'm serious). The default value of 0.0005 should be okay in most cases.

Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| edge_feather | number | Edge feathering level (0 to 0.5) |
Use this to fade out shadows towards the edge of the shadowmap. If you set up your shadowmap to properly fit the bounds of the camera, as in the demo, it can be pretty hard to notice either way.

Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| brightness | number | The brightness of the shadows (0 to 1) |
Set the brightness of the shadows. Setting it to 0 makes shadowed pixels completely black. Setting it to 1 effectively turns shadows off. However, for that it's probably better to use
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| enabled | boolean | Whether shadows should be enabled or not |
Use this to turn off shadowmaps in the main shader. If you do this you probably would also want to skip rendering to the shadowmap yourself.
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| shadowmap | shadowmap struct | The shadowmap you want to begin drawing to |
Shadowmaps require rendering the scene from the point of view of the light. Call this function to begin rendering the shadowmap. You can draw any objects you want to cast shadows here.
It doesn't particularly matter what GameMaker event you do this in, but I usually use Draw Begin for this kind of thing.
For performance reasons, you might consider not drawing small details, or drawing 3D models with a lower level of detail than the visible models. You might also want to skip drawing particles entirely, since it can look kind of weird for those to cast shadows.
It can also be a good idea to reverse the culling direction when you render shadowmaps to mitigate weird self-shadows or shadow acne, but that won't work in situations where you're drawing things like flat planes or objects that don't have a back side.
From here you shouldn't change the shader, target a surface, or generally mess with any GPU pipeline settings until you call cluck_shadowmap_render_end() when you're finished.
Returns: N/A
To be called when you're finished rendering a shadowmap and want to return to normal drawing.
Returns: N/A
| Parameter | Type | Description |
|---|---|---|
| shadowmap | shadowmap struct | The shadowmap you want to use to render your scene |
Once you've rendered your shadowmap, you can use it in your 3D scene. Call this function before calling cluck_apply to target the shadowmap you want to use.
If you google "how to fit shadowmap to camera" you'll find many, many different opinions on how to do this.
The solution I've settled on for the demo is to center the shadowmap on the player and scale its view size up or down based on how high the camera is in the air, and I've found that it works pretty well. Your individual needs may vary.
var size = self.setting_shadow_sizes[self.setting_shadow_resolution];
var xx = self.player.position.x;
var yy = self.player.position.y;
var zz = self.player.position.z;
var cz = self.camera.from.z;
// derived from https://www.desmos.com/calculator/ikqzud26px
var s = 6 * cz + 50 * sqrt(cz);
cluck_shadowmap_update(self.shadowmap, size, matrix_build_lookat(
-5_000 + xx, 5_000 + yy, 5_000 + zz,
xx, yy, zz,
0, 0, 1
), matrix_build_projection_ortho(
s, -s, 1, 10_000
));
cluck_shadowmap_render_begin(self.shadowmap);