This change combines the diffuse/specular light passes into a single texture array, freeing up an image binding for cryptomatte. When diffuse/specular light pass and/or requested a texture array will be allocated. Only when specular light is requested 2 images will always be allocated. This increases the memory overhead when viewing the specular light renderpass in the viewport. For final rendering it is a common scenario that none or both are requested. Reviewed By: fclem Differential Revision: https://developer.blender.org/D15701
286 lines
12 KiB
C++
286 lines
12 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2021 Blender Foundation.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup eevee
|
|
*
|
|
* Shading passes contain drawcalls specific to shading pipelines.
|
|
* They are to be shared across views.
|
|
* This file is only for shading passes. Other passes are declared in their own module.
|
|
*/
|
|
|
|
#include "eevee_instance.hh"
|
|
|
|
#include "eevee_pipeline.hh"
|
|
|
|
namespace blender::eevee {
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name World Pipeline
|
|
*
|
|
* Used to draw background.
|
|
* \{ */
|
|
|
|
void WorldPipeline::sync(GPUMaterial *gpumat)
|
|
{
|
|
RenderBuffers &rbufs = inst_.render_buffers;
|
|
|
|
DRWState state = DRW_STATE_WRITE_COLOR;
|
|
world_ps_ = DRW_pass_create("World", state);
|
|
|
|
/* Push a matrix at the same location as the camera. */
|
|
float4x4 camera_mat = float4x4::identity();
|
|
// copy_v3_v3(camera_mat[3], inst_.camera.data_get().viewinv[3]);
|
|
|
|
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, world_ps_);
|
|
DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
|
|
DRW_shgroup_call_obmat(grp, DRW_cache_fullscreen_quad_get(), camera_mat.ptr());
|
|
DRW_shgroup_uniform_float_copy(grp, "world_opacity_fade", inst_.film.background_opacity_get());
|
|
/* AOVs. */
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
|
|
DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
|
|
/* RenderPasses. Cleared by background (even if bad practice). */
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_light_img", &rbufs.light_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
|
|
/* To allow opaque pass rendering over it. */
|
|
DRW_shgroup_barrier(grp, GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
|
}
|
|
|
|
void WorldPipeline::render()
|
|
{
|
|
DRW_draw_pass(world_ps_);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Forward Pass
|
|
*
|
|
* NPR materials (using Closure to RGBA) or material using ALPHA_BLEND.
|
|
* \{ */
|
|
|
|
void ForwardPipeline::sync()
|
|
{
|
|
{
|
|
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
|
prepass_ps_ = DRW_pass_create("Forward.Opaque.Prepass", state);
|
|
prepass_velocity_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Velocity",
|
|
state | DRW_STATE_WRITE_COLOR);
|
|
|
|
state |= DRW_STATE_CULL_BACK;
|
|
prepass_culled_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Culled", state);
|
|
prepass_culled_velocity_ps_ = DRW_pass_create("Forward.Opaque.Prepass.Velocity",
|
|
state | DRW_STATE_WRITE_COLOR);
|
|
|
|
DRW_pass_link(prepass_ps_, prepass_velocity_ps_);
|
|
DRW_pass_link(prepass_velocity_ps_, prepass_culled_ps_);
|
|
DRW_pass_link(prepass_culled_ps_, prepass_culled_velocity_ps_);
|
|
}
|
|
{
|
|
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
|
|
opaque_ps_ = DRW_pass_create("Forward.Opaque", state);
|
|
|
|
state |= DRW_STATE_CULL_BACK;
|
|
opaque_culled_ps_ = DRW_pass_create("Forward.Opaque.Culled", state);
|
|
|
|
DRW_pass_link(opaque_ps_, opaque_culled_ps_);
|
|
}
|
|
{
|
|
DRWState state = DRW_STATE_DEPTH_LESS_EQUAL;
|
|
transparent_ps_ = DRW_pass_create("Forward.Transparent", state);
|
|
}
|
|
}
|
|
|
|
DRWShadingGroup *ForwardPipeline::material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat)
|
|
{
|
|
RenderBuffers &rbufs = inst_.render_buffers;
|
|
DRWPass *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? opaque_culled_ps_ : opaque_ps_;
|
|
LightModule &lights = inst_.lights;
|
|
Sampling &sampling = inst_.sampling;
|
|
// LightProbeModule &lightprobes = inst_.lightprobes;
|
|
// RaytracingModule &raytracing = inst_.raytracing;
|
|
// eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT;
|
|
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, pass);
|
|
lights.bind_resources(grp);
|
|
sampling.bind_resources(grp);
|
|
// DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "grids_buf", lightprobes.grid_ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "cubes_buf", lightprobes.cube_ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "probes_buf", lightprobes.info_ubo_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get());
|
|
DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
|
|
/* AOVs. */
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
|
|
DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
|
|
/* RenderPasses. */
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_light_img", &rbufs.light_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
|
|
|
|
/* TODO(fclem): Make this only needed if material uses it ... somehow. */
|
|
// if (true) {
|
|
// DRW_shgroup_uniform_texture_ref(
|
|
// grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get());
|
|
// }
|
|
// if (raytracing.enabled()) {
|
|
// DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data);
|
|
// DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data);
|
|
// DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data);
|
|
// DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_screen_radiance_tx_,
|
|
// no_interp);
|
|
// }
|
|
// if (raytracing.enabled()) {
|
|
// DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get());
|
|
// }
|
|
return grp;
|
|
}
|
|
|
|
DRWShadingGroup *ForwardPipeline::prepass_opaque_add(::Material *blender_mat,
|
|
GPUMaterial *gpumat,
|
|
bool has_motion)
|
|
{
|
|
DRWPass *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
|
|
(has_motion ? prepass_culled_velocity_ps_ : prepass_culled_ps_) :
|
|
(has_motion ? prepass_velocity_ps_ : prepass_ps_);
|
|
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, pass);
|
|
if (has_motion) {
|
|
inst_.velocity.bind_resources(grp);
|
|
}
|
|
return grp;
|
|
}
|
|
|
|
DRWShadingGroup *ForwardPipeline::material_transparent_add(::Material *blender_mat,
|
|
GPUMaterial *gpumat)
|
|
{
|
|
RenderBuffers &rbufs = inst_.render_buffers;
|
|
LightModule &lights = inst_.lights;
|
|
Sampling &sampling = inst_.sampling;
|
|
// LightProbeModule &lightprobes = inst_.lightprobes;
|
|
// RaytracingModule &raytracing = inst_.raytracing;
|
|
// eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT;
|
|
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, transparent_ps_);
|
|
lights.bind_resources(grp);
|
|
sampling.bind_resources(grp);
|
|
// DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "grids_buf", lightprobes.grid_ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "cubes_buf", lightprobes.cube_ubo_get());
|
|
// DRW_shgroup_uniform_block(grp, "probes_buf", lightprobes.info_ubo_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get());
|
|
DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.pipelines.utility_tx);
|
|
/* TODO(fclem): Make this only needed if material uses it ... somehow. */
|
|
// if (true) {
|
|
// DRW_shgroup_uniform_texture_ref(
|
|
// grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get());
|
|
// }
|
|
// if (raytracing.enabled()) {
|
|
// DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data);
|
|
// DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data);
|
|
// DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data);
|
|
// DRW_shgroup_uniform_texture_ref_ex(
|
|
// grp, "rt_radiance_tx", &input_screen_radiance_tx_, no_interp);
|
|
// }
|
|
// if (raytracing.enabled()) {
|
|
// DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get());
|
|
// DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get());
|
|
// }
|
|
{
|
|
/* TODO(fclem): This is not needed. This is only to please the OpenGL debug Layer.
|
|
* If we are to introduce transparency render-passes support, it would be through a separate
|
|
* pass. */
|
|
/* AOVs. */
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_color_img", &rbufs.aov_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "aov_value_img", &rbufs.aov_value_tx);
|
|
DRW_shgroup_storage_block_ref(grp, "aov_buf", &inst_.film.aovs_info);
|
|
/* RenderPasses. */
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_normal_img", &rbufs.normal_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_light_img", &rbufs.light_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_diffuse_color_img", &rbufs.diffuse_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_specular_color_img", &rbufs.specular_color_tx);
|
|
DRW_shgroup_uniform_image_ref(grp, "rp_emission_img", &rbufs.emission_tx);
|
|
}
|
|
|
|
DRWState state_disable = DRW_STATE_WRITE_DEPTH;
|
|
DRWState state_enable = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
|
|
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
|
|
state_enable |= DRW_STATE_CULL_BACK;
|
|
}
|
|
DRW_shgroup_state_disable(grp, state_disable);
|
|
DRW_shgroup_state_enable(grp, state_enable);
|
|
return grp;
|
|
}
|
|
|
|
DRWShadingGroup *ForwardPipeline::prepass_transparent_add(::Material *blender_mat,
|
|
GPUMaterial *gpumat)
|
|
{
|
|
if ((blender_mat->blend_flag & MA_BL_HIDE_BACKFACE) == 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, transparent_ps_);
|
|
|
|
DRWState state_disable = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
|
|
DRWState state_enable = DRW_STATE_WRITE_DEPTH;
|
|
if (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) {
|
|
state_enable |= DRW_STATE_CULL_BACK;
|
|
}
|
|
DRW_shgroup_state_disable(grp, state_disable);
|
|
DRW_shgroup_state_enable(grp, state_enable);
|
|
return grp;
|
|
}
|
|
|
|
void ForwardPipeline::render(const DRWView *view,
|
|
Framebuffer &prepass_fb,
|
|
Framebuffer &combined_fb,
|
|
GPUTexture *UNUSED(combined_tx))
|
|
{
|
|
UNUSED_VARS(view);
|
|
|
|
DRW_stats_group_start("ForwardOpaque");
|
|
|
|
GPU_framebuffer_bind(prepass_fb);
|
|
DRW_draw_pass(prepass_ps_);
|
|
|
|
if (!DRW_pass_is_empty(prepass_ps_)) {
|
|
inst_.hiz_buffer.set_dirty();
|
|
}
|
|
|
|
// if (inst_.raytracing.enabled()) {
|
|
// rt_buffer.radiance_copy(combined_tx);
|
|
// inst_.hiz_buffer.update();
|
|
// }
|
|
|
|
// inst_.shadows.set_view(view, depth_tx);
|
|
|
|
GPU_framebuffer_bind(combined_fb);
|
|
DRW_draw_pass(opaque_ps_);
|
|
|
|
DRW_stats_group_end();
|
|
|
|
DRW_stats_group_start("ForwardTransparent");
|
|
/* TODO(fclem) This is suboptimal. We could sort during sync. */
|
|
/* FIXME(fclem) This wont work for panoramic, where we need
|
|
* to sort by distance to camera, not by z. */
|
|
DRW_pass_sort_shgroup_z(transparent_ps_);
|
|
DRW_draw_pass(transparent_ps_);
|
|
DRW_stats_group_end();
|
|
|
|
// if (inst_.raytracing.enabled()) {
|
|
// gbuffer.ray_radiance_tx.release();
|
|
// }
|
|
}
|
|
|
|
/** \} */
|
|
|
|
} // namespace blender::eevee
|