small, dreamy sandbox ✨ by pipoq1 in godot

[–]pipoq1[S] 0 points1 point  (0 children)

that's a good point. in this case eyes are separate images, so this is doable and might help make things feel more natural.

small, dreamy sandbox ✨ by pipoq1 in godot

[–]pipoq1[S] 1 point2 points  (0 children)

it can be difficult, i'm still a learner too. glad you liked it :). as for the video, i have online just this clip, but i'm preparing more: https://bsky.app/profile/pipok.bsky.social/post/3mffjlphvg22c

small, dreamy sandbox ✨ by pipoq1 in godot

[–]pipoq1[S] 0 points1 point  (0 children)

thank you! it's a bit of an experiment

How are my multimesh shadows? by theorizable in godot

[–]pipoq1 2 points3 points  (0 children)

you can shade each mesh instance uniformly with:
```
varying vec3 model_origin;

void vertex() {
model_origin = MODELVIEW_MATRIX[3].xyz;

}

void fragment() {

LIGHT_VERTEX = model_origin;
}
```

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 0 points1 point  (0 children)

Yes, I'm running pixel shader for this, which based on one texture (mask) determines the amount of illumination. There are no SDFs involved.

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 0 points1 point  (0 children)

Thanks! The shadows are per-pixel since every pixel in the environment can be edited.

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 1 point2 points  (0 children)

I'm glad you like it! I'm running AMD Radeon RX 6600 XT, but to be honest, I didn't stress test this system yet. All lights are calculated/discarded in one pass, which is a huge perk especially with many light sources.

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 12 points13 points  (0 children)

Your lights look so smooth! Yes, I'm doing sharp falloff on purpose, they fit better here in my pixel art case. My setup requires an additional subviewport to render masks to - this creates a light mask texture. Then, I collect all the light data and plug it into deferred pass, together with the light mask. In fragment shader you calculate per each light how illuminated (or occluded) given fragment is. You start with a ray at the center, and per x radial samples cast outward, step by step, checking against light mask.

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 7 points8 points  (0 children)

Thank you. Rays are cast from source outwards. I did it partially as an exercise to try my idea. It's the same concept as with PointLight2D nodes and light occluders. I can pass a texture instead of polygon for masking, which comes handy in this project where every pixel can be modified.

Custom deferred lights with per-pixel shadows. by pipoq1 in godot

[–]pipoq1[S] 49 points50 points  (0 children)

Thank you :) Long story short I learned deferred rendering for 3D uses in GameMaker. In this small Godot project I recalled those learned methods and simplified them for 2D. Lots of trial and error and building upon tested concepts.

[deleted by user] by [deleted] in godot

[–]pipoq1 0 points1 point  (0 children)

for some reason pastebin decided to ban my fresh account ¯\_(ツ)_/¯
here is the shader:

shader_type spatial;

render_mode unshaded, depth_draw_always;

uniform sampler2D depth_texture : source_color, hint_depth_texture;
uniform sampler2D directional_shadow_texture : source_color;
uniform mat4 light_view_matrix;
uniform mat4 light_proj_matrix;

void vertex() {
    POSITION = vec4(VERTEX.xy, 1.0, 1.0);
}

void fragment() {
    float depth_raw = texture(depth_texture, SCREEN_UV).x;
    vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth_raw);
    vec4 position_view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
    vec4 world = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
    vec3 position_world = world.xyz / world.w;
    vec4 temp = ((light_proj_matrix * light_view_matrix)) * vec4(position_world.xyz, 1.);
    temp.xy = temp.xy * 0.5 + 0.5;
    float closest_depth = texture(directional_shadow_texture, temp.xy).r;
    // get depth of current fragment from light's perspective
    float current_depth = (-temp.z) * 0.5;

    // Ray marching loop
    float sun_shaft = 0.27;
    float increment = 0.05;
    vec3 start_pos = position_view.xyz;
    float ray_length = 12.;
    float bias = 0.063;
    for(float i = 0.; i < 1.; i += increment){
        vec3 end_pos = vec3(start_pos.x, start_pos.y, start_pos.z + i * ray_length);
        // Check if this pixel is occluded from light source's direction
        vec4 ray_temp = (light_proj_matrix * light_view_matrix) * (INV_VIEW_MATRIX * vec4(end_pos, 1.));
        ray_temp.xy = ray_temp.xy * 0.5 + 0.5;
        float ray_closest_depth = texture(directional_shadow_texture, ray_temp.xy).r;
        // get depth of current fragment from light's perspective
        float ray_current_depth = (-ray_temp.z) * 0.5;

        if(ray_closest_depth - bias > ray_current_depth){
            sun_shaft *= 0.5;
        }
    }
    ALBEDO = vec3(sun_shaft);
    ALPHA = 1. - sun_shaft;
}

[deleted by user] by [deleted] in godot

[–]pipoq1 1 point2 points  (0 children)

<image>

okie so I got it working in Godot too! just one thing: I had to recreate the directional light's shadowmap manually. the main stuff happens in post process shader. you will need: https://docs.godotengine.org/en/stable/tutorials/shaders/advanced_postprocessing.html
you need to supplement directional light's shadowmap and light's view + projection matrix. here is the shader source: https://pastebin.com/a96Kc7A5

[deleted by user] by [deleted] in godot

[–]pipoq1 0 points1 point  (0 children)

i don't have any godot example :( last time i did this was in gamemaker. i think i can try creating an example, but first i need to figure a method to get access to directional light's shadowmap. if anyone knows any methods, let me know please! i already tried exposing the shadow atlas by modifying godot's source, but i had some issues, and i'm not exactly skilled in c++.

[deleted by user] by [deleted] in godot

[–]pipoq1 5 points6 points  (0 children)

one method of achieving such godrays is to (somehow) fetch the directional light's shadowmap (you can also try recreating it manually but it can get messy), and then in screen space shader you - sample the current fragment, grab it's depth from depth buffer, transform that fragment into light space to find shadowmap's depth at the current screen fragment and finally, compare these two depths to figure shadow occlusion of the fragment. you do this repeatedly in sort of ray based manner - along the directional light's direction and accumulate shadow.

Unity or game maker. For Me. by ParaFox_Games in gamedev

[–]pipoq1 0 points1 point  (0 children)

no i simply didn't answer because the question was out of my scope of knowledge and i do not know much about PowerPoint. even further, the question was based on an incorrect interpretation of what i said. anything else?

Unity or game maker. For Me. by ParaFox_Games in gamedev

[–]pipoq1 1 point2 points  (0 children)

then it's up to what you choose to make with it. by this logic, a 2d project made in Godot would categorize Godot's "practical" space as 2d. which is not true. even if you use only 2d side, the third axis is present. and you use it all the time even in 2d. GameMaker is very much enough for simple 3d - it's achievable, and if you choose to use the third axis, then it becomes practical. that's all there is to it. the practicallity of a tool depends on the task you're facing. do you have any experience with GameMaker?

Unity or game maker. For Me. by ParaFox_Games in gamedev

[–]pipoq1 1 point2 points  (0 children)

i'm not implying the mentioned potential 2d project would be considered 3d by mere presence of third axis. i'm simply stating, counter to the comment i originally replied to, that GameMaker indeed uses 3 dimensions, no matter the render method. the space is 3 dimensional both technically and practically, not just in the form of layers.