Eevee-Next: World Reflective Light #108149
|
@ -291,7 +291,8 @@ void Instance::render_sample()
|
|||
}
|
||||
|
||||
sampling.step();
|
||||
|
||||
|
||||
capture_view.render();
|
||||
main_view.render();
|
||||
|
||||
motion_blur.step();
|
||||
|
|
|
@ -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){};
|
||||
|
|
|
@ -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());
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -59,37 +59,14 @@ class WorldPipeline {
|
|||
Texture dummy_aov_color_tx_;
|
||||
Texture dummy_aov_value_tx_;
|
||||
|
||||
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();
|
||||
world.sync();
|
||||
capture.sync();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
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);
|
||||
}
|
||||
GPU_texture_update_mipmap_chain(inst_.reflection_probes.cubemaps_tx_);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue