Shader code
#DepthBuffer Compositor Effect#
@tool
extends CompositorEffect
class_name DepthBuffer
var output_texture:RID
@export var texture_size:Vector2 = Vector2(1024,1024)
func _init() -> void:
# print("DepthBuffer: Initializing...") # Debug info
# 使用 PRE_OPAQUE 回调
effect_callback_type = CompositorEffect.EFFECT_CALLBACK_TYPE_PRE_OPAQUE
RenderingServer.call_on_render_thread(_initialize_compute)
# print("DepthBuffer: Effect callback type set to: ", effect_callback_type) # Debug info
func _notification(what:int) -> void:
if what == NOTIFICATION_PREDELETE:
# print("DepthBuffer: Cleaning up...") # Debug info
if output_texture.is_valid():
rd.free_rid(output_texture)
if shader.is_valid():
rd.free_rid(shader)
if nearest_sampler.is_valid():
rd.free_rid(nearest_sampler)
var rd : RenderingDevice
var nearest_sampler: RID
var shader : RID
var pipeline : RID
func _initialize_compute()->void:
# print("DepthBuffer: Initializing compute...") # Debug info
rd = RenderingServer.get_rendering_device()
if !rd:
# print("DepthBuffer: No rendering device!") # Debug info
return
# Create output texture
var format := RDTextureFormat.new()
format.width = texture_size.x
format.height = texture_size.y
format.format = RenderingDevice.DATA_FORMAT_R32_SFLOAT
format.usage_bits = RenderingDevice.TEXTURE_USAGE_STORAGE_BIT | RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT
output_texture = rd.texture_create(format, RDTextureView.new(), [])
# print("DepthBuffer: Created output texture") # Debug info
var sampler_state: RDSamplerState = RDSamplerState.new()
sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_LINEAR
sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_LINEAR
sampler_state.repeat_u = RenderingDevice.SAMPLER_REPEAT_MODE_REPEAT
sampler_state.repeat_v = RenderingDevice.SAMPLER_REPEAT_MODE_REPEAT
nearest_sampler = rd.sampler_create(sampler_state)
# print("DepthBuffer: Created sampler") # Debug info
var shader_file: RDShaderFile = load("res://RenderingEffects/DepthBuffer/depth_buffer.glsl")
var shader_spirv: RDShaderSPIRV = shader_file.get_spirv()
shader = rd.shader_create_from_spirv(shader_spirv)
pipeline = rd.compute_pipeline_create(shader)
# print("DepthBuffer: Created shader and pipeline") # Debug info
func _render_callback(p_effect_callback_type:int, p_render_data: RenderData)->void:
# print("DepthBuffer: Render callback called with type: ", p_effect_callback_type) # Debug info
if not output_texture.is_valid():
# print("DepthBuffer: Output texture is invalid!") # Debug info
return
if rd and p_effect_callback_type == CompositorEffect.EFFECT_CALLBACK_TYPE_PRE_OPAQUE:
var render_scene_buffers : RenderSceneBuffersRD = p_render_data.get_render_scene_buffers()
if render_scene_buffers:
var size:Vector2i = Vector2i(texture_size)
# print("DepthBuffer: Using texture size: ", size) # Debug info
var x_groups:int = (size.x - 1) / 16 + 1
var y_groups:int = (size.y - 1) / 16 + 1
var view_count:int = render_scene_buffers.get_view_count()
# print("DepthBuffer: View count: ", view_count) # Debug info
for view in range(view_count):
var depth_tex: RID = render_scene_buffers.get_depth_layer(view)
if not depth_tex.is_valid():
# print("DepthBuffer: Invalid depth texture for view ", view) # Debug info
continue
# print("DepthBuffer: Processing depth texture for view ", view) # Debug info
var depth_uniform : RDUniform = RDUniform.new()
depth_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
depth_uniform.binding = 0
depth_uniform.add_id(nearest_sampler)
depth_uniform.add_id(depth_tex)
var depth_copy_uniform : RDUniform = RDUniform.new()
depth_copy_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE
depth_copy_uniform.binding = 1
depth_copy_uniform.add_id(output_texture)
var params: PackedFloat32Array = PackedFloat32Array()
params.push_back(size.x)
params.push_back(size.y)
var params_buffer: RID = rd.storage_buffer_create(params.size()* 4, params.to_byte_array())
var params_uniform : RDUniform = RDUniform.new()
params_uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_STORAGE_BUFFER
params_uniform.binding = 2
params_uniform.add_id(params_buffer)
var uniform_set: RID = rd.uniform_set_create([depth_uniform, depth_copy_uniform, params_uniform],shader,0)
var compute_list := rd.compute_list_begin()
rd.compute_list_bind_compute_pipeline(compute_list, pipeline)
rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0)
rd.compute_list_dispatch(compute_list, x_groups, y_groups, 1)
rd.compute_list_end()
rd.free_rid(uniform_set)
rd.free_rid(params_buffer)
else:
# print("DepthBuffer: No render scene buffers!") # Debug info
pass
else:
# print("DepthBuffer: Invalid render device or wrong callback type!") # Debug info
pass
#Depth Buffer GLSL File#
#[compute]
#version 450
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
layout(set = 0, binding = 0) uniform sampler2D depth_buffer;
layout(r32f, set = 0, binding = 1) uniform restrict writeonly image2D depth_copy;
layout(set = 0, binding = 2, std430) restrict buffer Params {
vec2 resolution;
} params;
void main() {
ivec2 xy = ivec2(gl_GlobalInvocationID.xy);
vec2 uv = vec2(xy) / params.resolution;
float depth = texture(depth_buffer, uv).r;
// 直接输出原始深度值,不做任何处理
imageStore(depth_copy, xy, vec4(depth, 0.0, 0.0, 0.0));
}
#Custom Decal GDscript#
extends MeshInstance3D
class_name DecalBox
@onready var depth_camera: Camera3D = %DepthCamera
@onready var half_depth_camera: Camera3D = %HalfDepthCamera
@onready var fov: Node3D = %FOV
func _ready() -> void:
await RenderingServer.frame_post_draw
var effect : DepthBuffer = depth_camera.compositor.compositor_effects[0]
var texture_rd = Texture2DRD.new()
texture_rd.texture_rd_rid = effect.output_texture
get_active_material(0).set_shader_parameter("depth_camera_texture", texture_rd)
var effect1 : DepthBuffer = half_depth_camera.compositor.compositor_effects[0]
var texture_rd1 = Texture2DRD.new()
texture_rd1.texture_rd_rid = effect1.output_texture
get_active_material(0).set_shader_parameter("half_depth_camera_texture", texture_rd1)
func _process(delta: float) -> void:
global_rotation.y = 0.0
depth_camera.fov = rad_to_deg(get_active_material(0).get_shader_parameter("fov_angle") * TAU)
half_depth_camera.fov = depth_camera.fov
get_active_material(0).set_shader_parameter("decal_inv_transform", global_transform.affine_inverse())
var view_matrix: Transform3D = depth_camera.global_transform.affine_inverse()
var projection_matrix: Projection = depth_camera.get_camera_projection()
get_active_material(0).set_shader_parameter("depth_camera_view_matrix",view_matrix)
get_active_material(0).set_shader_parameter("depth_camera_projection_matrix",projection_matrix)
get_active_material(0).set_shader_parameter("rotation",fov.global_rotation.y)
#CustomDecal Shader :MeshInstance-Box instance#
shader_type spatial;
render_mode cull_back,unshaded;
uniform sampler2D depth_texture : hint_depth_texture;
uniform sampler2D depth_camera_texture;
uniform sampler2D half_depth_camera_texture;
uniform sampler2D normal_texture : hint_normal_roughness_texture;
uniform mat4 decal_inv_transform;
uniform mat4 depth_camera_view_matrix;
uniform mat4 depth_camera_projection_matrix;
uniform vec4 fov_color : source_color;
uniform float fov_angle : hint_range(0.0, 0.5) = 0.25;
uniform int stripe_count : hint_range(1, 500) = 100; // 斑马圈数量
uniform float rotation : hint_range(-3.14, 3.14) = 0.0; // 旋转角度(弧度)
uniform float normal_fade : hint_range(0.0, 1.0) = 0.4;
uniform float full_radius :hint_range (0.0,0.5,0.01) = 0.25;
void fragment() {
float depth = texture(depth_texture, SCREEN_UV).x;
vec3 ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth);
vec4 world = INV_VIEW_MATRIX * INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
vec3 world_position = world.xyz / world.w;
mat4 depth_camera_view_project_matrix = depth_camera_projection_matrix * depth_camera_view_matrix;
vec4 depth_camera_space_pos = depth_camera_view_project_matrix * vec4(world_position, 1.0);
vec3 shadow_uv = depth_camera_space_pos.xyz / depth_camera_space_pos.w;
shadow_uv = shadow_uv * 0.5 + 0.5; // NDC to UV
shadow_uv.y = 1.0 - shadow_uv.y; // 反转Y轴
float shadow_depth = texture(depth_camera_texture, clamp(shadow_uv.xy, 0.0, 1.0)).r;
float half_shadow_depth = texture(half_depth_camera_texture, clamp(shadow_uv.xy, 0.0, 1.0)).r;
// 世界坐标转到 Cube 局部空间
vec4 local_pos = decal_inv_transform * vec4(world_position, 1.0);
// 视角控制
vec2 uv = local_pos.xz;
vec2 dir = uv;
float r = length(dir);
float angle = atan(dir.y, dir.x);
// 应用旋转和视角限制
angle = mod(angle + rotation + PI * 0.5, 2.0 * PI);
float normalized_angle = angle / (2.0 * PI);
float half_fov = fov_angle * 0.5;
// 斑马线效果
float stripe = mod(floor(r * float(stripe_count)), 2.0);
// 检查半径范围
if (r > 0.5 || r < 0.02) {
discard;
}
// 检查是否在视角范围内
if (normalized_angle > half_fov && normalized_angle < (1.0 - half_fov)) {
discard;
}
// 法线检查
vec3 normal = normalize(texture(normal_texture, SCREEN_UV).xyz * 2.0 - 1.0);
float fade = clamp(normal.y, 0.0, 1.0);
if (fade < normal_fade) {
discard;
}
bool visual_area = shadow_uv.z <= 1.0 - shadow_depth + 0.00001;
bool half_visual_area = shadow_uv.z <= 1.0 - half_shadow_depth + 0.00001;
if (visual_area) {
if (r > full_radius || !half_visual_area) {
if (stripe >= 1.0) discard;
}
ALBEDO = fov_color.rgb;
ALPHA = fov_color.a;
} else {
ALBEDO = vec3(.0,.0,.0);
ALPHA = 0.5;
}
}
Live Preview
Tags
CompositorEffect,
FOV,
Shadow Mapping