1
1
This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/draw/engines/eevee_next/eevee_pipeline.cc
Clément Foucault d371dfbe2c DRW: Change binding API
Using bind() overload is too error prone.
2022-08-30 21:27:02 +02:00

235 lines
8.2 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)
{
Manager &manager = *inst_.manager;
RenderBuffers &rbufs = inst_.render_buffers;
ResourceHandle handle = manager.resource_handle(float4x4::identity().ptr());
world_ps_.init();
world_ps_.state_set(DRW_STATE_WRITE_COLOR);
world_ps_.material_set(manager, gpumat);
world_ps_.push_constant("world_opacity_fade", inst_.film.background_opacity_get());
world_ps_.bind_texture("utility_tx", inst_.pipelines.utility_tx);
/* AOVs. */
world_ps_.bind_image("aov_color_img", &rbufs.aov_color_tx);
world_ps_.bind_image("aov_value_img", &rbufs.aov_value_tx);
world_ps_.bind_ssbo("aov_buf", &inst_.film.aovs_info);
/* RenderPasses. Cleared by background (even if bad practice). */
world_ps_.bind_image("rp_normal_img", &rbufs.normal_tx);
world_ps_.bind_image("rp_light_img", &rbufs.light_tx);
world_ps_.bind_image("rp_diffuse_color_img", &rbufs.diffuse_color_tx);
world_ps_.bind_image("rp_specular_color_img", &rbufs.specular_color_tx);
world_ps_.bind_image("rp_emission_img", &rbufs.emission_tx);
world_ps_.draw(DRW_cache_fullscreen_quad_get(), handle);
/* To allow opaque pass rendering over it. */
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
void WorldPipeline::render(View &view)
{
inst_.manager->submit(world_ps_, view);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Forward Pass
*
* NPR materials (using Closure to RGBA) or material using ALPHA_BLEND.
* \{ */
void ForwardPipeline::sync()
{
camera_forward_ = inst_.camera.forward();
DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
DRWState state_depth_color = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
DRW_STATE_WRITE_COLOR;
{
prepass_ps_.init();
{
/* Common resources. */
/* Textures. */
prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.velocity.bind_resources(&prepass_ps_);
inst_.sampling.bind_resources(&prepass_ps_);
}
prepass_double_sided_static_ps_ = &prepass_ps_.sub("DoubleSided.Static");
prepass_double_sided_static_ps_->state_set(state_depth_only);
prepass_single_sided_static_ps_ = &prepass_ps_.sub("SingleSided.Static");
prepass_single_sided_static_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK);
prepass_double_sided_moving_ps_ = &prepass_ps_.sub("DoubleSided.Moving");
prepass_double_sided_moving_ps_->state_set(state_depth_color);
prepass_single_sided_moving_ps_ = &prepass_ps_.sub("SingleSided.Moving");
prepass_single_sided_moving_ps_->state_set(state_depth_color | DRW_STATE_CULL_BACK);
}
{
opaque_ps_.init();
{
/* Common resources. */
/* RenderPasses. */
opaque_ps_.bind_image(RBUFS_NORMAL_SLOT, &inst_.render_buffers.normal_tx);
opaque_ps_.bind_image(RBUFS_LIGHT_SLOT, &inst_.render_buffers.light_tx);
opaque_ps_.bind_image(RBUFS_DIFF_COLOR_SLOT, &inst_.render_buffers.diffuse_color_tx);
opaque_ps_.bind_image(RBUFS_SPEC_COLOR_SLOT, &inst_.render_buffers.specular_color_tx);
opaque_ps_.bind_image(RBUFS_EMISSION_SLOT, &inst_.render_buffers.emission_tx);
/* AOVs. */
opaque_ps_.bind_image(RBUFS_AOV_COLOR_SLOT, &inst_.render_buffers.aov_color_tx);
opaque_ps_.bind_image(RBUFS_AOV_VALUE_SLOT, &inst_.render_buffers.aov_value_tx);
/* Storage Buf. */
opaque_ps_.bind_ssbo(RBUFS_AOV_BUF_SLOT, &inst_.film.aovs_info);
/* Textures. */
opaque_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.lights.bind_resources(&opaque_ps_);
inst_.sampling.bind_resources(&opaque_ps_);
}
opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided");
opaque_single_sided_ps_->state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_CULL_BACK);
opaque_double_sided_ps_ = &opaque_ps_.sub("DoubleSided");
opaque_double_sided_ps_->state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
}
{
transparent_ps_.init();
/* Workaround limitation of PassSortable. Use dummy pass that will be sorted first in all
* circumstances. */
PassMain::Sub &sub = transparent_ps_.sub("ResourceBind", -FLT_MAX);
/* Common resources. */
/* Textures. */
sub.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
inst_.lights.bind_resources(&sub);
inst_.sampling.bind_resources(&sub);
}
}
PassMain::Sub *ForwardPipeline::prepass_opaque_add(::Material *blender_mat,
GPUMaterial *gpumat,
bool has_motion)
{
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
(has_motion ? prepass_single_sided_moving_ps_ :
prepass_single_sided_static_ps_) :
(has_motion ? prepass_double_sided_moving_ps_ :
prepass_double_sided_static_ps_);
return &pass->sub(GPU_material_get_name(gpumat));
}
PassMain::Sub *ForwardPipeline::material_opaque_add(::Material *blender_mat, GPUMaterial *gpumat)
{
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? opaque_single_sided_ps_ :
opaque_double_sided_ps_;
return &pass->sub(GPU_material_get_name(gpumat));
}
PassMain::Sub *ForwardPipeline::prepass_transparent_add(const Object *ob,
::Material *blender_mat,
GPUMaterial *gpumat)
{
if ((blender_mat->blend_flag & MA_BL_HIDE_BACKFACE) == 0) {
return nullptr;
}
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
if ((blender_mat->blend_flag & MA_BL_CULL_BACKFACE)) {
state |= DRW_STATE_CULL_BACK;
}
float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
pass->material_set(*inst_.manager, gpumat);
return pass;
}
PassMain::Sub *ForwardPipeline::material_transparent_add(const Object *ob,
::Material *blender_mat,
GPUMaterial *gpumat)
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_LESS_EQUAL;
if ((blender_mat->blend_flag & MA_BL_CULL_BACKFACE)) {
state |= DRW_STATE_CULL_BACK;
}
float sorting_value = math::dot(float3(ob->obmat[3]), camera_forward_);
PassMain::Sub *pass = &transparent_ps_.sub(GPU_material_get_name(gpumat), sorting_value);
pass->state_set(state);
pass->material_set(*inst_.manager, gpumat);
return pass;
}
void ForwardPipeline::render(View &view,
Framebuffer &prepass_fb,
Framebuffer &combined_fb,
GPUTexture *UNUSED(combined_tx))
{
UNUSED_VARS(view);
DRW_stats_group_start("Forward.Opaque");
GPU_framebuffer_bind(prepass_fb);
inst_.manager->submit(prepass_ps_, view);
// 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);
inst_.manager->submit(opaque_ps_, view);
DRW_stats_group_end();
inst_.manager->submit(transparent_ps_, view);
// if (inst_.raytracing.enabled()) {
// gbuffer.ray_radiance_tx.release();
// }
}
/** \} */
} // namespace blender::eevee