Fix:修复了material最大只能加载255个的问题
parent
dbf5b8579c
commit
2e850c40ff
Binary file not shown.
|
|
@ -12,11 +12,14 @@ constexpr int MAX_RAY_DEPTH = 8;
|
||||||
/// @brief Default samples per pixel for ray tracing
|
/// @brief Default samples per pixel for ray tracing
|
||||||
constexpr int DEFAULT_SPP = 1;
|
constexpr int DEFAULT_SPP = 1;
|
||||||
|
|
||||||
/// @brief G-Buffer attachment indices
|
/// @brief G-Buffer texture types
|
||||||
constexpr int GBUFFER_POSITION = 0;
|
enum GBufferTextureType {
|
||||||
constexpr int GBUFFER_NORMAL = 1;
|
GBUFFER_POSITION = 0,
|
||||||
constexpr int GBUFFER_ALBEDO = 2;
|
GBUFFER_NORMAL = 1,
|
||||||
constexpr int GBUFFER_COUNT = 3;
|
GBUFFER_ALBEDO = 2,
|
||||||
|
GBUFFER_MATERIAL_ID = 3,
|
||||||
|
GBUFFER_TEXTURE_COUNT = 4
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief Compute shader work group size
|
/// @brief Compute shader work group size
|
||||||
constexpr int COMPUTE_GROUP_SIZE_X = 16;
|
constexpr int COMPUTE_GROUP_SIZE_X = 16;
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ private:
|
||||||
uint width_;
|
uint width_;
|
||||||
uint height_;
|
uint height_;
|
||||||
FramebufferHandle fbo_;
|
FramebufferHandle fbo_;
|
||||||
TextureHandle textures_[GBUFFER_COUNT];
|
TextureHandle textures_[GBUFFER_TEXTURE_COUNT];
|
||||||
TextureHandle depth_texture_;
|
TextureHandle depth_texture_;
|
||||||
|
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ in VS_OUT {
|
||||||
layout(location = 0) out vec4 g_position;
|
layout(location = 0) out vec4 g_position;
|
||||||
layout(location = 1) out vec4 g_normal;
|
layout(location = 1) out vec4 g_normal;
|
||||||
layout(location = 2) out vec4 g_albedo;
|
layout(location = 2) out vec4 g_albedo;
|
||||||
layout(location = 3) out vec4 g_material;
|
layout(location = 3) out uvec4 g_material_id;
|
||||||
|
|
||||||
// Material uniforms
|
// Material uniforms
|
||||||
uniform vec3 u_albedo;
|
uniform vec3 u_albedo;
|
||||||
|
|
@ -24,7 +24,7 @@ uniform float u_metallic;
|
||||||
uniform float u_roughness;
|
uniform float u_roughness;
|
||||||
uniform float u_ior;
|
uniform float u_ior;
|
||||||
uniform vec3 u_emission;
|
uniform vec3 u_emission;
|
||||||
uniform uint u_material_type;
|
uniform uint u_material_id;
|
||||||
|
|
||||||
uniform bool u_has_albedo_map;
|
uniform bool u_has_albedo_map;
|
||||||
uniform sampler2D u_albedo_map;
|
uniform sampler2D u_albedo_map;
|
||||||
|
|
@ -45,5 +45,5 @@ void main() {
|
||||||
g_albedo = vec4(albedo, 1.0);
|
g_albedo = vec4(albedo, 1.0);
|
||||||
|
|
||||||
// Material properties
|
// Material properties
|
||||||
g_material = vec4(u_metallic, u_roughness, u_ior, float(u_material_type));
|
g_material_id = uvec4(u_material_id, 0u, 0u, 0u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,28 +19,66 @@
|
||||||
#define LIGHT_POINT 1
|
#define LIGHT_POINT 1
|
||||||
#define LIGHT_SPOT 2
|
#define LIGHT_SPOT 2
|
||||||
|
|
||||||
// Structures
|
// Material structure - 使用 vec4 确保对齐
|
||||||
struct Material {
|
struct Material {
|
||||||
vec3 albedo;
|
vec4 albedo_metallic; // xyz = albedo, w = metallic
|
||||||
float metallic;
|
vec4 emission_roughness; // xyz = emission, w = roughness
|
||||||
vec3 emission;
|
|
||||||
float roughness;
|
|
||||||
int type;
|
int type;
|
||||||
float ior;
|
float ior;
|
||||||
vec2 padding;
|
float padding1;
|
||||||
|
float padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Light structure - 使用 vec4 确保对齐
|
||||||
struct Light {
|
struct Light {
|
||||||
vec3 position;
|
vec4 position_type; // xyz = position, w = type
|
||||||
int type;
|
vec4 direction_intensity; // xyz = direction, w = intensity
|
||||||
vec3 direction;
|
vec4 color_range; // xyz = color, w = range
|
||||||
float intensity;
|
vec4 spot_angles; // xy = spot angles, zw = padding
|
||||||
vec3 color;
|
|
||||||
float range;
|
|
||||||
vec2 spot_angles; // inner, outer
|
|
||||||
vec2 padding;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 辅助函数:从 Material 获取属性
|
||||||
|
vec3 get_material_albedo(Material mat) {
|
||||||
|
return mat.albedo_metallic.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_material_metallic(Material mat) {
|
||||||
|
return mat.albedo_metallic.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 get_material_emission(Material mat) {
|
||||||
|
return mat.emission_roughness.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_material_roughness(Material mat) {
|
||||||
|
return mat.emission_roughness.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助函数:从 Light 获取属性
|
||||||
|
vec3 get_light_position(Light light) {
|
||||||
|
return light.position_type.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_light_type(Light light) {
|
||||||
|
return int(light.position_type.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 get_light_direction(Light light) {
|
||||||
|
return light.direction_intensity.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_light_intensity(Light light) {
|
||||||
|
return light.direction_intensity.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 get_light_color(Light light) {
|
||||||
|
return light.color_range.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_light_range(Light light) {
|
||||||
|
return light.color_range.w;
|
||||||
|
}
|
||||||
|
|
||||||
struct Ray {
|
struct Ray {
|
||||||
vec3 origin;
|
vec3 origin;
|
||||||
vec3 direction;
|
vec3 direction;
|
||||||
|
|
@ -153,10 +191,11 @@ layout(local_size_x = 16, local_size_y = 16) in;
|
||||||
layout(binding = 0, rgba32f) uniform readonly image2D g_position;
|
layout(binding = 0, rgba32f) uniform readonly image2D g_position;
|
||||||
layout(binding = 1, rgba32f) uniform readonly image2D g_normal;
|
layout(binding = 1, rgba32f) uniform readonly image2D g_normal;
|
||||||
layout(binding = 2, rgba8) uniform readonly image2D g_albedo;
|
layout(binding = 2, rgba8) uniform readonly image2D g_albedo;
|
||||||
|
layout(binding = 3, r32ui) uniform readonly uimage2D g_material_id;
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
layout(binding = 3, rgba32f) uniform image2D output_image;
|
layout(binding = 4, rgba32f) uniform image2D output_image;
|
||||||
layout(binding = 4, rgba32f) uniform image2D accumulation_image;
|
layout(binding = 5, rgba32f) uniform image2D accumulation_image;
|
||||||
|
|
||||||
// Scene data
|
// Scene data
|
||||||
layout(std430, binding = 0) readonly buffer MaterialBuffer {
|
layout(std430, binding = 0) readonly buffer MaterialBuffer {
|
||||||
|
|
@ -182,21 +221,35 @@ vec3 evaluate_direct_lighting(vec3 position, vec3 normal, vec3 view_dir,
|
||||||
Material material, inout uint seed) {
|
Material material, inout uint seed) {
|
||||||
vec3 direct_light = vec3(0.0);
|
vec3 direct_light = vec3(0.0);
|
||||||
|
|
||||||
|
// 获取材质属性
|
||||||
|
vec3 mat_albedo = get_material_albedo(material);
|
||||||
|
float mat_metallic = get_material_metallic(material);
|
||||||
|
float mat_roughness = get_material_roughness(material);
|
||||||
|
|
||||||
for (uint i = 0u; i < u_light_count; i++) {
|
for (uint i = 0u; i < u_light_count; i++) {
|
||||||
Light light = lights[i];
|
Light light = lights[i];
|
||||||
|
|
||||||
|
// 获取光源属性
|
||||||
|
vec3 light_pos = get_light_position(light);
|
||||||
|
int light_type = get_light_type(light);
|
||||||
|
vec3 light_dir_raw = get_light_direction(light);
|
||||||
|
float light_intensity = get_light_intensity(light);
|
||||||
|
vec3 light_color = get_light_color(light);
|
||||||
|
float light_range = get_light_range(light);
|
||||||
|
|
||||||
vec3 light_dir;
|
vec3 light_dir;
|
||||||
float light_distance;
|
float light_distance;
|
||||||
float attenuation = 1.0;
|
float attenuation = 1.0;
|
||||||
|
|
||||||
if (light.type == LIGHT_POINT) {
|
if (light_type == LIGHT_POINT) {
|
||||||
vec3 to_light = light.position - position;
|
vec3 to_light = light_pos - position;
|
||||||
light_distance = length(to_light);
|
light_distance = length(to_light);
|
||||||
light_dir = to_light / light_distance;
|
light_dir = to_light / light_distance;
|
||||||
attenuation = 1.0 / max(light_distance * light_distance, 0.01);
|
attenuation = 1.0 / max(light_distance * light_distance, 0.01);
|
||||||
|
|
||||||
if (light_distance > light.range) continue;
|
if (light_distance > light_range) continue;
|
||||||
} else if (light.type == LIGHT_DIRECTIONAL) {
|
} else if (light_type == LIGHT_DIRECTIONAL) {
|
||||||
light_dir = normalize(-light.direction);
|
light_dir = normalize(-light_dir_raw);
|
||||||
light_distance = MAX_FLOAT;
|
light_distance = MAX_FLOAT;
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -209,20 +262,20 @@ vec3 evaluate_direct_lighting(vec3 position, vec3 normal, vec3 view_dir,
|
||||||
float NdotV = max(dot(normal, view_dir), 0.0);
|
float NdotV = max(dot(normal, view_dir), 0.0);
|
||||||
|
|
||||||
// PBR lighting
|
// PBR lighting
|
||||||
vec3 F0 = mix(vec3(0.04), material.albedo, material.metallic);
|
vec3 F0 = mix(vec3(0.04), mat_albedo, mat_metallic);
|
||||||
vec3 F = fresnel_schlick(max(dot(H, view_dir), 0.0), F0);
|
vec3 F = fresnel_schlick(max(dot(H, view_dir), 0.0), F0);
|
||||||
float D = distribution_ggx(normal, H, max(material.roughness, 0.04));
|
float D = distribution_ggx(normal, H, max(mat_roughness, 0.04));
|
||||||
float G = geometry_smith(normal, view_dir, light_dir, material.roughness);
|
float G = geometry_smith(normal, view_dir, light_dir, mat_roughness);
|
||||||
|
|
||||||
vec3 numerator = D * G * F;
|
vec3 numerator = D * G * F;
|
||||||
float denominator = 4.0 * NdotV * NdotL + EPSILON;
|
float denominator = 4.0 * NdotV * NdotL + EPSILON;
|
||||||
vec3 specular = numerator / denominator;
|
vec3 specular = numerator / denominator;
|
||||||
|
|
||||||
vec3 kS = F;
|
vec3 kS = F;
|
||||||
vec3 kD = (vec3(1.0) - kS) * (1.0 - material.metallic);
|
vec3 kD = (vec3(1.0) - kS) * (1.0 - mat_metallic);
|
||||||
|
|
||||||
vec3 radiance = light.color * light.intensity * attenuation;
|
vec3 radiance = light_color * light_intensity * attenuation;
|
||||||
direct_light += (kD * material.albedo * INV_PI + specular) * radiance * NdotL;
|
direct_light += (kD * mat_albedo * INV_PI + specular) * radiance * NdotL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,10 +290,26 @@ void main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============ DEBUG MODE 6: 显示材质Metallic ============
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
uint mat_id = imageLoad(g_material_id, pixel_coords).r;
|
||||||
|
if (imageLoad(g_position, pixel_coords).w > 0.5 && mat_id < uint(materials.length())) {
|
||||||
|
Material mat = materials[mat_id];
|
||||||
|
float metallic_vis = get_material_metallic(mat);
|
||||||
|
imageStore(output_image, pixel_coords, vec4(metallic_vis, metallic_vis, metallic_vis, 1.0));
|
||||||
|
} else {
|
||||||
|
imageStore(output_image, pixel_coords, vec4(0.0, 0.0, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Read G-Buffer
|
// Read G-Buffer
|
||||||
vec4 position_data = imageLoad(g_position, pixel_coords);
|
vec4 position_data = imageLoad(g_position, pixel_coords);
|
||||||
vec4 normal_data = imageLoad(g_normal, pixel_coords);
|
vec4 normal_data = imageLoad(g_normal, pixel_coords);
|
||||||
vec4 albedo_data = imageLoad(g_albedo, pixel_coords);
|
vec4 albedo_data = imageLoad(g_albedo, pixel_coords);
|
||||||
|
uint material_id = imageLoad(g_material_id, pixel_coords).r;
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
if (position_data.w < 0.5) {
|
if (position_data.w < 0.5) {
|
||||||
|
|
@ -254,11 +323,6 @@ void main() {
|
||||||
vec3 normal = normalize(normal_data.xyz);
|
vec3 normal = normalize(normal_data.xyz);
|
||||||
vec3 albedo = albedo_data.rgb;
|
vec3 albedo = albedo_data.rgb;
|
||||||
|
|
||||||
// 关键修复:从G-Buffer的alpha通道读取material_id
|
|
||||||
// 注意:albedo_data是从RGBA8纹理读取的,alpha值范围是[0,1]
|
|
||||||
// 我们需要将其转换回整数ID
|
|
||||||
uint material_id = uint(albedo_data.a * 255.0 + 0.5);
|
|
||||||
|
|
||||||
// Initialize random seed
|
// Initialize random seed
|
||||||
uint seed = uint(pixel_coords.x) + uint(pixel_coords.y) * uint(image_size.x) + u_frame_count * 719393u;
|
uint seed = uint(pixel_coords.x) + uint(pixel_coords.y) * uint(image_size.x) + u_frame_count * 719393u;
|
||||||
|
|
||||||
|
|
@ -269,20 +333,17 @@ void main() {
|
||||||
uint mat_count = uint(materials.length());
|
uint mat_count = uint(materials.length());
|
||||||
|
|
||||||
if (material_id < mat_count) {
|
if (material_id < mat_count) {
|
||||||
// 从SSBO读取材质
|
|
||||||
material = materials[material_id];
|
material = materials[material_id];
|
||||||
} else {
|
} else {
|
||||||
// 使用G-Buffer中的albedo作为fallback
|
// Fallback - 创建默认材质
|
||||||
material.albedo = albedo;
|
material.albedo_metallic = vec4(albedo, 0.0);
|
||||||
material.metallic = 0.0;
|
material.emission_roughness = vec4(0.0, 0.0, 0.0, 0.5);
|
||||||
material.roughness = 0.5;
|
|
||||||
material.emission = vec3(0.0);
|
|
||||||
material.type = MATERIAL_DIFFUSE;
|
material.type = MATERIAL_DIFFUSE;
|
||||||
material.ior = 1.5;
|
material.ior = 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add emission
|
// Add emission
|
||||||
color += material.emission;
|
color += get_material_emission(material);
|
||||||
|
|
||||||
// Direct lighting
|
// Direct lighting
|
||||||
vec3 view_dir = normalize(u_camera_position - position);
|
vec3 view_dir = normalize(u_camera_position - position);
|
||||||
|
|
@ -292,7 +353,7 @@ void main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ambient lighting
|
// Ambient lighting
|
||||||
color += material.albedo * 0.05;
|
color += get_material_albedo(material) * 0.05;
|
||||||
|
|
||||||
// Clamp
|
// Clamp
|
||||||
color = clamp(color, vec3(0.0), vec3(10.0));
|
color = clamp(color, vec3(0.0), vec3(10.0));
|
||||||
|
|
@ -307,197 +368,3 @@ void main() {
|
||||||
imageStore(accumulation_image, pixel_coords, vec4(color, 1.0));
|
imageStore(accumulation_image, pixel_coords, vec4(color, 1.0));
|
||||||
imageStore(output_image, pixel_coords, vec4(color, 1.0));
|
imageStore(output_image, pixel_coords, vec4(color, 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout(local_size_x = 16, local_size_y = 16) in;
|
|
||||||
//
|
|
||||||
// // G-Buffer inputs
|
|
||||||
// layout(binding = 0, rgba32f) uniform readonly image2D g_position;
|
|
||||||
// layout(binding = 1, rgba32f) uniform readonly image2D g_normal;
|
|
||||||
// layout(binding = 2, rgba8) uniform readonly image2D g_albedo;
|
|
||||||
//
|
|
||||||
// // Output
|
|
||||||
// layout(binding = 3, rgba32f) uniform image2D output_image;
|
|
||||||
// layout(binding = 4, rgba32f) uniform image2D accumulation_image;
|
|
||||||
//
|
|
||||||
// // Scene data
|
|
||||||
// layout(std430, binding = 0) readonly buffer MaterialBuffer {
|
|
||||||
// Material materials[];
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// layout(std430, binding = 1) readonly buffer LightBuffer {
|
|
||||||
// Light lights[];
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// // Uniforms
|
|
||||||
// uniform uint u_frame_count;
|
|
||||||
// uniform uint u_samples_per_pixel;
|
|
||||||
// uniform uint u_max_depth;
|
|
||||||
// uniform uint u_light_count;
|
|
||||||
// uniform vec3 u_camera_position;
|
|
||||||
// uniform mat4 u_inv_view_projection;
|
|
||||||
// uniform bool u_enable_accumulation;
|
|
||||||
// uniform bool u_use_bvh;
|
|
||||||
//
|
|
||||||
// // Cosine-weighted hemisphere sampling
|
|
||||||
// vec3 cosine_weighted_hemisphere(vec3 normal, inout uint seed) {
|
|
||||||
// vec2 r = random_vec2(seed);
|
|
||||||
// float r1 = 2.0 * PI * r.x;
|
|
||||||
// float r2 = r.y;
|
|
||||||
// float r2s = sqrt(r2);
|
|
||||||
//
|
|
||||||
// vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
|
||||||
// vec3 tangent = normalize(cross(up, normal));
|
|
||||||
// vec3 bitangent = cross(normal, tangent);
|
|
||||||
//
|
|
||||||
// vec3 dir = tangent * cos(r1) * r2s + bitangent * sin(r1) * r2s + normal * sqrt(1.0 - r2);
|
|
||||||
// return normalize(dir);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Evaluate direct lighting
|
|
||||||
// vec3 evaluate_direct_lighting(vec3 position, vec3 normal, vec3 view_dir,
|
|
||||||
// Material material, inout uint seed) {
|
|
||||||
// vec3 direct_light = vec3(0.0);
|
|
||||||
//
|
|
||||||
// for (uint i = 0u; i < u_light_count; i++) {
|
|
||||||
// Light light = lights[i];
|
|
||||||
// vec3 light_dir;
|
|
||||||
// float light_distance;
|
|
||||||
// float attenuation = 1.0;
|
|
||||||
//
|
|
||||||
// if (light.type == LIGHT_POINT) {
|
|
||||||
// vec3 to_light = light.position - position;
|
|
||||||
// light_distance = length(to_light);
|
|
||||||
// light_dir = to_light / light_distance;
|
|
||||||
// attenuation = 1.0 / max(light_distance * light_distance, 0.01);
|
|
||||||
//
|
|
||||||
// if (light_distance > light.range) continue;
|
|
||||||
// } else if (light.type == LIGHT_DIRECTIONAL) {
|
|
||||||
// light_dir = normalize(-light.direction);
|
|
||||||
// light_distance = MAX_FLOAT;
|
|
||||||
// } else {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// float NdotL = max(dot(normal, light_dir), 0.0);
|
|
||||||
//
|
|
||||||
// if (NdotL > 0.0) {
|
|
||||||
// vec3 H = normalize(view_dir + light_dir);
|
|
||||||
// float NdotV = max(dot(normal, view_dir), 0.0);
|
|
||||||
//
|
|
||||||
// // PBR lighting
|
|
||||||
// vec3 F0 = mix(vec3(0.04), material.albedo, material.metallic);
|
|
||||||
// vec3 F = fresnel_schlick(max(dot(H, view_dir), 0.0), F0);
|
|
||||||
// float D = distribution_ggx(normal, H, max(material.roughness, 0.04));
|
|
||||||
// float G = geometry_smith(normal, view_dir, light_dir, material.roughness);
|
|
||||||
//
|
|
||||||
// vec3 numerator = D * G * F;
|
|
||||||
// float denominator = 4.0 * NdotV * NdotL + EPSILON;
|
|
||||||
// vec3 specular = numerator / denominator;
|
|
||||||
//
|
|
||||||
// vec3 kS = F;
|
|
||||||
// vec3 kD = (vec3(1.0) - kS) * (1.0 - material.metallic);
|
|
||||||
//
|
|
||||||
// vec3 radiance = light.color * light.intensity * attenuation;
|
|
||||||
// direct_light += (kD * material.albedo * INV_PI + specular) * radiance * NdotL;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return direct_light;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Trace indirect lighting (simple path tracing)
|
|
||||||
// vec3 trace_indirect(vec3 position, vec3 normal, Material material, inout uint seed) {
|
|
||||||
// vec3 color = vec3(0.0);
|
|
||||||
//
|
|
||||||
// // Sample random direction
|
|
||||||
// vec3 ray_dir = cosine_weighted_hemisphere(normal, seed);
|
|
||||||
//
|
|
||||||
// // Sky color based on direction
|
|
||||||
// float t = 0.5 * (ray_dir.y + 1.0);
|
|
||||||
// vec3 sky_color = mix(vec3(1.0), vec3(0.5, 0.7, 1.0), t) * 0.2;
|
|
||||||
//
|
|
||||||
// color = sky_color;
|
|
||||||
//
|
|
||||||
// return color;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// void main() {
|
|
||||||
// ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
|
|
||||||
// ivec2 image_size = imageSize(output_image);
|
|
||||||
//
|
|
||||||
// if (pixel_coords.x >= image_size.x || pixel_coords.y >= image_size.y) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Read G-Buffer
|
|
||||||
// vec4 position_data = imageLoad(g_position, pixel_coords);
|
|
||||||
// vec4 normal_data = imageLoad(g_normal, pixel_coords);
|
|
||||||
// vec4 albedo_data = imageLoad(g_albedo, pixel_coords);
|
|
||||||
//
|
|
||||||
// // Check if this pixel has valid geometry
|
|
||||||
// if (position_data.w < 0.5) {
|
|
||||||
// vec3 background = vec3(0.1, 0.1, 0.15);
|
|
||||||
// imageStore(output_image, pixel_coords, vec4(background, 1.0));
|
|
||||||
// imageStore(accumulation_image, pixel_coords, vec4(background, 1.0));
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// vec3 position = position_data.xyz;
|
|
||||||
// vec3 normal = normalize(normal_data.xyz);
|
|
||||||
// vec3 albedo = albedo_data.rgb;
|
|
||||||
// uint material_id = floatBitsToUint(albedo_data.a);
|
|
||||||
//
|
|
||||||
// if (material_id >= 1000u) {
|
|
||||||
// material_id = 0u;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Initialize random seed
|
|
||||||
// uint seed = uint(pixel_coords.x) + uint(pixel_coords.y) * uint(image_size.x) + u_frame_count * 719393u;
|
|
||||||
//
|
|
||||||
// vec3 color = vec3(0.0);
|
|
||||||
//
|
|
||||||
// // Get material
|
|
||||||
// Material material;
|
|
||||||
// if (material_id < uint(materials.length())) {
|
|
||||||
// material = materials[material_id];
|
|
||||||
// } else {
|
|
||||||
// material.albedo = albedo;
|
|
||||||
// material.metallic = 0.0;
|
|
||||||
// material.roughness = 0.5;
|
|
||||||
// material.emission = vec3(0.0);
|
|
||||||
// material.type = MATERIAL_DIFFUSE;
|
|
||||||
// material.ior = 1.5;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Add emission
|
|
||||||
// color += material.emission;
|
|
||||||
//
|
|
||||||
// // Direct lighting
|
|
||||||
// vec3 view_dir = normalize(u_camera_position - position);
|
|
||||||
//
|
|
||||||
// if (u_light_count > 0u) {
|
|
||||||
// color += evaluate_direct_lighting(position, normal, view_dir, material, seed);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Indirect lighting (path tracing) - THIS ADDS NOISE
|
|
||||||
// for (uint samp_idx = 0u; samp_idx < u_samples_per_pixel; samp_idx++) { // 修复: sample -> samp_idx
|
|
||||||
// vec3 indirect = trace_indirect(position, normal, material, seed);
|
|
||||||
// color += indirect * material.albedo * INV_PI;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Ambient
|
|
||||||
// color += material.albedo * 0.02;
|
|
||||||
//
|
|
||||||
// // Clamp
|
|
||||||
// color = clamp(color, vec3(0.0), vec3(100.0));
|
|
||||||
//
|
|
||||||
// // Accumulation for denoising
|
|
||||||
// if (u_enable_accumulation && u_frame_count > 0u) {
|
|
||||||
// vec3 accumulated = imageLoad(accumulation_image, pixel_coords).rgb;
|
|
||||||
// float weight = 1.0 / float(u_frame_count + 1u);
|
|
||||||
// color = mix(accumulated, color, weight);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// imageStore(accumulation_image, pixel_coords, vec4(color, 1.0));
|
|
||||||
// imageStore(output_image, pixel_coords, vec4(color, 1.0));
|
|
||||||
// }
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "core/gbuffer.h"
|
#include "core/gbuffer.h"
|
||||||
|
#include "basic/constants.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
|
@ -10,7 +11,7 @@ GBuffer::GBuffer(uint width, uint height)
|
||||||
, fbo_(INVALID_HANDLE)
|
, fbo_(INVALID_HANDLE)
|
||||||
, depth_texture_(INVALID_HANDLE)
|
, depth_texture_(INVALID_HANDLE)
|
||||||
, initialized_(false) {
|
, initialized_(false) {
|
||||||
for (int i = 0; i < GBUFFER_COUNT; ++i) {
|
for (int i = 0; i < GBUFFER_TEXTURE_COUNT; ++i) {
|
||||||
textures_[i] = INVALID_HANDLE;
|
textures_[i] = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -33,32 +34,30 @@ bool GBuffer::initialize() {
|
||||||
textures_[GBUFFER_POSITION] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
textures_[GBUFFER_POSITION] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
||||||
textures_[GBUFFER_NORMAL] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
textures_[GBUFFER_NORMAL] = create_texture_(GL_RGBA32F, GL_RGBA, GL_FLOAT);
|
||||||
textures_[GBUFFER_ALBEDO] = create_texture_(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
textures_[GBUFFER_ALBEDO] = create_texture_(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||||
|
textures_[GBUFFER_MATERIAL_ID] = create_texture_(GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT);
|
||||||
|
|
||||||
// Attach textures to framebuffer
|
// Attach textures to framebuffer
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION, GL_TEXTURE_2D, textures_[GBUFFER_POSITION], 0);
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_POSITION], 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL, GL_TEXTURE_2D, textures_[GBUFFER_NORMAL], 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO, GL_TEXTURE_2D, textures_[GBUFFER_ALBEDO], 0);
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_NORMAL], 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_MATERIAL_ID, GL_TEXTURE_2D, textures_[GBUFFER_MATERIAL_ID], 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO,
|
|
||||||
GL_TEXTURE_2D, textures_[GBUFFER_ALBEDO], 0);
|
|
||||||
|
|
||||||
// Create depth texture
|
// Create depth texture
|
||||||
glGenTextures(1, &depth_texture_);
|
glGenTextures(1, &depth_texture_);
|
||||||
glBindTexture(GL_TEXTURE_2D, depth_texture_);
|
glBindTexture(GL_TEXTURE_2D, depth_texture_);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width_, height_, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width_, height_, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
||||||
GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth_texture_, 0);
|
||||||
GL_TEXTURE_2D, depth_texture_, 0);
|
|
||||||
|
|
||||||
// Set draw buffers
|
// Set draw buffers
|
||||||
GLenum draw_buffers[GBUFFER_COUNT] = {
|
GLenum draw_buffers[GBUFFER_TEXTURE_COUNT] = {
|
||||||
GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
GL_COLOR_ATTACHMENT0 + GBUFFER_POSITION,
|
||||||
GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
GL_COLOR_ATTACHMENT0 + GBUFFER_NORMAL,
|
||||||
GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO
|
GL_COLOR_ATTACHMENT0 + GBUFFER_ALBEDO,
|
||||||
|
GL_COLOR_ATTACHMENT0 + GBUFFER_MATERIAL_ID
|
||||||
};
|
};
|
||||||
glDrawBuffers(GBUFFER_COUNT, draw_buffers);
|
glDrawBuffers(GBUFFER_TEXTURE_COUNT, draw_buffers);
|
||||||
|
|
||||||
// Check framebuffer completeness
|
// Check framebuffer completeness
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
|
@ -82,7 +81,7 @@ void GBuffer::release() {
|
||||||
fbo_ = INVALID_HANDLE;
|
fbo_ = INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < GBUFFER_COUNT; ++i) {
|
for (int i = 0; i < GBUFFER_TEXTURE_COUNT; ++i) {
|
||||||
if (textures_[i] != INVALID_HANDLE) {
|
if (textures_[i] != INVALID_HANDLE) {
|
||||||
glDeleteTextures(1, &textures_[i]);
|
glDeleteTextures(1, &textures_[i]);
|
||||||
textures_[i] = INVALID_HANDLE;
|
textures_[i] = INVALID_HANDLE;
|
||||||
|
|
@ -194,7 +193,7 @@ void GBuffer::resize(uint width, uint height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle GBuffer::get_texture(int index) const {
|
TextureHandle GBuffer::get_texture(int index) const {
|
||||||
if (index < 0 || index >= GBUFFER_COUNT) {
|
if (index < 0 || index >= GBUFFER_TEXTURE_COUNT) {
|
||||||
Logger::error("Invalid G-Buffer texture index");
|
Logger::error("Invalid G-Buffer texture index");
|
||||||
return INVALID_HANDLE;
|
return INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,8 @@ void RayTracer::trace(const Scene& scene, const GBuffer& gbuffer, TextureHandle
|
||||||
bind_gbuffer_(gbuffer);
|
bind_gbuffer_(gbuffer);
|
||||||
|
|
||||||
// Bind output and accumulation textures
|
// Bind output and accumulation textures
|
||||||
glBindImageTexture(3, output_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
glBindImageTexture(GBUFFER_TEXTURE_COUNT, output_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
||||||
glBindImageTexture(4, accumulation_texture_, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
glBindImageTexture(GBUFFER_TEXTURE_COUNT + 1, accumulation_texture_, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
||||||
|
|
||||||
// Bind BVH buffers if enabled
|
// Bind BVH buffers if enabled
|
||||||
if (config_.use_bvh_ && bvh_built_) {
|
if (config_.use_bvh_ && bvh_built_) {
|
||||||
|
|
@ -234,14 +234,14 @@ void RayTracer::upload_scene_data_(const Scene& scene) {
|
||||||
// Upload materials
|
// Upload materials
|
||||||
const auto& materials = scene.get_materials();
|
const auto& materials = scene.get_materials();
|
||||||
if (!materials.empty()) {
|
if (!materials.empty()) {
|
||||||
struct MaterialData {
|
// 使用 vec4 确保对齐正确
|
||||||
Vec3 albedo;
|
struct alignas(16) MaterialData {
|
||||||
float metallic;
|
Vec4 albedo_metallic; // xyz = albedo, w = metallic
|
||||||
Vec3 emission;
|
Vec4 emission_roughness; // xyz = emission, w = roughness
|
||||||
float roughness;
|
|
||||||
int type;
|
int type;
|
||||||
float ior;
|
float ior;
|
||||||
Vec2 padding;
|
float padding1;
|
||||||
|
float padding2;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<MaterialData> material_data;
|
std::vector<MaterialData> material_data;
|
||||||
|
|
@ -249,34 +249,52 @@ void RayTracer::upload_scene_data_(const Scene& scene) {
|
||||||
|
|
||||||
for (const auto& mat : materials) {
|
for (const auto& mat : materials) {
|
||||||
MaterialData data;
|
MaterialData data;
|
||||||
data.albedo = mat->get_albedo();
|
data.albedo_metallic = Vec4(mat->get_albedo(), mat->get_metallic());
|
||||||
data.metallic = mat->get_metallic();
|
data.emission_roughness = Vec4(mat->get_emission(), mat->get_roughness());
|
||||||
data.emission = mat->get_emission();
|
|
||||||
data.roughness = mat->get_roughness();
|
|
||||||
data.type = static_cast<int>(mat->get_type());
|
data.type = static_cast<int>(mat->get_type());
|
||||||
data.ior = mat->get_ior();
|
data.ior = mat->get_ior();
|
||||||
|
data.padding1 = 0.0f;
|
||||||
|
data.padding2 = 0.0f;
|
||||||
material_data.push_back(data);
|
material_data.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 打印调试信息
|
||||||
|
Logger::info("MaterialData size: " + std::to_string(sizeof(MaterialData)) + " bytes");
|
||||||
|
Logger::info("Material[0] albedo: (" +
|
||||||
|
std::to_string(material_data[0].albedo_metallic.x) + ", " +
|
||||||
|
std::to_string(material_data[0].albedo_metallic.y) + ", " +
|
||||||
|
std::to_string(material_data[0].albedo_metallic.z) + ")");
|
||||||
|
Logger::info("Material[0] metallic: " + std::to_string(material_data[0].albedo_metallic.w));
|
||||||
|
|
||||||
|
// 找到金属材质并打印
|
||||||
|
for (size_t i = 0; i < material_data.size(); i++) {
|
||||||
|
if (material_data[i].albedo_metallic.w > 0.5f) {
|
||||||
|
Logger::info("Material[" + std::to_string(i) + "] is metallic: " +
|
||||||
|
std::to_string(material_data[i].albedo_metallic.w));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, material_buffer_);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, material_buffer_);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER,
|
glBufferData(GL_SHADER_STORAGE_BUFFER,
|
||||||
material_data.size() * sizeof(MaterialData),
|
material_data.size() * sizeof(MaterialData),
|
||||||
material_data.data(), GL_DYNAMIC_DRAW);
|
material_data.data(), GL_DYNAMIC_DRAW);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, material_buffer_);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, material_buffer_);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
|
|
||||||
|
Logger::info("Uploaded " + std::to_string(material_data.size()) + " materials to GPU");
|
||||||
|
} else {
|
||||||
|
Logger::warning("No materials to upload");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload lights
|
// Upload lights (保持不变)
|
||||||
const auto& lights = scene.get_lights();
|
const auto& lights = scene.get_lights();
|
||||||
if (!lights.empty()) {
|
if (!lights.empty()) {
|
||||||
struct LightData {
|
// 同样使用 vec4 确保对齐
|
||||||
Vec3 position;
|
struct alignas(16) LightData {
|
||||||
int type;
|
Vec4 position_type; // xyz = position, w = type (as float)
|
||||||
Vec3 direction;
|
Vec4 direction_intensity; // xyz = direction, w = intensity
|
||||||
float intensity;
|
Vec4 color_range; // xyz = color, w = range
|
||||||
Vec3 color;
|
Vec4 spot_angles; // xy = spot angles, zw = padding
|
||||||
float range;
|
|
||||||
Vec2 spot_angles;
|
|
||||||
Vec2 padding;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<LightData> light_data;
|
std::vector<LightData> light_data;
|
||||||
|
|
@ -284,28 +302,33 @@ void RayTracer::upload_scene_data_(const Scene& scene) {
|
||||||
|
|
||||||
for (const auto& light : lights) {
|
for (const auto& light : lights) {
|
||||||
LightData data;
|
LightData data;
|
||||||
data.position = light->get_position();
|
data.position_type = Vec4(light->get_position(), static_cast<float>(light->get_type()));
|
||||||
data.type = static_cast<int>(light->get_type());
|
data.direction_intensity = Vec4(light->get_direction(), light->get_intensity());
|
||||||
data.direction = light->get_direction();
|
data.color_range = Vec4(light->get_color(), light->get_range());
|
||||||
data.intensity = light->get_intensity();
|
data.spot_angles = Vec4(light->get_inner_angle(), light->get_outer_angle(), 0.0f, 0.0f);
|
||||||
data.color = light->get_color();
|
|
||||||
data.range = light->get_range();
|
|
||||||
data.spot_angles = Vec2(light->get_inner_angle(), light->get_outer_angle());
|
|
||||||
light_data.push_back(data);
|
light_data.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger::info("LightData size: " + std::to_string(sizeof(LightData)) + " bytes");
|
||||||
|
|
||||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, light_buffer_);
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, light_buffer_);
|
||||||
glBufferData(GL_SHADER_STORAGE_BUFFER,
|
glBufferData(GL_SHADER_STORAGE_BUFFER,
|
||||||
light_data.size() * sizeof(LightData),
|
light_data.size() * sizeof(LightData),
|
||||||
light_data.data(), GL_DYNAMIC_DRAW);
|
light_data.data(), GL_DYNAMIC_DRAW);
|
||||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, light_buffer_);
|
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, light_buffer_);
|
||||||
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
||||||
|
|
||||||
|
Logger::info("Uploaded " + std::to_string(light_data.size()) + " lights to GPU");
|
||||||
|
} else {
|
||||||
|
Logger::warning("No lights to upload");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RayTracer::bind_gbuffer_(const GBuffer& gbuffer) {
|
void RayTracer::bind_gbuffer_(const GBuffer& gbuffer) {
|
||||||
glBindImageTexture(0, gbuffer.get_texture(GBUFFER_POSITION), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
glBindImageTexture(GBUFFER_POSITION, gbuffer.get_texture(GBUFFER_POSITION), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||||
glBindImageTexture(1, gbuffer.get_texture(GBUFFER_NORMAL), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
glBindImageTexture(GBUFFER_NORMAL, gbuffer.get_texture(GBUFFER_NORMAL), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||||
glBindImageTexture(2, gbuffer.get_texture(GBUFFER_ALBEDO), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
|
glBindImageTexture(GBUFFER_ALBEDO, gbuffer.get_texture(GBUFFER_ALBEDO), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
|
||||||
|
glBindImageTexture(GBUFFER_MATERIAL_ID, gbuffer.get_texture(GBUFFER_MATERIAL_ID), 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RayTracer::set_compute_shader(const Shader& shader) {
|
void RayTracer::set_compute_shader(const Shader& shader) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue