Universal Screen Space Reflection(SSR)屏幕空间反射 use ray marching

这是一个能给所有渲染管线使用的SSR shader,解决只有forward+渲染器能使用屏幕空间反射的痛点。

首先需要配置3D后处理,详见godot文档。

HOW TO USE:

1. Create a MeshInstance3D node and place it in your scene.

2. Set its size to 2×2.

3. Enable the “Flip Faces” option.

4. Create a new shader material with this shader.

5. Assign the material to the MeshInstance3D

6. Set the MeshInstance3D as a child of your camera OR set the Geometry property extra_cull_margin as large as possible in the QuadMesh

使用白噪波来进行模糊,记得添加白噪波。

我使用的Godot4.3

 

This is an SSR shader that can be used by all rendering pipelines, solving the pain point that only forward + renderers can use screen space reflection. First, you need to configure 3D postprocessing, see the godot documentation for details. Use white noise to blur, remember to add white noise. I use Godot 4.3.

Shader code
shader_type spatial;
render_mode unshaded;

uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
uniform sampler2D normal_roughness_texture : hint_normal_roughness_texture, repeat_disable, filter_nearest;
uniform sampler2D noise_texture : repeat_enable, filter_linear;

uniform int MAX_STEPS = 60; // 最大步进次数
uniform float step_size = 0.1; // 每次步进的长度
uniform float max_distance = 100.0; // 最大反射距离
uniform float bias=3.0;

void fragment() {
    vec3 col = vec3(0.0); // 反射采样到的颜色,默认是黑色

    // 从深度纹理获取当前像素的深度值
    float depth = textureLod(depth_texture, SCREEN_UV, 0.0).r;

    // 将屏幕坐标转换为摄像机空间坐标
    vec4 camera_space_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
    vec3 pixel_position = camera_space_pos.xyz / camera_space_pos.w; // 摄像机空间中的像素位置

    // 获取法线和粗糙度
    vec4 normal_roughness = texture(normal_roughness_texture, SCREEN_UV);
    vec3 normal = normalize(normal_roughness.xyz * 2.0 - 1.0); // 法线在[-1, 1]范围内
    float roughness = normal_roughness.w;

    // 摄像机视线方向
    vec3 view_dir = normalize(pixel_position);

    // 计算反射方向
    vec3 reflect_dir = reflect(view_dir, normal);
    
    // 使用噪声和粗糙度扰动反射方向
    vec3 noise = texture(noise_texture, SCREEN_UV/vec2(.1)).rgb*vec3(2.0)-vec3(1.4);
    reflect_dir = normalize(mix(reflect_dir, reflect_dir + noise * roughness, roughness));

    // 初始化步进,反射方向的步进大小
    vec3 ray_pos = pixel_position; // 光线起点为像素位置
    vec3 one_step = reflect_dir * step_size; // 每一步的移动距离

    for (int i = 0; i < MAX_STEPS; i++) {
        ray_pos += one_step; // 沿反射方向步进

        // 将摄像机空间坐标转换回屏幕空间
        vec4 clip_pos = PROJECTION_MATRIX * vec4(ray_pos, 1.0);
        vec2 screen_pos = clip_pos.xy / clip_pos.w * 0.5 + 0.5;

        // 检查光线是否越界
        if (screen_pos.x < 0.0 || screen_pos.x > 1.0 || screen_pos.y < 0.0 || screen_pos.y > 1.0) {
            break; // 光线超出屏幕范围时停止步进
        }

        // 从深度纹理获取当前步进点的深度
        float scene_depth = textureLod(depth_texture, screen_pos, 0.0).r;

        // 将深度值转换回摄像机空间
        vec4 projected_pos = INV_PROJECTION_MATRIX * vec4(screen_pos * 2.0 - 1.0, scene_depth, 1.0);
        vec3 scene_position = projected_pos.xyz / projected_pos.w;

        // 如果步进的光线位置比当前深度值靠近摄像机,说明碰撞到了几何体
        if (length(scene_position) < length(ray_pos)) {
			if(abs(ray_pos.z-scene_position.z)<step_size*bias){//判断是否在反射物体的背面,3是一个bias,用于修复缝隙
            vec4 hit_color = texture(screen_texture, screen_pos);
            col = hit_color.rgb; // 采样颜色
			}
            break; // 停止步进
        }

        // 如果光线步进距离超过最大反射距离,则停止
        if (length(ray_pos) > max_distance) {
            break;
        }
    }
	if(depth>0.0){
		depth=1.0;
	}
    // 如果没有找到反射,默认使用黑色(或其他颜色)
    ALBEDO = texture(screen_texture,SCREEN_UV).xyz+col*vec3(depth)*vec3(1.0-roughness);
}
Tags
SSR
The shader code and all code snippets in this post are under GNU GPL v.3 license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Ray Marching Lava Lamp

(NOT NEEDED – USE ORIGINAL) High Quality Post Process Outline (FIXED FOR 4.3+)

Ray-box setup

Subscribe
Notify of
guest

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jooio
Jooio
1 month ago

Can you do universal SSAO?

Jooio
Jooio
1 month ago
Reply to  Jooio

It didn’t work in compatibility mode

not w
not w
1 month ago

not working for mobile