This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/workbench/workbench_shader.cc
Campbell Barton 66595e29e2 Cleanup: remove/comment unused code, simplify casts
Remove simple counters where they aren't used, comment in some cases.
Also add missing include.
2023-01-19 17:10:42 +11:00

383 lines
13 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2020 Blender Foundation. */
/** \file
* \ingroup draw_engine
*/
#include "DRW_render.h"
#include <string>
#include "workbench_engine.h"
#include "workbench_private.h"
/* Maximum number of variations. */
#define MAX_LIGHTING 3
enum eWORKBENCH_TextureType {
TEXTURE_SH_NONE = 0,
TEXTURE_SH_SINGLE,
TEXTURE_SH_TILED,
TEXTURE_SH_MAX,
};
static struct {
struct GPUShader
*opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX][TEXTURE_SH_MAX];
struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX]
[MAX_LIGHTING][TEXTURE_SH_MAX];
struct GPUShader *opaque_composite_sh[MAX_LIGHTING];
struct GPUShader *oit_resolve_sh;
struct GPUShader *outline_sh;
struct GPUShader *merge_infront_sh;
struct GPUShader *shadow_depth_pass_sh[2];
struct GPUShader *shadow_depth_fail_sh[2][2];
struct GPUShader *cavity_sh[2][2];
struct GPUShader *dof_prepare_sh;
struct GPUShader *dof_downsample_sh;
struct GPUShader *dof_blur1_sh;
struct GPUShader *dof_blur2_sh;
struct GPUShader *dof_resolve_sh;
struct GPUShader *aa_accum_sh;
struct GPUShader *smaa_sh[3];
struct GPUShader *volume_sh[2][2][3][2];
} e_data = {{{{nullptr}}}};
/* -------------------------------------------------------------------- */
/** \name Conversions
* \{ */
static const char *workbench_lighting_mode_to_str(int light)
{
switch (light) {
default:
BLI_assert_msg(0, "Error: Unknown lighting mode.");
ATTR_FALLTHROUGH;
case V3D_LIGHTING_STUDIO:
return "_studio";
case V3D_LIGHTING_MATCAP:
return "_matcap";
case V3D_LIGHTING_FLAT:
return "_flat";
}
}
static const char *workbench_datatype_mode_to_str(eWORKBENCH_DataType datatype)
{
switch (datatype) {
default:
BLI_assert_msg(0, "Error: Unknown data mode.");
ATTR_FALLTHROUGH;
case WORKBENCH_DATATYPE_MESH:
return "_mesh";
case WORKBENCH_DATATYPE_HAIR:
return "_hair";
case WORKBENCH_DATATYPE_POINTCLOUD:
return "_ptcloud";
}
}
static const char *workbench_volume_interp_to_str(eWORKBENCH_VolumeInterpType interp_type)
{
switch (interp_type) {
default:
BLI_assert_msg(0, "Error: Unknown lighting mode.");
ATTR_FALLTHROUGH;
case WORKBENCH_VOLUME_INTERP_LINEAR:
return "_linear";
case WORKBENCH_VOLUME_INTERP_CUBIC:
return "_cubic";
case WORKBENCH_VOLUME_INTERP_CLOSEST:
return "_closest";
}
}
static const char *workbench_texture_type_to_str(eWORKBENCH_TextureType tex_type)
{
switch (tex_type) {
default:
BLI_assert_msg(0, "Error: Unknown texture mode.");
ATTR_FALLTHROUGH;
case TEXTURE_SH_NONE:
return "_tex_none";
case TEXTURE_SH_TILED:
return "_tex_tile";
case TEXTURE_SH_SINGLE:
return "_tex_single";
}
}
static eWORKBENCH_TextureType workbench_texture_type_get(bool textured, bool tiled)
{
return textured ? (tiled ? TEXTURE_SH_TILED : TEXTURE_SH_SINGLE) : TEXTURE_SH_NONE;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Shader request
* \{ */
static GPUShader *workbench_shader_get_ex(WORKBENCH_PrivateData *wpd,
bool transp,
eWORKBENCH_DataType datatype,
bool textured,
bool tiled)
{
eWORKBENCH_TextureType tex_type = workbench_texture_type_get(textured, tiled);
int light = wpd->shading.light;
BLI_assert(light < MAX_LIGHTING);
struct GPUShader **shader =
(transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][datatype][light][tex_type] :
&e_data.opaque_prepass_sh_cache[wpd->sh_cfg][datatype][tex_type];
if (*shader == nullptr) {
std::string create_info_name = "workbench";
create_info_name += (transp) ? "_transp" : "_opaque";
if (transp) {
create_info_name += workbench_lighting_mode_to_str(light);
}
create_info_name += workbench_datatype_mode_to_str(datatype);
create_info_name += workbench_texture_type_to_str(tex_type);
create_info_name += (wpd->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "_clip" : "_no_clip";
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return *shader;
}
GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType datatype)
{
return workbench_shader_get_ex(wpd, false, datatype, false, false);
}
GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd,
eWORKBENCH_DataType datatype,
bool tiled)
{
return workbench_shader_get_ex(wpd, false, datatype, true, tiled);
}
GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd,
eWORKBENCH_DataType datatype)
{
return workbench_shader_get_ex(wpd, true, datatype, false, false);
}
GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd,
eWORKBENCH_DataType datatype,
bool tiled)
{
return workbench_shader_get_ex(wpd, true, datatype, true, tiled);
}
GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd)
{
int light = wpd->shading.light;
struct GPUShader **shader = &e_data.opaque_composite_sh[light];
BLI_assert(light < MAX_LIGHTING);
if (*shader == nullptr) {
std::string create_info_name = "workbench_composite";
create_info_name += workbench_lighting_mode_to_str(light);
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return *shader;
}
GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData * /*wpd*/)
{
if (e_data.merge_infront_sh == nullptr) {
e_data.merge_infront_sh = GPU_shader_create_from_info_name("workbench_merge_infront");
}
return e_data.merge_infront_sh;
}
GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData * /*wpd*/)
{
if (e_data.oit_resolve_sh == nullptr) {
e_data.oit_resolve_sh = GPU_shader_create_from_info_name("workbench_transparent_resolve");
}
return e_data.oit_resolve_sh;
}
static GPUShader *workbench_shader_shadow_pass_get_ex(bool depth_pass, bool manifold, bool cap)
{
struct GPUShader **shader = (depth_pass) ? &e_data.shadow_depth_pass_sh[manifold] :
&e_data.shadow_depth_fail_sh[manifold][cap];
if (*shader == nullptr) {
std::string create_info_name = "workbench_shadow";
create_info_name += (depth_pass) ? "_pass" : "_fail";
create_info_name += (manifold) ? "_manifold" : "_no_manifold";
create_info_name += (cap) ? "_caps" : "_no_caps";
#if DEBUG_SHADOW_VOLUME
create_info_name += "_debug";
#endif
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return *shader;
}
GPUShader *workbench_shader_shadow_pass_get(bool manifold)
{
return workbench_shader_shadow_pass_get_ex(true, manifold, false);
}
GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap)
{
return workbench_shader_shadow_pass_get_ex(false, manifold, cap);
}
GPUShader *workbench_shader_cavity_get(bool cavity, bool curvature)
{
BLI_assert(cavity || curvature);
struct GPUShader **shader = &e_data.cavity_sh[cavity][curvature];
if (*shader == nullptr) {
std::string create_info_name = "workbench_effect";
create_info_name += (cavity) ? "_cavity" : "";
create_info_name += (curvature) ? "_curvature" : "";
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return *shader;
}
GPUShader *workbench_shader_outline_get(void)
{
if (e_data.outline_sh == nullptr) {
e_data.outline_sh = GPU_shader_create_from_info_name("workbench_effect_outline");
}
return e_data.outline_sh;
}
void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **downsample_sh,
GPUShader **blur1_sh,
GPUShader **blur2_sh,
GPUShader **resolve_sh)
{
if (e_data.dof_prepare_sh == nullptr) {
e_data.dof_prepare_sh = GPU_shader_create_from_info_name("workbench_effect_dof_prepare");
e_data.dof_downsample_sh = GPU_shader_create_from_info_name("workbench_effect_dof_downsample");
#if 0 /* TODO(fclem): finish COC min_max optimization */
e_data.dof_flatten_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_v");
e_data.dof_flatten_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_flatten_h");
e_data.dof_dilate_v_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_v");
e_data.dof_dilate_h_sh = GPU_shader_create_from_info_name("workbench_effect_dof_dilate_h");
#endif
e_data.dof_blur1_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur1");
e_data.dof_blur2_sh = GPU_shader_create_from_info_name("workbench_effect_dof_blur2");
e_data.dof_resolve_sh = GPU_shader_create_from_info_name("workbench_effect_dof_resolve");
}
*prepare_sh = e_data.dof_prepare_sh;
*downsample_sh = e_data.dof_downsample_sh;
*blur1_sh = e_data.dof_blur1_sh;
*blur2_sh = e_data.dof_blur2_sh;
*resolve_sh = e_data.dof_resolve_sh;
}
GPUShader *workbench_shader_antialiasing_accumulation_get(void)
{
if (e_data.aa_accum_sh == nullptr) {
e_data.aa_accum_sh = GPU_shader_create_from_info_name("workbench_taa");
}
return e_data.aa_accum_sh;
}
GPUShader *workbench_shader_antialiasing_get(int stage)
{
BLI_assert(stage < 3);
GPUShader **shader = &e_data.smaa_sh[stage];
if (*shader == nullptr) {
std::string create_info_name = "workbench_smaa_stage_";
create_info_name += std::to_string(stage);
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return e_data.smaa_sh[stage];
}
GPUShader *workbench_shader_volume_get(bool slice,
bool coba,
eWORKBENCH_VolumeInterpType interp_type,
bool smoke)
{
GPUShader **shader = &e_data.volume_sh[slice][coba][interp_type][smoke];
if (*shader == nullptr) {
std::string create_info_name = "workbench_volume";
create_info_name += (smoke) ? "_smoke" : "_object";
create_info_name += workbench_volume_interp_to_str(interp_type);
create_info_name += (coba) ? "_coba" : "_no_coba";
create_info_name += (slice) ? "_slice" : "_no_slice";
*shader = GPU_shader_create_from_info_name(create_info_name.c_str());
}
return *shader;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Cleanup
* \{ */
void workbench_shader_free(void)
{
for (int j = 0; j < sizeof(e_data.opaque_prepass_sh_cache) / sizeof(void *); j++) {
struct GPUShader **sh_array = &e_data.opaque_prepass_sh_cache[0][0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.transp_prepass_sh_cache) / sizeof(void *); j++) {
struct GPUShader **sh_array = &e_data.transp_prepass_sh_cache[0][0][0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < ARRAY_SIZE(e_data.opaque_composite_sh); j++) {
struct GPUShader **sh_array = &e_data.opaque_composite_sh[0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < ARRAY_SIZE(e_data.shadow_depth_pass_sh); j++) {
struct GPUShader **sh_array = &e_data.shadow_depth_pass_sh[0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.shadow_depth_fail_sh) / sizeof(void *); j++) {
struct GPUShader **sh_array = &e_data.shadow_depth_fail_sh[0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.cavity_sh) / sizeof(void *); j++) {
struct GPUShader **sh_array = &e_data.cavity_sh[0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < ARRAY_SIZE(e_data.smaa_sh); j++) {
struct GPUShader **sh_array = &e_data.smaa_sh[0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.volume_sh) / sizeof(void *); j++) {
struct GPUShader **sh_array = &e_data.volume_sh[0][0][0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.outline_sh);
DRW_SHADER_FREE_SAFE(e_data.merge_infront_sh);
DRW_SHADER_FREE_SAFE(e_data.dof_prepare_sh);
DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh);
DRW_SHADER_FREE_SAFE(e_data.dof_blur1_sh);
DRW_SHADER_FREE_SAFE(e_data.dof_blur2_sh);
DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.aa_accum_sh);
}
/** \} */