Eevee-Next: World Reflective Light #108149

Merged
Jeroen Bakker merged 33 commits from Jeroen-Bakker/blender:eevee-next-world-shader into main 2023-06-29 15:25:04 +02:00
7 changed files with 61 additions and 85 deletions
Showing only changes of commit 00fda3ecda - Show all commits

View File

@ -291,7 +291,8 @@ void Instance::render_sample()
}
sampling.step();
capture_view.render();
main_view.render();
motion_blur.step();

View File

@ -67,6 +67,7 @@ class Instance {
Film film;
RenderBuffers render_buffers;
MainView main_view;
CaptureView capture_view;
World world;
LightProbeModule light_probes;
IrradianceCache irradiance_cache;
@ -118,6 +119,7 @@ class Instance {
film(*this),
render_buffers(*this),
main_view(*this),
capture_view(*this),
world(*this),
light_probes(*this),
irradiance_cache(*this){};

View File

@ -60,19 +60,8 @@ void BackgroundPipeline::render(View &view)
/** \name World Probe Pipeline
* \{ */
void WorldPipeline::sync()
void WorldPipeline::sync(GPUMaterial *gpumat)
{
for (int face : IndexRange(6)) {
CubemapSide &side = sides_[face];
/* View */
float4x4 view_m4 = cubeface_mat(face);
float4x4 win_m4;
cubeface_winmat_get(win_m4, 1.0f, 10.0f);
side.view.sync(view_m4, win_m4);
side.cubemap_face_ps.init();
side.cubemap_face_ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS);
}
const int2 extent(1);
constexpr eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_WRITE;
dummy_cryptomatte_tx_.ensure_2d(GPU_RGBA32F, extent, usage);
@ -80,31 +69,12 @@ void WorldPipeline::sync()
dummy_aov_color_tx_.ensure_2d_array(GPU_RGBA16F, extent, 1, usage);
dummy_aov_value_tx_.ensure_2d_array(GPU_R16F, extent, 1, usage);
has_draw_commands_ = false;
}
PassSimple &pass = cubemap_face_ps_;
pass.init();
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS);
void WorldPipeline::sync(GPUMaterial *gpumat)
{
for (int face : IndexRange(6)) {
sync(gpumat, face);
}
has_draw_commands_ = true;
}
void WorldPipeline::sync(GPUMaterial *gpumat, int face)
{
Manager &manager = *inst_.manager;
CubemapSide &side = sides_[face];
/* Framebuffer. */
Texture &cubemap = inst_.reflection_probes.cubemaps_tx_;
side.cubemap_face_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE_CUBEFACE(cubemap, face));
ResourceHandle handle = manager.resource_handle(float4x4::identity());
Jeroen-Bakker marked this conversation as resolved Outdated

Can we use GPU_TEXTURE_USAGE_MEMORYLESS with GPU_TEXTURE_USAGE_SHADER_WRITE here? sounds like potential issue.

Can we use GPU_TEXTURE_USAGE_MEMORYLESS with GPU_TEXTURE_USAGE_SHADER_WRITE here? sounds like potential issue.
PassSimple &pass = side.cubemap_face_ps;
pass.framebuffer_set(&side.cubemap_face_fb);
pass.material_set(manager, gpumat);
pass.push_constant("world_opacity_fade", 1.0f);
@ -127,32 +97,11 @@ void WorldPipeline::sync(GPUMaterial *gpumat, int face)
pass.bind_ssbo("aov_buf", &inst_.film.aovs_info);

Currently reuses previous resources, as the last one would be the world background pass this kinda works. But should be fixed.

Currently reuses previous resources, as the last one would be the world background pass this kinda works. But should be fixed.
pass.draw(DRW_cache_fullscreen_quad_get(), handle);
pass.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
void WorldPipeline::render()
void WorldPipeline::render(View &view)
{
if (!has_draw_commands_) {
return;
}
GPUFrameBuffer *previous_framebuffer = GPU_framebuffer_active_get();
GPU_debug_group_begin("World.Probe");
for (int face : IndexRange(6)) {
sides_[face].render(inst_);
}
GPU_debug_group_end();
GPU_texture_update_mipmap_chain(inst_.reflection_probes.cubemaps_tx_);
if (previous_framebuffer) {
GPU_framebuffer_bind(previous_framebuffer);
}
}
void WorldPipeline::CubemapSide::render(Instance &instance)
{
instance.manager->submit(cubemap_face_ps, view);
inst_.manager->submit(cubemap_face_ps_, view);
}
/** \} */

View File

@ -59,37 +59,14 @@ class WorldPipeline {
Texture dummy_aov_color_tx_;
Texture dummy_aov_value_tx_;
Jeroen-Bakker marked this conversation as resolved Outdated

This struct shouldn't be contained by the pipeline. The pipeline should only contain the pass and be view agnostic.

So you should only have one pass that is being drawn for the 6 views.

This struct shouldn't be contained by the pipeline. The pipeline should only contain the pass and be view agnostic. So you should only have one pass that is being drawn for the 6 views.
struct CubemapSide {
PassSimple cubemap_face_ps;
View view;
Framebuffer cubemap_face_fb;
void render(Instance &instance);
};
/**
* Keep track if the world probe needs to be updated. This should only be the case when the
* world is updated. This flag is used to skip updating mipmaps when the world isn't changed.
*/
bool has_draw_commands_ = false;
CubemapSide sides_[6] = {
{{"PosX"}, {"PosX"}},
{{"NegX"}, {"NegX"}},
{{"PosY"}, {"PosY"}},
{{"NegY"}, {"NegY"}},
{{"PosZ"}, {"PosZ"}},
{{"NegZ"}, {"NegZ"}},
};
PassSimple cubemap_face_ps_ = {"World.Probe"};
public:
WorldPipeline(Instance &inst) : inst_(inst){};
void sync();
void sync(GPUMaterial *gpumat);
void render();
void render(View &view);
private:
void sync(GPUMaterial *gpumat, int face);
}; // namespace blender::eevee
/** \} */
@ -361,7 +338,6 @@ class PipelineModule {
deferred.begin_sync();
forward.sync();
shadow.sync();
Jeroen-Bakker marked this conversation as resolved Outdated

Maybe we could rename this to BackgroundPipeline and use WorldPipeline for world rendering. Could do that in another PR.

Maybe we could rename this to BackgroundPipeline and use WorldPipeline for world rendering. Could do that in another PR.

I did the change in #109495

I did the change in #109495
world.sync();
capture.sync();
}

View File

@ -29,6 +29,7 @@ namespace blender::eevee {
class Instance;
class WorldPipeline;
class CaptureView;
/* -------------------------------------------------------------------- */
/** \name Reflection Probes
@ -85,6 +86,8 @@ class ReflectionProbeModule {
void sync(const ReflectionProbe &cubemap);
friend class WorldPipeline;
/* Capture View requires access to the cubemaps texture for framebuffer configuration. */
friend class CaptureView;
};
} // namespace blender::eevee

View File

@ -118,7 +118,6 @@ void ShadingView::render()
GPU_framebuffer_bind(combined_fb_);
GPU_framebuffer_clear_color_depth(combined_fb_, clear_color, 1.0f);
inst_.pipelines.world.render();
inst_.pipelines.background.render(render_view_new_);
/* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */
@ -190,4 +189,31 @@ void ShadingView::update_view()
/** \} */
/* -------------------------------------------------------------------- */
/** \name Capture View
* \{ */
void CaptureView::render()
{
// TODO: only do this when world needs to be captured.

Replace by inst_.reflection_probes.do_world_update.

Replace by `inst_.reflection_probes.do_world_update`.
View view = {"World.Capture.View"};
for (int face : IndexRange(6)) {
capture_fb_.ensure(
GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE_CUBEFACE(inst_.reflection_probes.cubemaps_tx_, face));
GPU_framebuffer_bind(capture_fb_);
float4x4 view_m4 = cubeface_mat(face);
float4x4 win_m4;
cubeface_winmat_get(win_m4, 1.0f, 10.0f);
view.sync(view_m4, win_m4);
inst_.pipelines.world.render(view);
}
Jeroen-Bakker marked this conversation as resolved Outdated

use math::projection::perspective()

use `math::projection::perspective()`
GPU_texture_update_mipmap_chain(inst_.reflection_probes.cubemaps_tx_);
}
/** \} */
} // namespace blender::eevee

View File

@ -142,4 +142,23 @@ class MainView {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Capture View
*
* View for capturing cubemap renders outside a ShadingView.
* \{ */
class CaptureView {
private:
Instance &inst_;
Framebuffer capture_fb_ = {"World.Capture"};
public:
CaptureView(Instance &inst) : inst_(inst) {}
void render();
};
/** \} */
} // namespace blender::eevee