Revert "fix&feat:修复spp过高会崩溃问题,添加均值滤波功能"
This reverts commit bc4ec55b95.
修复单次spp过高导致崩溃问题时引入了多帧累积失效问题,故进行一次回滚。
master
parent
bc4ec55b95
commit
24be211acc
Binary file not shown.
|
|
@ -442,10 +442,10 @@ int main() {
|
|||
RendererConfig config;
|
||||
config.width_ = WINDOW_WIDTH;
|
||||
config.height_ = WINDOW_HEIGHT;
|
||||
config.samples_per_pixel_ = 10;
|
||||
config.samples_per_pixel_ = 4;
|
||||
config.max_ray_depth_ = 4;
|
||||
config.enable_accumulation_ = true;
|
||||
config.enable_denoising_ = true;
|
||||
config.enable_accumulation_ = false;
|
||||
config.enable_denoising_ = false;
|
||||
|
||||
g_renderer = std::make_unique<Renderer>(config);
|
||||
if (!g_renderer->initialize()) {
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef ARE_INCLUDE_CORE_DENOISER_H
|
||||
#define ARE_INCLUDE_CORE_DENOISER_H
|
||||
|
||||
#include "basic/types.h"
|
||||
#include "resource/shader.h"
|
||||
#include <memory>
|
||||
|
||||
namespace are {
|
||||
|
||||
/**
|
||||
* @brief Mean filter denoiser using compute shader
|
||||
*/
|
||||
class Denoiser {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct denoiser
|
||||
* @param width Output width
|
||||
* @param height Output height
|
||||
*/
|
||||
Denoiser(uint width, uint height);
|
||||
|
||||
/**
|
||||
* @brief Destroy denoiser
|
||||
*/
|
||||
~Denoiser();
|
||||
|
||||
/**
|
||||
* @brief Initialize GPU resources
|
||||
* @param shader Denoise compute shader (managed by ShaderManager)
|
||||
* @return True on success
|
||||
*/
|
||||
bool initialize(const std::shared_ptr<Shader>& shader);
|
||||
|
||||
/**
|
||||
* @brief Release GPU resources
|
||||
*/
|
||||
void release();
|
||||
|
||||
/**
|
||||
* @brief Resize internal targets
|
||||
* @param width New width
|
||||
* @param height New height
|
||||
*/
|
||||
void resize(uint width, uint height);
|
||||
|
||||
/**
|
||||
* @brief Apply mean filter
|
||||
* @param input_texture RGBA32F input texture
|
||||
* @param radius Filter radius (1 => 3x3)
|
||||
* @return Output texture handle (internal)
|
||||
*/
|
||||
TextureHandle denoise(TextureHandle input_texture, int radius);
|
||||
|
||||
private:
|
||||
uint width_;
|
||||
uint height_;
|
||||
std::shared_ptr<Shader> shader_;
|
||||
TextureHandle output_texture_;
|
||||
bool initialized_;
|
||||
|
||||
/**
|
||||
* @brief Create output texture
|
||||
*/
|
||||
void create_output_texture_();
|
||||
};
|
||||
|
||||
} // namespace are
|
||||
|
||||
#endif // ARE_INCLUDE_CORE_DENOISER_H
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
#include "core/raytracer.h"
|
||||
#include "core/screen_blit.h"
|
||||
#include "core/shader_manager.h"
|
||||
#include "core/denoiser.h"
|
||||
#include <memory>
|
||||
|
||||
namespace are {
|
||||
|
|
@ -67,7 +66,6 @@ private:
|
|||
std::unique_ptr<RayTracer> raytracer_;
|
||||
std::unique_ptr<ShaderManager> shader_manager_;
|
||||
std::unique_ptr<ScreenBlit> screen_blit_;
|
||||
std::unique_ptr<Denoiser> denoiser_;
|
||||
|
||||
bool initialized_;
|
||||
uint frame_count_;
|
||||
|
|
|
|||
|
|
@ -54,15 +54,10 @@ public:
|
|||
/// @return Ray tracing shader
|
||||
const std::shared_ptr<Shader>& get_raytracing_shader() const { return raytracing_shader_; }
|
||||
|
||||
/// @brief Get mean denoise compute shader
|
||||
/// @return Denoise shader (nullptr if not loaded)
|
||||
const std::shared_ptr<Shader>& get_denoise_shader() const { return denoise_shader_; }
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<Shader>> shader_cache_;
|
||||
std::shared_ptr<Shader> gbuffer_shader_;
|
||||
std::shared_ptr<Shader> raytracing_shader_;
|
||||
std::shared_ptr<Shader> denoise_shader_;
|
||||
|
||||
bool initialized_;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
#version 430 core
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
|
||||
layout(binding = 0, rgba32f) uniform readonly image2D u_input;
|
||||
layout(binding = 1, rgba32f) uniform writeonly image2D u_output;
|
||||
|
||||
// uniform int u_radius; // 已经不需要了,但保留定义以防外部报错
|
||||
|
||||
void main() {
|
||||
ivec2 p = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 size = imageSize(u_output);
|
||||
|
||||
// 边界检查:如果像素超出范围,直接返回
|
||||
if (p.x >= size.x || p.y >= size.y) return;
|
||||
|
||||
// 【修改点】:
|
||||
// 1. 不再使用循环去遍历周围的像素 (dy, dx)。
|
||||
// 2. 直接读取当前位置 (p) 的颜色。
|
||||
vec3 original_color = imageLoad(u_input, p).rgb;
|
||||
|
||||
// 直接写入输出图像,不做任何平均计算
|
||||
imageStore(u_output, p, vec4(original_color, 1.0));
|
||||
}
|
||||
|
|
@ -603,18 +603,22 @@ void main() {
|
|||
uint base_seed = uint(pixel_coords.x) + uint(pixel_coords.y) * uint(image_size.x);
|
||||
uint seed = base_seed + u_frame_count * 719393u;
|
||||
|
||||
vec3 sample_color = trace_path_primary_gbuffer(pixel_coords, image_size, seed);
|
||||
sample_color = clamp(sample_color, vec3(0.0), vec3(10.0));
|
||||
vec3 color = vec3(0.0);
|
||||
uint spp = max(u_samples_per_pixel, 1u);
|
||||
|
||||
if (u_enable_accumulation) {
|
||||
vec3 sum = imageLoad(accumulation_image, pixel_coords).rgb;
|
||||
sum += sample_color;
|
||||
imageStore(accumulation_image, pixel_coords, vec4(sum, 1.0));
|
||||
for (uint s = 0u; s < spp; ++s) {
|
||||
color += trace_path_primary_gbuffer(pixel_coords, image_size, seed);
|
||||
}
|
||||
color /= float(spp);
|
||||
|
||||
float inv_n = 1.0 / float(u_frame_count + 1u); // u_frame_count is "sample index"
|
||||
vec3 avg = sum * inv_n;
|
||||
imageStore(output_image, pixel_coords, vec4(avg, 1.0));
|
||||
} else {
|
||||
imageStore(output_image, pixel_coords, vec4(sample_color, 1.0));
|
||||
}
|
||||
color = clamp(color, vec3(0.0), vec3(10.0));
|
||||
|
||||
if (u_enable_accumulation && u_frame_count > 0u) {
|
||||
vec3 accumulated = imageLoad(accumulation_image, pixel_coords).rgb;
|
||||
float w = 1.0 / float(u_frame_count + 1u);
|
||||
color = mix(accumulated, color, w);
|
||||
}
|
||||
|
||||
imageStore(accumulation_image, pixel_coords, vec4(color, 1.0));
|
||||
imageStore(output_image, pixel_coords, vec4(color, 1.0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
#include "core/denoiser.h"
|
||||
#include "basic/constants.h"
|
||||
#include "utils/logger.h"
|
||||
#include <glad/glad.h>
|
||||
|
||||
namespace are {
|
||||
|
||||
Denoiser::Denoiser(uint width, uint height)
|
||||
: width_(width)
|
||||
, height_(height)
|
||||
, output_texture_(INVALID_HANDLE)
|
||||
, initialized_(false) {
|
||||
}
|
||||
|
||||
Denoiser::~Denoiser() {
|
||||
release();
|
||||
}
|
||||
|
||||
bool Denoiser::initialize(const std::shared_ptr<Shader>& shader) {
|
||||
if (initialized_) return true;
|
||||
|
||||
if (!shader || !shader->is_valid()) {
|
||||
Logger::error("Invalid denoise shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
shader_ = shader;
|
||||
create_output_texture_();
|
||||
|
||||
initialized_ = true;
|
||||
Logger::info("Denoiser initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Denoiser::release() {
|
||||
if (!initialized_) return;
|
||||
|
||||
shader_.reset();
|
||||
|
||||
if (output_texture_ != INVALID_HANDLE) {
|
||||
glDeleteTextures(1, &output_texture_);
|
||||
output_texture_ = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
|
||||
void Denoiser::resize(uint width, uint height) {
|
||||
if (width == width_ && height == height_) return;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
|
||||
if (!initialized_) return;
|
||||
|
||||
if (output_texture_ != INVALID_HANDLE) {
|
||||
glDeleteTextures(1, &output_texture_);
|
||||
output_texture_ = INVALID_HANDLE;
|
||||
}
|
||||
create_output_texture_();
|
||||
}
|
||||
|
||||
TextureHandle Denoiser::denoise(TextureHandle input_texture, int radius) {
|
||||
if (!initialized_) return input_texture;
|
||||
|
||||
radius = (radius < 0) ? 0 : radius;
|
||||
|
||||
shader_->use();
|
||||
|
||||
glBindImageTexture(0, input_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
|
||||
glBindImageTexture(1, output_texture_, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
||||
|
||||
shader_->set_int("u_radius", radius);
|
||||
|
||||
uint groups_x = (width_ + COMPUTE_GROUP_SIZE_X - 1) / COMPUTE_GROUP_SIZE_X;
|
||||
uint groups_y = (height_ + COMPUTE_GROUP_SIZE_Y - 1) / COMPUTE_GROUP_SIZE_Y;
|
||||
glDispatchCompute(groups_x, groups_y, 1);
|
||||
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
|
||||
return output_texture_;
|
||||
}
|
||||
|
||||
void Denoiser::create_output_texture_() {
|
||||
glGenTextures(1, &output_texture_);
|
||||
glBindTexture(GL_TEXTURE_2D, output_texture_);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width_, height_, 0, GL_RGBA, GL_FLOAT, nullptr);
|
||||
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_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
} // namespace are
|
||||
|
|
@ -184,48 +184,14 @@ void RayTracer::trace(const Scene &scene, const GBuffer &gbuffer, TextureHandle
|
|||
uint num_groups_x = (width_ + COMPUTE_GROUP_SIZE_X - 1) / COMPUTE_GROUP_SIZE_X;
|
||||
uint num_groups_y = (height_ + COMPUTE_GROUP_SIZE_Y - 1) / COMPUTE_GROUP_SIZE_Y;
|
||||
|
||||
const uint spp = std::max(config_.samples_per_pixel_, 1u);
|
||||
glDispatchCompute(num_groups_x, num_groups_y, 1);
|
||||
|
||||
// We interpret frame_count_ as "accumulated sample count"
|
||||
for (uint i = 0; i < spp; ++i) {
|
||||
compute_shader_->use();
|
||||
// Memory barrier
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
|
||||
// Bind G-Buffer textures
|
||||
bind_gbuffer_(gbuffer);
|
||||
|
||||
// Bind output and accumulation textures
|
||||
glBindImageTexture(3, output_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
|
||||
glBindImageTexture(4, accumulation_texture_, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
||||
|
||||
// Bind BVH buffers if enabled
|
||||
if (config_.use_bvh_ && bvh_built_) {
|
||||
bvh_node_buffer_.bind_base(2);
|
||||
bvh_triangle_buffer_.bind_base(3);
|
||||
compute_shader_->set_bool("u_use_bvh", true);
|
||||
compute_shader_->set_uint("u_bvh_node_count", bvh_->get_node_count());
|
||||
} else {
|
||||
compute_shader_->set_bool("u_use_bvh", false);
|
||||
compute_shader_->set_uint("u_bvh_node_count", 0u);
|
||||
}
|
||||
|
||||
// Set uniforms (u_frame_count is sample index)
|
||||
compute_shader_->set_uint("u_frame_count", frame_count_);
|
||||
compute_shader_->set_uint("u_samples_per_pixel", 1u); // shader does 1 sample per dispatch now
|
||||
compute_shader_->set_uint("u_max_depth", config_.max_depth_);
|
||||
compute_shader_->set_uint("u_light_count", static_cast<uint>(scene.get_lights().size()));
|
||||
compute_shader_->set_bool("u_enable_accumulation", config_.enable_accumulation_);
|
||||
|
||||
// Camera
|
||||
const Camera& camera = scene.get_camera();
|
||||
Mat4 inv_vp = glm::inverse(camera.get_view_projection_matrix());
|
||||
compute_shader_->set_mat4("u_inv_view_projection", inv_vp);
|
||||
|
||||
glDispatchCompute(num_groups_x, num_groups_y, 1);
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
|
||||
if (config_.enable_accumulation_) {
|
||||
frame_count_++;
|
||||
}
|
||||
// Increment frame count for accumulation
|
||||
if (config_.enable_accumulation_) {
|
||||
frame_count_++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,14 +67,6 @@ bool Renderer::initialize() {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Initialize denoiser
|
||||
denoiser_ = std::make_unique<Denoiser>(config_.width_, config_.height_);
|
||||
const auto& denoise_shader = shader_manager_->get_denoise_shader();
|
||||
if (!denoiser_->initialize(denoise_shader)) {
|
||||
Logger::error("Failed to initialize denoiser");
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
Logger::info("Aurora Rendering Engine initialized successfully");
|
||||
return true;
|
||||
|
|
@ -106,11 +98,6 @@ void Renderer::shutdown() {
|
|||
shader_manager_.reset();
|
||||
}
|
||||
|
||||
if(denoiser_) {
|
||||
denoiser_->release();
|
||||
denoiser_.reset();
|
||||
}
|
||||
|
||||
initialized_ = false;
|
||||
Logger::info("Aurora Rendering Engine shut down");
|
||||
}
|
||||
|
|
@ -161,18 +148,11 @@ RenderStats Renderer::render(const Scene& scene, TextureHandle output_texture) {
|
|||
auto raytrace_end = std::chrono::high_resolution_clock::now();
|
||||
stats.raytrace_time_ms_ = std::chrono::duration<float, std::milli>(raytrace_end - raytrace_start).count();
|
||||
|
||||
// Phase 3: Denoise texture
|
||||
TextureHandle final_output = rt_output;
|
||||
|
||||
if (denoiser_) {
|
||||
final_output = denoiser_->denoise(rt_output, 1); // radius=1 => 3x3
|
||||
}
|
||||
|
||||
// Phase 4: Blit to screen if output is default framebuffer
|
||||
if (created_temp_texture && output_texture == 0) {
|
||||
screen_blit_->blit_fullscreen(final_output);
|
||||
glDeleteTextures(1, &rt_output);
|
||||
}
|
||||
// Phase 3: Blit to screen if output is default framebuffer
|
||||
if (created_temp_texture && output_texture == 0) {
|
||||
screen_blit_->blit_fullscreen(rt_output);
|
||||
glDeleteTextures(1, &rt_output);
|
||||
}
|
||||
|
||||
// Calculate total frame time
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
|
|
@ -202,7 +182,6 @@ void Renderer::resize(uint width, uint height) {
|
|||
if (initialized_) {
|
||||
gbuffer_->resize(width, height);
|
||||
raytracer_->resize(width, height);
|
||||
denoiser_->resize(width, height);
|
||||
|
||||
Logger::info("Renderer resized to " + std::to_string(width) + "x" + std::to_string(height));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ void ShaderManager::release() {
|
|||
|
||||
gbuffer_shader_.reset();
|
||||
raytracing_shader_.reset();
|
||||
denoise_shader_.reset();
|
||||
|
||||
initialized_ = false;
|
||||
Logger::info("ShaderManager released");
|
||||
|
|
@ -109,15 +108,6 @@ bool ShaderManager::load_builtin_shaders_() {
|
|||
shader_cache_["raytracing"] = raytracing_shader_;
|
||||
Logger::info("Ray tracing shader loaded successfully");
|
||||
|
||||
Logger::info("Loading denoise compute shader...");
|
||||
denoise_shader_ = std::make_shared<Shader>();
|
||||
if (!denoise_shader_->load_compute("shaders/denoiser.comp")) {
|
||||
Logger::error("Failed to load denoise shader");
|
||||
return false;
|
||||
}
|
||||
shader_cache_["denoise"] = denoise_shader_;
|
||||
Logger::info("Denoise shader loaded successfully");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue