Workbench: Enable BSL 5.3

Contains refactors to use the BSL
version of draw and gpu libs.

Only leave workbench_shadow_raytrace out
because of missing raytrace API in
5.3 compiler.

Pull Request: https://projects.blender.org/blender/blender/pulls/164410
This commit is contained in:
Clément Foucault 2026-09-28 16:40:46 +02:00 • committed by Clément Foucault
parent 5ce66a846e
commit d50d0205d2
40 changed files with 952 additions and 1460 deletions

View file

@ -350,12 +350,7 @@ set(GLSL_SRC
engines/select/shaders/infos/select_id_infos.hh
engines/workbench/shaders/infos/workbench_depth_infos.hh
engines/workbench/shaders/infos/workbench_effect_antialiasing_infos.hh
engines/workbench/shaders/infos/workbench_effect_dof_infos.hh
engines/workbench/shaders/infos/workbench_effect_outline_infos.hh
engines/workbench/shaders/infos/workbench_prepass_infos.hh
engines/workbench/shaders/infos/workbench_transparent_resolve_infos.hh
engines/eevee/shaders/eevee_attributes_curves_lib.bsl.hh
engines/eevee/shaders/eevee_attributes_mesh_lib.bsl.hh
@ -512,35 +507,23 @@ set(GLSL_SRC
engines/workbench/shaders/workbench_cavity.bsl.hh
engines/workbench/shaders/workbench_common.bsl.hh
engines/workbench/shaders/workbench_common_lib.glsl
engines/workbench/shaders/workbench_composite.bsl.hh
engines/workbench/shaders/workbench_curvature.bsl.hh
engines/workbench/shaders/workbench_effect_dof_prepare_frag.glsl
engines/workbench/shaders/workbench_effect_dof_downsample_frag.glsl
engines/workbench/shaders/workbench_effect_dof_blur1_frag.glsl
engines/workbench/shaders/workbench_effect_dof_blur2_frag.glsl
engines/workbench/shaders/workbench_effect_dof_resolve_frag.glsl
engines/workbench/shaders/workbench_effect_dof_lib.glsl
engines/workbench/shaders/workbench_effect_outline_frag.glsl
engines/workbench/shaders/workbench_fx_dof.bsl.hh
engines/workbench/shaders/workbench_fx_outline.bsl.hh
engines/workbench/shaders/workbench_effect_smaa_frag.glsl
engines/workbench/shaders/workbench_effect_smaa_vert.glsl
engines/workbench/shaders/workbench_effect_taa_frag.glsl
engines/workbench/shaders/workbench_fullscreen_vert.glsl
engines/workbench/shaders/workbench_image_lib.glsl
engines/workbench/shaders/workbench_fx_taa.bsl.hh
engines/workbench/shaders/workbench_image.bsl.hh
engines/workbench/shaders/workbench_matcap_lib.glsl
engines/workbench/shaders/workbench_matcap.bsl.hh
engines/workbench/shaders/workbench_material.bsl.hh
engines/workbench/shaders/workbench_merge_depth_frag.glsl
engines/workbench/shaders/workbench_overlay_depth_frag.glsl
engines/workbench/shaders/workbench_depth.bsl.hh
engines/workbench/shaders/workbench_prepass.bsl.hh
engines/workbench/shaders/workbench_shadow.bsl.hh
engines/workbench/shaders/workbench_shadow_raytrace.bsl.hh
engines/workbench/shaders/workbench_shadow_visibility.bsl.hh
engines/workbench/shaders/workbench_transparent_accum_frag.glsl
engines/workbench/shaders/workbench_transparent_resolve_frag.glsl
engines/workbench/shaders/workbench_transparent_resolve.bsl.hh
engines/workbench/shaders/workbench_volume.bsl.hh
engines/workbench/shaders/workbench_world_light_lib.glsl
engines/workbench/shaders/workbench_world_light.bsl.hh
engines/workbench/workbench_defines.hh

View file

@ -26,29 +26,10 @@ set(INC_GLSL
set(SRC_GLSL_VERT
workbench_effect_smaa_vert.glsl
workbench_fullscreen_vert.glsl
)
set(SRC_GLSL_FRAG
workbench_effect_dof_prepare_frag.glsl
workbench_effect_dof_downsample_frag.glsl
workbench_effect_dof_blur1_frag.glsl
workbench_effect_dof_blur2_frag.glsl
workbench_effect_dof_resolve_frag.glsl
workbench_effect_outline_frag.glsl
workbench_effect_smaa_frag.glsl
workbench_effect_taa_frag.glsl
workbench_merge_depth_frag.glsl
workbench_overlay_depth_frag.glsl
workbench_transparent_resolve_frag.glsl
)
set(SRC_GLSL_LIB
workbench_effect_dof_lib.glsl
workbench_common_lib.glsl
workbench_image_lib.glsl
workbench_matcap_lib.glsl
workbench_world_light_lib.glsl
)
set(SRC_BSL
@ -61,7 +42,6 @@ if(WITH_GPU_SHADER_CPP_COMPILATION)
add_definitions(-DUSE_GPU_SHADER_CREATE_INFO)
compile_sources_as_cpp(workbench_cpp_shaders_vert "${SRC_GLSL_VERT}" "GPU_VERTEX_SHADER")
compile_sources_as_cpp(workbench_cpp_shaders_frag "${SRC_GLSL_FRAG}" "GPU_FRAGMENT_SHADER")
compile_sources_as_cpp(workbench_cpp_shaders_bsl "${SRC_BSL}" "")
# Only enable to make sure they compile on their own.
# Otherwise it creates a warning about `pragma once`.

View file

@ -10,6 +10,9 @@
#include "workbench_common.bsl.hh" /* IWYU pragma: export */
#include "workbench_composite.bsl.hh" /* IWYU pragma: export */
#include "workbench_curvature.bsl.hh" /* IWYU pragma: export */
#include "workbench_fx_dof.bsl.hh" /* IWYU pragma: export */
#include "workbench_fx_outline.bsl.hh" /* IWYU pragma: export */
#include "workbench_fx_taa.bsl.hh" /* IWYU pragma: export */
#include "workbench_image.bsl.hh" /* IWYU pragma: export */
#include "workbench_matcap.bsl.hh" /* IWYU pragma: export */
#include "workbench_material.bsl.hh" /* IWYU pragma: export */

View file

@ -1,25 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef GPU_SHADER
# pragma once
# include "gpu_shader_compat.hh"
#endif
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(workbench_merge_depth)
SAMPLER(0, sampler2DDepth, depth_tx)
FRAGMENT_SOURCE("workbench_merge_depth_frag.glsl")
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
DEPTH_WRITE(DepthWrite::ANY)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_overlay_depth)
FRAGMENT_SOURCE("workbench_overlay_depth_frag.glsl")
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
DEPTH_WRITE(DepthWrite::ANY)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()

View file

@ -18,21 +18,6 @@
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
/** \name TAA
* \{ */
GPU_SHADER_CREATE_INFO(workbench_taa)
SAMPLER(0, sampler2D, color_buffer)
PUSH_CONSTANT_ARRAY(float, samplesWeights, 9)
FRAGMENT_OUT(0, float4, frag_color)
FRAGMENT_SOURCE("workbench_effect_taa_frag.glsl")
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
/** \} */
/* -------------------------------------------------------------------- */
/** \name SMAA
* \{ */

View file

@ -1,94 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef GPU_SHADER
# pragma once
# include "gpu_shader_compat.hh"
# include "workbench_shader_shared.hh"
# include "draw_view_infos.hh"
#endif
#ifdef GLSL_CPP_STUBS
# define PREPARE
# define DOWNSAMPLE
# define BLUR1
# define BLUR2
# define RESOLVE
# define NUM_SAMPLES 49
#endif
#include "gpu_shader_create_info.hh"
/*
* NOTE: Keep the sampler bind points consistent between the steps.
*
* SAMPLER(0, sampler2D, input_coc_tx)
* SAMPLER(1, sampler2D, scene_color_tx)
* SAMPLER(2, sampler2D, scene_depth_tx)
* SAMPLER(3, sampler2D, half_res_color_tx)
* SAMPLER(4, sampler2D, blur_tx)
* SAMPLER(5, sampler2D, noise_tx)
*/
GPU_SHADER_CREATE_INFO(workbench_effect_dof)
PUSH_CONSTANT(float2, inverted_viewport_size)
PUSH_CONSTANT(float2, near_far)
PUSH_CONSTANT(float3, dof_params)
PUSH_CONSTANT(float, noise_offset)
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
ADDITIONAL_INFO(draw_view)
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_effect_dof_prepare)
SAMPLER(1, sampler2D, scene_color_tx)
SAMPLER(2, sampler2D, scene_depth_tx)
FRAGMENT_OUT(0, float4, halfResColor)
FRAGMENT_OUT(1, float2, normalizedCoc)
FRAGMENT_SOURCE("workbench_effect_dof_prepare_frag.glsl")
ADDITIONAL_INFO(workbench_effect_dof)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_effect_dof_downsample)
SAMPLER(0, sampler2D, input_coc_tx)
SAMPLER(1, sampler2D, scene_color_tx)
FRAGMENT_OUT(0, float4, outColor)
FRAGMENT_OUT(1, float2, outCocs)
FRAGMENT_SOURCE("workbench_effect_dof_downsample_frag.glsl")
ADDITIONAL_INFO(workbench_effect_dof)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_effect_dof_blur1)
DEFINE_VALUE("NUM_SAMPLES", "49")
SAMPLER(0, sampler2D, input_coc_tx)
SAMPLER(3, sampler2D, half_res_color_tx)
SAMPLER(5, sampler2D, noise_tx)
UNIFORM_BUF(1, float4, samples[49])
FRAGMENT_OUT(0, float4, blurColor)
FRAGMENT_SOURCE("workbench_effect_dof_blur1_frag.glsl")
ADDITIONAL_INFO(workbench_effect_dof)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_effect_dof_blur2)
SAMPLER(0, sampler2D, input_coc_tx)
SAMPLER(4, sampler2D, blur_tx)
FRAGMENT_OUT(0, float4, final_color)
FRAGMENT_SOURCE("workbench_effect_dof_blur2_frag.glsl")
ADDITIONAL_INFO(workbench_effect_dof)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(workbench_effect_dof_resolve)
SAMPLER(2, sampler2D, scene_depth_tx)
SAMPLER(3, sampler2D, half_res_color_tx)
FRAGMENT_OUT_DUAL(0, float4, final_colorAdd, SRC_0)
FRAGMENT_OUT_DUAL(0, float4, final_colorMul, SRC_1)
FRAGMENT_SOURCE("workbench_effect_dof_resolve_frag.glsl")
ADDITIONAL_INFO(workbench_effect_dof)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()

View file

@ -1,24 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef GPU_SHADER
# pragma once
# include "gpu_shader_compat.hh"
# include "workbench_shader_shared.hh"
#endif
#include "workbench_defines.hh"
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(workbench_effect_outline)
TYPEDEF_SOURCE("workbench_shader_shared.hh")
FRAGMENT_SOURCE("workbench_effect_outline_frag.glsl")
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
SAMPLER(0, usampler2D, object_id_buffer)
UNIFORM_BUF(WB_WORLD_SLOT, WorldData, world_data)
FRAGMENT_OUT(0, float4, frag_color)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()

View file

@ -1,34 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef GPU_SHADER
# pragma once
# include "BLI_utildefines_variadic.hh"
# include "gpu_shader_compat.hh"
# include "draw_object_infos_infos.hh"
# include "draw_view_infos.hh"
# include "workbench_shader_shared.hh"
#endif
#ifdef GLSL_CPP_STUBS
# define WORKBENCH_COLOR_MATERIAL
# define WORKBENCH_COLOR_TEXTURE
# define WORKBENCH_TEXTURE_IMAGE_ARRAY
# define WORKBENCH_COLOR_MATERIAL
# define WORKBENCH_COLOR_VERTEX
# define WORKBENCH_LIGHTING_MATCAP 1
# define CURVES_SHADER
# define DRW_HAIR_INFO
# define POINTCLOUD_SHADER
# define DRW_POINTCLOUD_INFO
#endif
#include "gpu_shader_create_info.hh"
#include "workbench_defines.hh"

View file

@ -1,19 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef GPU_SHADER
# pragma once
# include "gpu_shader_compat.hh"
#endif
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(workbench_transparent_resolve)
FRAGMENT_OUT(0, float4, frag_color)
SAMPLER(0, sampler2D, transparent_accum)
SAMPLER(1, sampler2D, transparent_revealage)
FRAGMENT_SOURCE("workbench_transparent_resolve_frag.glsl")
VERTEX_SOURCE("workbench_fullscreen_vert.glsl")
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()

View file

@ -4,7 +4,7 @@
#pragma once
#include "draw_view_lib.glsl"
#include "draw_view.bsl.hh"
#include "workbench_common.bsl.hh"
@ -20,6 +20,7 @@ struct Cavity {
void cavity_compute([[resource_table]] const workbench::Cavity &cavity,
[[resource_table]] const workbench::World &world,
ViewMatrices view,
sampler2DDepth depth_tx,
sampler2D normal_tx,
float2 screenco,
@ -37,7 +38,7 @@ void cavity_compute([[resource_table]] const workbench::Cavity &cavity,
const WorldData &world_data = world.world_data;
float3 position = drw_point_screen_to_view(float3(screenco, depth));
float3 position = view.point_screen_to_view(float3(screenco, depth));
float3 normal = workbench::normal_decode(texture(normal_tx, screenco));
float2 jitter_co = (screenco * world_data.viewport_size.xy) * world_data.cavity_jitter_scale;
@ -46,9 +47,9 @@ void cavity_compute([[resource_table]] const workbench::Cavity &cavity,
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
float2 offset;
float homcoord = drw_view().winmat[2][3] * position.z + drw_view().winmat[3][3];
offset.x = drw_view().winmat[0][0] * world_data.cavity_distance / homcoord;
offset.y = drw_view().winmat[1][1] * world_data.cavity_distance / homcoord;
float homcoord = view.winmat[2][3] * position.z + view.winmat[3][3];
offset.x = view.winmat[0][0] * world_data.cavity_distance / homcoord;
offset.y = view.winmat[1][1] * world_data.cavity_distance / homcoord;
/* convert from -1...1 range to 0..1 for easy use with texture coordinates */
offset *= 0.5f;
@ -77,7 +78,7 @@ void cavity_compute([[resource_table]] const workbench::Cavity &cavity,
bool is_background = (s_depth == 1.0f);
/* This trick provide good edge effect even if no neighbor is found. */
s_depth = (is_background) ? depth : s_depth;
float3 s_pos = drw_point_screen_to_view(float3(uvcoords, s_depth));
float3 s_pos = view.point_screen_to_view(float3(uvcoords, s_depth));
if (is_background) {
s_pos.z -= world_data.cavity_distance;

View file

@ -1,64 +0,0 @@
/* SPDX-FileCopyrightText: 2018-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "gpu_shader_compat.hh"
#define EPSILON 0.00001f
#define CAVITY_BUFFER_RANGE 4.0f
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Sphere-map Transform */
float3 workbench_normal_decode(float4 enc)
{
float2 fenc = enc.xy * 4.0f - 2.0f;
float f = dot(fenc, fenc);
float g = sqrt(1.0f - f / 4.0f);
float3 n;
n.xy = fenc * g;
n.z = 1 - f / 2;
return n;
}
/* From http://aras-p.info/texts/CompactNormalStorage.html
* Using Method #4: Sphere-map Transform */
float2 workbench_normal_encode(bool front_face, float3 n)
{
n = normalize(front_face ? n : -n);
float p = sqrt(n.z * 8.0f + 8.0f);
n.xy = clamp(n.xy / p + 0.5f, 0.0f, 1.0f);
return n.xy;
}
/* Encoding into the alpha of a RGBA16F texture. (10bit mantissa) */
#define TARGET_BITCOUNT 8u
#define METALLIC_BITS 3u /* Metallic channel is less important. */
#define ROUGHNESS_BITS (TARGET_BITCOUNT - METALLIC_BITS)
/* Encode 2 float into 1 with the desired precision. */
float workbench_float_pair_encode(float v1, float v2)
{
// constexpr uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
// constexpr uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
/* Same as above because some compiler are very dumb and think we use medium int. */
constexpr int v1_mask = 0x1F;
constexpr int v2_mask = 0x7;
int iv1 = int(v1 * float(v1_mask));
int iv2 = int(v2 * float(v2_mask)) << int(ROUGHNESS_BITS);
return float(iv1 | iv2);
}
void workbench_float_pair_decode(float data, float &v1, float &v2)
{
// constexpr uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS);
// constexpr uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS);
/* Same as above because some compiler are very dumb and think we use medium int. */
constexpr int v1_mask = 0x1F;
constexpr int v2_mask = 0x7;
int idata = int(data);
v1 = float(idata & v1_mask) * (1.0f / float(v1_mask));
v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0f / float(v2_mask));
}

View file

@ -8,7 +8,6 @@
#pragma once
#include "draw_view_lib.glsl"
#include "gpu_shader_fullscreen.bsl.hh"
#include "workbench_cavity.bsl.hh"
#include "workbench_common.bsl.hh"
@ -17,11 +16,6 @@
#include "workbench_matcap.bsl.hh"
#include "workbench_world_light.bsl.hh"
/* TODO(fclem): Move to workbench. */
#define WORKBENCH_LIGHTING_STUDIO 0
#define WORKBENCH_LIGHTING_MATCAP 1
#define WORKBENCH_LIGHTING_FLAT 2
namespace workbench::resolve {
struct Resources {
@ -30,7 +24,6 @@ struct Resources {
[[compilation_constant]] bool use_curvature;
[[compilation_constant]] bool use_shadow;
[[legacy_info]] ShaderCreateInfo draw_view;
[[sampler(3)]] sampler2DDepth depth_tx;
[[sampler(4)]] sampler2D normal_tx;
[[sampler(5)]] sampler2D material_tx;
@ -58,6 +51,7 @@ struct FragOut {
[[fragment]] void frag([[frag_coord]] const float4 &frag_coord,
[[resource_table]] Resources &srt,
[[resource_table]] draw::View &views,
[[out]] FragOut &frag_out)
{
float2 uv = frag_coord.xy / float2(textureSize(srt.depth_tx, 0).xy);
@ -69,9 +63,11 @@ struct FragOut {
return;
}
ViewMatrices view = views.get(0);
/* Normal and Incident vector are in view-space. Lighting is evaluated in view-space. */
float3 P = drw_point_screen_to_view(float3(uv, 0.5f));
float3 V = drw_view_incident_vector(P);
float3 P = view.point_screen_to_view(float3(uv, 0.5f));
float3 V = view.view_incident_vector(P);
float3 N = workbench::normal_decode(texture(srt.normal_tx, uv));
float4 mat_data = texture(srt.material_tx, uv);
@ -95,7 +91,7 @@ struct FragOut {
float cavity = 0.0f, edges = 0.0f, curvature = 0.0f;
if (srt.use_cavity) [[static_branch]] {
workbench::cavity_compute(
srt.cavity, srt.world, srt.depth_tx, srt.normal_tx, uv, cavity, edges);
srt.cavity, srt.world, view, srt.depth_tx, srt.normal_tx, uv, cavity, edges);
}
if (srt.use_curvature) [[static_branch]] {

View file

@ -0,0 +1,41 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "gpu_shader_fullscreen.bsl.hh"
namespace workbench::depth {
[[vertex]]
void vert([[vertex_id]] const int vert_id, [[position]] float4 &position)
{
fullscreen_vertex(vert_id, position);
}
struct Merge {
[[sampler(0)]] sampler2DDepth depth_tx;
};
/* Merge a depth texture into the current framebuffer. */
[[fragment]] void merge([[resource_table]] const Merge &srt,
[[frag_coord]] const float4 frag_co,
[[frag_depth(any)]] float &out_depth)
{
float2 screen_uv = frag_co.xy / float2(textureSize(srt.depth_tx, 0));
out_depth = texture(srt.depth_tx, screen_uv).r;
}
/* Prepare the Depth Buffer for the Overlay Engine.
* Set the depth to 0 for "In Front" objects which have set a specific stencil bit.
* This way, the Overlay engine doesn't draw on top of them. */
[[fragment]] void overlay([[frag_depth(any)]] float &out_depth)
{
out_depth = 0.0f;
}
} // namespace workbench::depth
PipelineGraphic workbench_merge_depth(workbench::depth::vert, workbench::depth::merge);
PipelineGraphic workbench_overlay_depth(workbench::depth::vert, workbench::depth::overlay);

View file

@ -1,72 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#include "infos/workbench_effect_dof_infos.hh"
#include "gpu_shader_math_constants.bsl.hh"
#include "workbench_effect_dof_lib.glsl"
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_dof_blur1)
/**
* ----------------- STEP 2 ------------------
* Blur vertically and diagonally.
* Outputs vertical blur and combined blur in MRT
*/
float2 get_random_vector(float offset)
{
/* Interleaved gradient noise by Jorge Jimenez
* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */
float ign = fract(
offset + 52.9829189f * fract(0.06711056f * gl_FragCoord.x + 0.00583715f * gl_FragCoord.y));
float bn = texelFetch(noise_tx, int2(gl_FragCoord.xy) % 64, 0).a;
float ang = M_PI * 2.0f * fract(bn + offset);
return float2(cos(ang), sin(ang)) * sqrt(ign);
// return noise.rg * sqrt(ign);
}
void main()
{
float2 uv = gl_FragCoord.xy * inverted_viewport_size * 2.0f;
float2 size = float2(textureSize(half_res_color_tx, 0).xy);
int2 texel = int2(uv * size);
float4 color = float4(0.0f);
float tot = 0.0f;
float coc = dof_decode_coc(texelFetch(input_coc_tx, texel, 0).rg);
float max_radius = coc;
float2 noise = get_random_vector(noise_offset) * 0.2f *
clamp(max_radius * 0.2f - 4.0f, 0.0f, 1.0f);
for (int i = 0; i < NUM_SAMPLES; i++) {
float2 tc = uv + (noise + samples[i].xy) * inverted_viewport_size * max_radius;
/* decode_signed_coc return biggest coc. */
coc = abs(dof_decode_signed_coc(texture(input_coc_tx, tc).rg));
float lod = log2(clamp((coc + min(coc, max_radius)) * 0.5f - 21.0f, 0.0f, 16.0f) * 0.25f);
float4 samp = textureLod(half_res_color_tx, tc, lod);
float radius = samples[i].z * max_radius;
float weight = abs(coc) * smoothstep(radius - 0.5f, radius + 0.5f, abs(coc));
color += samp * weight;
tot += weight;
}
if (tot > 0.0f) {
blurColor = color / tot;
}
else {
blurColor = textureLod(half_res_color_tx, uv, 0.0f);
}
}

View file

@ -1,95 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#include "infos/workbench_effect_dof_infos.hh"
#include "draw_view_lib.glsl"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_effect_dof_lib.glsl"
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_dof_blur2)
/**
* ----------------- STEP 3 ------------------
* 3x3 Median Filter
* Morgan McGuire and Kyle Whitson
* http://graphics.cs.williams.edu
*
* SPDX-License-Identifier: BSD-2-Clause
* Copyright 2006 Morgan McGuire and Williams College, All rights reserved.
*/
void main()
{
/* Half Res pass */
float2 pixel_size = 1.0f / float2(textureSize(blur_tx, 0).xy);
float2 uv = gl_FragCoord.xy * pixel_size.xy;
float coc = dof_decode_coc(texture(input_coc_tx, uv).rg);
/* Only use this filter if coc is > 9.0f
* since this filter is not weighted by CoC
* and can bleed a bit. */
float rad = clamp(coc - 9.0f, 0.0f, 1.0f);
#define vec float4
#define toVec(x) x.rgba
#define s2(a, b) \
temp = a; \
a = min(a, b); \
b = max(temp, b);
#define mn3(a, b, c) \
s2(a, b); \
s2(a, c);
#define mx3(a, b, c) \
s2(b, c); \
s2(a, c);
#define mnmx3(a, b, c) \
mx3(a, b, c); \
s2(a, b); /* 3 exchanges */
#define mnmx4(a, b, c, d) \
s2(a, b); \
s2(c, d); \
s2(a, c); \
s2(b, d); /* 4 exchanges */
#define mnmx5(a, b, c, d, e) \
s2(a, b); \
s2(c, d); \
mn3(a, c, e); \
mx3(b, d, e); /* 6 exchanges */
#define mnmx6(a, b, c, d, e, f) \
s2(a, d); \
s2(b, e); \
s2(c, f); \
mn3(a, b, c); \
mx3(d, e, f); /* 7 exchanges */
vec v[9];
/* Add the pixels which make up our window to the pixel array. */
for (int dX = -1; dX <= 1; dX++) {
for (int dY = -1; dY <= 1; dY++) {
float2 offset = float2(float(dX), float(dY));
/* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) +
* (dY + R) of the pixel array. This will fill the pixel array, with the top left pixel of
* the window at pixel[0] and the bottom right pixel of the window at pixel[N-1]. */
v[(dX + 1) * 3 + (dY + 1)] = toVec(texture(blur_tx, uv + offset * pixel_size * rad));
}
}
vec temp;
/* Starting with a subset of size 6, remove the min and max each time */
mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]);
mnmx5(v[1], v[2], v[3], v[4], v[6]);
mnmx4(v[2], v[3], v[4], v[7]);
mnmx3(v[3], v[4], v[8]);
toVec(final_color) = v[4];
}

View file

@ -1,60 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#include "infos/workbench_effect_dof_infos.hh"
#include "gpu_shader_math_safe.bsl.hh"
#include "gpu_shader_math_vector_reduce.bsl.hh"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_effect_dof_lib.glsl"
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_dof_downsample)
/**
* ----------------- STEP 0.5 ------------------
* Custom COC aware down-sampling. Quarter res pass.
*/
void main()
{
float4 texel = float4(gl_FragCoord.xyxy) * 2.0f + float4(0.0f, 0.0f, 1.0f, 1.0f);
texel = (texel - 0.5f) / float4(textureSize(scene_color_tx, 0).xyxy);
/* Using texelFetch can bypass the mip range setting on some platform.
* Using texture LOD fixes this issue. Note that we need to disable filtering to get the right
* texel values. */
float4 color1 = textureLod(scene_color_tx, texel.xy, 0.0f);
float4 color2 = textureLod(scene_color_tx, texel.zw, 0.0f);
float4 color3 = textureLod(scene_color_tx, texel.zy, 0.0f);
float4 color4 = textureLod(scene_color_tx, texel.xw, 0.0f);
float2 cocs1 = textureLod(input_coc_tx, texel.xy, 0.0f).rg;
float2 cocs2 = textureLod(input_coc_tx, texel.zw, 0.0f).rg;
float2 cocs3 = textureLod(input_coc_tx, texel.zy, 0.0f).rg;
float2 cocs4 = textureLod(input_coc_tx, texel.xw, 0.0f).rg;
float4 cocs_near = float4(cocs1.r, cocs2.r, cocs3.r, cocs4.r) * MAX_COC_SIZE;
float4 cocs_far = float4(cocs1.g, cocs2.g, cocs3.g, cocs4.g) * MAX_COC_SIZE;
float coc_near = reduce_max(cocs_near);
float coc_far = reduce_max(cocs_far);
/* Now we need to write the near-far fields pre-multiplied by the COC
* also use bilateral weighting by each COC values to avoid bleeding. */
float4 near_weights = step(0.0f, cocs_near) *
clamp(1.0f - abs(coc_near - cocs_near), 0.0f, 1.0f);
float4 far_weights = step(0.0f, cocs_far) * clamp(1.0f - abs(coc_far - cocs_far), 0.0f, 1.0f);
/* now write output to weighted buffers. */
float4 w = any(notEqual(far_weights, float4(0.0f))) ? far_weights : near_weights;
outColor = weighted_sum(color1, color2, color3, color4, w);
outCocs = dof_encode_coc(coc_near, coc_far);
}

View file

@ -1,35 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#pragma once
#include "gpu_shader_math_vector.bsl.hh"
#define dof_aperturesize dof_params.x
#define dof_distance dof_params.y
#define dof_invsensorsize dof_params.z
/* divide by sensor size to get the normalized size */
#define dof_calculate_coc(zdepth) \
(dof_aperturesize * (dof_distance / zdepth - 1.0f) * dof_invsensorsize)
#define MAX_COC_SIZE 100.0f
float2 dof_encode_coc(float near, float far)
{
return float2(near, far) / MAX_COC_SIZE;
}
float dof_decode_coc(float2 cocs)
{
return max(cocs.x, cocs.y) * MAX_COC_SIZE;
}
float dof_decode_signed_coc(float2 cocs)
{
return ((cocs.x > cocs.y) ? cocs.x : -cocs.y) * MAX_COC_SIZE;
}

View file

@ -1,64 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#include "infos/workbench_effect_dof_infos.hh"
#include "draw_view_lib.glsl"
#include "gpu_shader_math_safe.bsl.hh"
#include "gpu_shader_math_vector_reduce.bsl.hh"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_effect_dof_lib.glsl"
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_dof_prepare)
/**
* ----------------- STEP 0 ------------------
* Custom COC aware down-sampling. Half res pass.
*/
void main()
{
int4 texel = int4(gl_FragCoord.xyxy) * 2 + int4(0, 0, 1, 1);
float4 color1 = texelFetch(scene_color_tx, texel.xy, 0);
float4 color2 = texelFetch(scene_color_tx, texel.zw, 0);
float4 color3 = texelFetch(scene_color_tx, texel.zy, 0);
float4 color4 = texelFetch(scene_color_tx, texel.xw, 0);
float4 depths;
depths.x = texelFetch(scene_depth_tx, texel.xy, 0).x;
depths.y = texelFetch(scene_depth_tx, texel.zw, 0).x;
depths.z = texelFetch(scene_depth_tx, texel.zy, 0).x;
depths.w = texelFetch(scene_depth_tx, texel.xw, 0).x;
float4 zdepths = float4(drw_depth_screen_to_view(depths.x),
drw_depth_screen_to_view(depths.y),
drw_depth_screen_to_view(depths.z),
drw_depth_screen_to_view(depths.w));
float4 cocs_near = dof_calculate_coc(zdepths);
float4 cocs_far = -cocs_near;
float coc_near = max(reduce_max(cocs_near), 0.0f);
float coc_far = max(reduce_max(cocs_far), 0.0f);
/* now we need to write the near-far fields premultiplied by the coc
* also use bilateral weighting by each coc values to avoid bleeding. */
float4 near_weights = step(0.0f, cocs_near) *
clamp(1.0f - abs(coc_near - cocs_near), 0.0f, 1.0f);
float4 far_weights = step(0.0f, cocs_far) * clamp(1.0f - abs(coc_far - cocs_far), 0.0f, 1.0f);
/* now write output to weighted buffers. */
/* Take far plane pixels in priority. */
float4 w = any(notEqual(far_weights, float4(0.0f))) ? far_weights : near_weights;
halfResColor = weighted_sum(color1, color2, color3, color4, w);
halfResColor = clamp(halfResColor, 0.0f, 3.0f);
normalizedCoc = dof_encode_coc(coc_near, coc_far);
}

View file

@ -1,37 +0,0 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#include "infos/workbench_effect_dof_infos.hh"
#include "draw_view_lib.glsl"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_effect_dof_lib.glsl"
/**
* ----------------- STEP 4 ------------------
*/
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_dof_resolve)
void main()
{
/* Full-screen pass. */
float2 pixel_size = 0.5f / float2(textureSize(half_res_color_tx, 0).xy);
float2 uv = gl_FragCoord.xy * pixel_size;
/* TODO: MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH. */
float depth = texelFetch(scene_depth_tx, int2(gl_FragCoord.xy), 0).r;
float zdepth = drw_depth_screen_to_view(depth);
float coc = dof_calculate_coc(zdepth);
float blend = smoothstep(1.0f, 3.0f, abs(coc));
final_colorAdd = texture(half_res_color_tx, uv) * blend;
final_colorMul = float4(1.0f - blend);
}

View file

@ -1,24 +0,0 @@
/* SPDX-FileCopyrightText: 2020-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/workbench_effect_outline_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_effect_outline)
void main()
{
float2 uv = gl_FragCoord.xy / float2(textureSize(object_id_buffer, 0));
float3 offset = float3(world_data.viewport_size_inv, 0.0f) * world_data.ui_scale;
uint center_id = texture(object_id_buffer, uv).r;
uint4 adjacent_ids = uint4(texture(object_id_buffer, uv + offset.zy).r,
texture(object_id_buffer, uv - offset.zy).r,
texture(object_id_buffer, uv + offset.xz).r,
texture(object_id_buffer, uv - offset.xz).r);
float outline_opacity = 1.0f - dot(float4(equal(uint4(center_id), adjacent_ids)), float4(0.25f));
frag_color = world_data.object_outline_color * outline_opacity;
}

View file

@ -1,27 +0,0 @@
/* SPDX-FileCopyrightText: 2018-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/workbench_effect_antialiasing_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_taa)
void main()
{
float2 texel_size = 1.0f / float2(textureSize(color_buffer, 0));
float2 uv = gl_FragCoord.xy * texel_size;
frag_color = float4(0.0f);
int i = 0;
for (int x = -1; x <= 1; x++) [[unroll]] {
for (int y = -1; y <= 1; y++, i++) [[unroll]] {
float4 color = texture(color_buffer, uv + float2(x, y) * texel_size);
/* Clamp infinite inputs (See #112211). */
color = clamp(color, float4(0.0f), float4(1e10f));
/* Use log2 space to avoid highlights creating too much aliasing. */
color.rgb = log2(color.rgb + 1.0f);
frag_color += color * samplesWeights[i];
}
}
}

View file

@ -1,15 +0,0 @@
/* SPDX-FileCopyrightText: 2015-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/workbench_depth_infos.hh"
#include "infos/workbench_effect_dof_infos.hh"
VERTEX_SHADER_CREATE_INFO(workbench_merge_depth)
#include "gpu_shader_fullscreen.bsl.hh"
void main()
{
fullscreen_vertex(gl_VertexID, gl_Position);
}

View file

@ -0,0 +1,408 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
* Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois
* https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
#pragma once
#include "draw_view.bsl.hh"
#include "gpu_shader_fullscreen.bsl.hh"
#include "gpu_shader_math_safe.bsl.hh"
#include "gpu_shader_math_vector_reduce.bsl.hh"
namespace workbench::dof {
[[vertex]]
void vert([[vertex_id]] const int vert_id, [[position]] float4 &position)
{
fullscreen_vertex(vert_id, position);
}
#define MAX_COC_SIZE 100.0f
float2 dof_encode_coc(float near, float far)
{
return float2(near, far) / MAX_COC_SIZE;
}
float dof_decode_coc(float2 cocs)
{
return max(cocs.x, cocs.y) * MAX_COC_SIZE;
}
float dof_decode_signed_coc(float2 cocs)
{
return ((cocs.x > cocs.y) ? cocs.x : -cocs.y) * MAX_COC_SIZE;
}
float4 sum_weighted(float4 val0, float4 val1, float4 val2, float4 val3, float4 weights)
{
return (val0 * weights[0] + val1 * weights[1] + val2 * weights[2] + val3 * weights[3]) *
safe_rcp(weights[0] + weights[1] + weights[2] + weights[3]);
}
struct DepthOfField {
[[push_constant]] float2 inverted_viewport_size;
[[push_constant]] float2 near_far;
[[push_constant]] float3 dof_params;
[[push_constant]] float noise_offset;
/* divide by sensor size to get the normalized size */
template<typename T> T calculate_coc(T z_depth)
{
float aperture_size = dof_params.x;
float distance = dof_params.y;
float invsensor_size = dof_params.z;
return aperture_size * (distance / z_depth - 1.0f) * invsensor_size;
}
};
template float DepthOfField::calculate_coc<float>(float);
template float4 DepthOfField::calculate_coc<float4>(float4);
/*
* NOTE: Keep the sampler bind points consistent between the steps.
*
* [[sampler(0)]] sampler2D input_coc_tx;
* [[sampler(1)]] sampler2D scene_color_tx;
* [[sampler(2)]] sampler2D scene_depth_tx;
* [[sampler(3)]] sampler2D half_res_color_tx;
* [[sampler(4)]] sampler2D blur_tx;
* [[sampler(5)]] sampler2D noise_tx;
*/
/**
* ----------------- STEP 0 ------------------
* Custom COC aware down-sampling. Half res pass.
*/
struct Prepare {
[[sampler(1)]] sampler2D scene_color_tx;
[[sampler(2)]] sampler2D scene_depth_tx;
};
struct PrepareOut {
[[frag_color(0)]] float4 half_res_color;
[[frag_color(1)]] float2 normalized_coc;
};
[[fragment]] void prepare([[resource_table]] DepthOfField &dof,
[[resource_table]] Prepare &srt,
[[resource_table]] draw::View &views,
[[out]] PrepareOut &out,
[[frag_coord]] const float4 frag_co)
{
int4 texel = int4(frag_co.xyxy) * 2 + int4(0, 0, 1, 1);
float4 color1 = texelFetch(srt.scene_color_tx, texel.xy, 0);
float4 color2 = texelFetch(srt.scene_color_tx, texel.zw, 0);
float4 color3 = texelFetch(srt.scene_color_tx, texel.zy, 0);
float4 color4 = texelFetch(srt.scene_color_tx, texel.xw, 0);
float4 depths;
depths.x = texelFetch(srt.scene_depth_tx, texel.xy, 0).x;
depths.y = texelFetch(srt.scene_depth_tx, texel.zw, 0).x;
depths.z = texelFetch(srt.scene_depth_tx, texel.zy, 0).x;
depths.w = texelFetch(srt.scene_depth_tx, texel.xw, 0).x;
ViewMatrices view = views.get(0);
float4 zdepths = float4(view.depth_screen_to_view(depths.x),
view.depth_screen_to_view(depths.y),
view.depth_screen_to_view(depths.z),
view.depth_screen_to_view(depths.w));
float4 cocs_near = dof.calculate_coc(zdepths);
float4 cocs_far = -cocs_near;
float coc_near = max(reduce_max(cocs_near), 0.0f);
float coc_far = max(reduce_max(cocs_far), 0.0f);
/* now we need to write the near-far fields premultiplied by the coc
* also use bilateral weighting by each coc values to avoid bleeding. */
float4 near_weights = step(0.0f, cocs_near) *
clamp(1.0f - abs(coc_near - cocs_near), 0.0f, 1.0f);
float4 far_weights = step(0.0f, cocs_far) * clamp(1.0f - abs(coc_far - cocs_far), 0.0f, 1.0f);
/* now write output to weighted buffers. */
/* Take far plane pixels in priority. */
float4 w = any(notEqual(far_weights, float4(0.0f))) ? far_weights : near_weights;
out.half_res_color = sum_weighted(color1, color2, color3, color4, w);
out.half_res_color = clamp(out.half_res_color, 0.0f, 3.0f);
out.normalized_coc = dof_encode_coc(coc_near, coc_far);
}
/**
* ----------------- STEP 1 ------------------
* Custom COC aware down-sampling. Quarter res pass.
*/
struct DownSample {
[[sampler(0)]] sampler2D input_coc_tx;
[[sampler(1)]] sampler2D scene_color_tx;
};
struct DownSampleOut {
[[frag_color(0)]] float4 color;
[[frag_color(1)]] float2 cocs;
};
[[fragment]] void downsample([[resource_table]] DownSample &srt,
[[out]] DownSampleOut &out,
[[frag_coord]] const float4 frag_co)
{
float4 texel = float4(frag_co.xyxy) * 2.0f + float4(0.0f, 0.0f, 1.0f, 1.0f);
texel = (texel - 0.5f) / float4(textureSize(srt.scene_color_tx, 0).xyxy);
/* Using texelFetch can bypass the mip range setting on some platform.
* Using texture LOD fixes this issue. Note that we need to disable filtering to get the right
* texel values. */
float4 color1 = textureLod(srt.scene_color_tx, texel.xy, 0.0f);
float4 color2 = textureLod(srt.scene_color_tx, texel.zw, 0.0f);
float4 color3 = textureLod(srt.scene_color_tx, texel.zy, 0.0f);
float4 color4 = textureLod(srt.scene_color_tx, texel.xw, 0.0f);
float2 cocs1 = textureLod(srt.input_coc_tx, texel.xy, 0.0f).rg;
float2 cocs2 = textureLod(srt.input_coc_tx, texel.zw, 0.0f).rg;
float2 cocs3 = textureLod(srt.input_coc_tx, texel.zy, 0.0f).rg;
float2 cocs4 = textureLod(srt.input_coc_tx, texel.xw, 0.0f).rg;
float4 cocs_near = float4(cocs1.r, cocs2.r, cocs3.r, cocs4.r) * MAX_COC_SIZE;
float4 cocs_far = float4(cocs1.g, cocs2.g, cocs3.g, cocs4.g) * MAX_COC_SIZE;
float coc_near = reduce_max(cocs_near);
float coc_far = reduce_max(cocs_far);
/* Now we need to write the near-far fields pre-multiplied by the COC
* also use bilateral weighting by each COC values to avoid bleeding. */
float4 near_weights = step(0.0f, cocs_near) *
clamp(1.0f - abs(coc_near - cocs_near), 0.0f, 1.0f);
float4 far_weights = step(0.0f, cocs_far) * clamp(1.0f - abs(coc_far - cocs_far), 0.0f, 1.0f);
/* now write output to weighted buffers. */
float4 w = any(notEqual(far_weights, float4(0.0f))) ? far_weights : near_weights;
out.color = sum_weighted(color1, color2, color3, color4, w);
out.cocs = dof_encode_coc(coc_near, coc_far);
}
/**
* ----------------- STEP 2 ------------------
* Blur vertically and diagonally.
* Outputs vertical blur and combined blur in MRT
*/
static constexpr int dof_sample_count = 49;
struct Blur1 {
[[sampler(0)]] sampler2D input_coc_tx;
[[sampler(3)]] sampler2D half_res_color_tx;
[[sampler(5)]] sampler2D noise_tx;
[[uniform(1)]] float4 samples[dof_sample_count];
float2 get_random_vector(float2 frag_co, float offset) const
{
/* Interleaved gradient noise by Jorge Jimenez
* http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */
float ign = fract(offset +
52.9829189f * fract(0.06711056f * frag_co.x + 0.00583715f * frag_co.y));
float bn = texelFetch(noise_tx, int2(frag_co.xy) % 64, 0).a;
float ang = M_PI * 2.0f * fract(bn + offset);
return float2(cos(ang), sin(ang)) * sqrt(ign);
}
};
struct Blur1Out {
[[frag_color(0)]] float4 color;
};
[[fragment]] void blur1([[resource_table]] DepthOfField &dof,
[[resource_table]] Blur1 &srt,
[[out]] Blur1Out &out,
[[frag_coord]] const float4 frag_co)
{
float2 uv = frag_co.xy * dof.inverted_viewport_size * 2.0f;
float2 size = float2(textureSize(srt.half_res_color_tx, 0).xy);
int2 texel = int2(uv * size);
float4 color = float4(0.0f);
float tot = 0.0f;
float coc = dof_decode_coc(texelFetch(srt.input_coc_tx, texel, 0).rg);
float max_radius = coc;
float2 noise = srt.get_random_vector(frag_co.xy, dof.noise_offset) * 0.2f *
clamp(max_radius * 0.2f - 4.0f, 0.0f, 1.0f);
for (int i = 0; i < dof_sample_count; i++) {
float2 tc = uv + (noise + srt.samples[i].xy) * dof.inverted_viewport_size * max_radius;
/* decode_signed_coc return biggest coc. */
coc = abs(dof_decode_signed_coc(texture(srt.input_coc_tx, tc).rg));
float lod = log2(clamp((coc + min(coc, max_radius)) * 0.5f - 21.0f, 0.0f, 16.0f) * 0.25f);
float4 samp = textureLod(srt.half_res_color_tx, tc, lod);
float radius = srt.samples[i].z * max_radius;
float weight = abs(coc) * smoothstep(radius - 0.5f, radius + 0.5f, abs(coc));
color += samp * weight;
tot += weight;
}
if (tot > 0.0f) {
out.color = color / tot;
}
else {
out.color = textureLod(srt.half_res_color_tx, uv, 0.0f);
}
}
/**
* ----------------- STEP 3 ------------------
* 3x3 Median Filter
* Morgan McGuire and Kyle Whitson
* http://graphics.cs.williams.edu
*
* SPDX-License-Identifier: BSD-2-Clause
* Copyright 2006 Morgan McGuire and Williams College, All rights reserved.
*/
struct Blur2 {
[[sampler(0)]] sampler2D input_coc_tx;
[[sampler(4)]] sampler2D blur_tx;
};
struct Blur2Out {
[[frag_color(0)]] float4 color;
};
[[force_inline]] void s2(float4 &a, float4 &b)
{
float4 temp = a;
a = min(a, b);
b = max(temp, b);
}
[[force_inline]] void mn3(float4 &a, float4 &b, float4 &c)
{
s2(a, b);
s2(a, c);
}
[[force_inline]] void mx3(float4 &a, float4 &b, float4 &c)
{
s2(b, c);
s2(a, c);
}
[[force_inline]] void mnmx3(float4 &a, float4 &b, float4 &c)
{
mx3(a, b, c);
s2(a, b); /* 3 exchanges */
}
[[force_inline]] void mnmx4(float4 &a, float4 &b, float4 &c, float4 &d)
{
s2(a, b);
s2(c, d);
s2(a, c);
s2(b, d); /* 4 exchanges */
}
[[force_inline]] void mnmx5(float4 &a, float4 &b, float4 &c, float4 &d, float4 &e)
{
s2(a, b);
s2(c, d);
mn3(a, c, e);
mx3(b, d, e); /* 6 exchanges */
}
[[force_inline]] void mnmx6(float4 &a, float4 &b, float4 &c, float4 &d, float4 &e, float4 &f)
{
s2(a, d);
s2(b, e);
s2(c, f);
mn3(a, b, c);
mx3(d, e, f); /* 7 exchanges */
}
[[fragment]] void blur2([[resource_table]] Blur2 &srt,
[[out]] Blur2Out &out,
[[frag_coord]] const float4 frag_co)
{
/* Half Res pass */
float2 pixel_size = 1.0f / float2(textureSize(srt.blur_tx, 0).xy);
float2 uv = frag_co.xy * pixel_size.xy;
float coc = dof_decode_coc(texture(srt.input_coc_tx, uv).rg);
/* Only use this filter if coc is > 9.0f
* since this filter is not weighted by CoC
* and can bleed a bit. */
float rad = clamp(coc - 9.0f, 0.0f, 1.0f);
float4 v[9];
/* Add the pixels which make up our window to the pixel array. */
for (int dX = -1; dX <= 1; dX++) [[unroll]] {
for (int dY = -1; dY <= 1; dY++) [[unroll]] {
float2 offset = float2(float(dX), float(dY));
/* If a pixel in the window is located at (x+dX, y+dY), put it at index (dX + R)(2R + 1) +
* (dY + R) of the pixel array. This will fill the pixel array, with the top left pixel of
* the window at pixel[0] and the bottom right pixel of the window at pixel[N-1]. */
v[(dX + 1) * 3 + (dY + 1)] = texture(srt.blur_tx, uv + offset * pixel_size * rad);
}
}
/* Starting with a subset of size 6, remove the min and max each time */
mnmx6(v[0], v[1], v[2], v[3], v[4], v[5]);
mnmx5(v[1], v[2], v[3], v[4], v[6]);
mnmx4(v[2], v[3], v[4], v[7]);
mnmx3(v[3], v[4], v[8]);
out.color = v[4];
}
/**
* ----------------- STEP 4 ------------------
*/
struct Resolve {
[[sampler(2)]] sampler2D scene_depth_tx;
[[sampler(3)]] sampler2D half_res_color_tx;
};
struct ResolveOut {
[[frag_color(0), index(0)]] float4 color_add;
[[frag_color(0), index(1)]] float4 color_mul;
};
[[fragment]] void resolve([[resource_table]] DepthOfField &dof,
[[resource_table]] Resolve &srt,
[[resource_table]] draw::View &views,
[[out]] ResolveOut &out,
[[frag_coord]] const float4 frag_co)
{
/* Full-screen pass. */
float2 pixel_size = 0.5f / float2(textureSize(srt.half_res_color_tx, 0).xy);
float2 uv = frag_co.xy * pixel_size;
ViewMatrices view = views.get(0);
/* TODO: MAKE SURE TO ALIGN SAMPLE POSITION TO AVOID OFFSET IN THE BOKEH. */
float depth = texelFetch(srt.scene_depth_tx, int2(frag_co.xy), 0).r;
float zdepth = view.depth_screen_to_view(depth);
float coc = dof.calculate_coc(zdepth);
float blend = smoothstep(1.0f, 3.0f, abs(coc));
out.color_add = texture(srt.half_res_color_tx, uv) * blend;
out.color_mul = float4(1.0f - blend);
}
} // namespace workbench::dof
PipelineGraphic workbench_effect_dof_prepare(workbench::dof::vert, workbench::dof::prepare);
PipelineGraphic workbench_effect_dof_downsample(workbench::dof::vert, workbench::dof::downsample);
PipelineGraphic workbench_effect_dof_blur1(workbench::dof::vert, workbench::dof::blur1);
PipelineGraphic workbench_effect_dof_blur2(workbench::dof::vert, workbench::dof::blur2);
PipelineGraphic workbench_effect_dof_resolve(workbench::dof::vert, workbench::dof::resolve);

View file

@ -0,0 +1,49 @@
/* SPDX-FileCopyrightText: 2020-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "gpu_shader_fullscreen.bsl.hh"
#include "workbench_shader_shared.hh"
namespace workbench::outline {
[[vertex]]
void vert([[vertex_id]] const int vert_id, [[position]] float4 &position)
{
fullscreen_vertex(vert_id, position);
}
struct Outlines {
[[sampler(0)]] usampler2D object_id_buffer;
[[uniform(WB_WORLD_SLOT)]] WorldData &world_data;
};
struct FragOut {
[[frag_color(0)]] float4 color;
};
[[fragment]]
void frag([[resource_table]] const Outlines &srt,
[[frag_coord]] const float4 frag_co,
[[out]] FragOut &frag_out)
{
float2 uv = frag_co.xy / float2(textureSize(srt.object_id_buffer, 0));
float3 offset = float3(srt.world_data.viewport_size_inv, 0.0f) * srt.world_data.ui_scale;
uint center_id = texture(srt.object_id_buffer, uv).r;
uint4 adjacent_ids = uint4(texture(srt.object_id_buffer, uv + offset.zy).r,
texture(srt.object_id_buffer, uv - offset.zy).r,
texture(srt.object_id_buffer, uv + offset.xz).r,
texture(srt.object_id_buffer, uv - offset.xz).r);
float outline_opacity = 1.0f - dot(float4(equal(uint4(center_id), adjacent_ids)), float4(0.25f));
frag_out.color = srt.world_data.object_outline_color * outline_opacity;
}
} // namespace workbench::outline
PipelineGraphic workbench_effect_outline(workbench::outline::vert, workbench::outline::frag);

View file

@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2018-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "gpu_shader_fullscreen.bsl.hh"
namespace workbench::taa {
[[vertex]]
void vert([[vertex_id]] const int vert_id, [[position]] float4 &position)
{
fullscreen_vertex(vert_id, position);
}
struct FragOut {
[[frag_color(0)]] float4 color;
};
struct TemporalAA {
[[push_constant]] float samplesWeights[9];
[[sampler(0)]] sampler2D color_buffer;
};
[[fragment]]
void frag([[resource_table]] const TemporalAA &srt,
[[frag_coord]] const float4 frag_co,
[[out]] FragOut &frag_out)
{
float2 texel_size = 1.0f / float2(textureSize(srt.color_buffer, 0));
float2 uv = frag_co.xy * texel_size;
frag_out.color = float4(0.0f);
int i = 0;
for (int x = -1; x <= 1; x++) [[unroll]] {
for (int y = -1; y <= 1; y++) [[unroll]] {
float4 color = texture(srt.color_buffer, uv + float2(x, y) * texel_size);
/* Clamp infinite inputs (See #112211). */
color = clamp(color, float4(0.0f), float4(1e10f));
/* Use log2 space to avoid highlights creating too much aliasing. */
color.rgb = log2(color.rgb + 1.0f);
frag_out.color += color * srt.samplesWeights[i];
i++;
}
}
}
} // namespace workbench::taa
PipelineGraphic workbench_taa(workbench::taa::vert, workbench::taa::frag);

View file

@ -1,71 +0,0 @@
/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "infos/workbench_prepass_infos.hh"
SHADER_LIBRARY_CREATE_INFO(workbench_color_texture)
/* TODO(fclem): deduplicate code. */
bool node_tex_tile_lookup(float3 &co, sampler1DArray map)
{
float2 tile_pos = floor(co.xy);
if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) {
return false;
}
float tile = 10.0f * tile_pos.y + tile_pos.x;
if (tile >= textureSize(map, 0).x) {
return false;
}
/* Fetch tile information. */
float tile_layer = texelFetch(map, int2(int(tile), 0), 0).x;
if (tile_layer < 0.0f) {
return false;
}
float4 tile_info = texelFetch(map, int2(int(tile), 1), 0);
co = float3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer);
return true;
}
float3 workbench_image_color(float2 uvs)
{
#ifdef WORKBENCH_COLOR_TEXTURE
float4 color;
float3 co = float3(uvs, 0.0f);
if (is_image_tile) {
if (node_tex_tile_lookup(co, imageTileData)) {
color = texture(imageTileArray, co);
}
else {
color = float4(1.0f, 0.0f, 1.0f, 1.0f);
}
}
else {
color = texture(imageTexture, uvs);
}
/* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
if (image_premult && !(color.a == 0.0f || color.a == 1.0f)) {
color.rgb /= color.a;
}
# ifdef GPU_FRAGMENT_SHADER
if (color.a < image_transparency_cutoff) {
gpu_discard_fragment();
}
# endif
return color.rgb;
#else
return float3(1.0f);
#endif
}

View file

@ -1,48 +0,0 @@
/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "infos/workbench_prepass_infos.hh"
#ifdef GPU_LIBRARY_SHADER
SHADER_LIBRARY_CREATE_INFO(workbench_prepass)
#endif
float2 matcap_uv_compute(float3 I, float3 N, bool flipped)
{
/* Quick creation of an orthonormal basis */
float a = 1.0f / (1.0f + I.z);
float b = -I.x * I.y * a;
float3 b1 = float3(1.0f - I.x * I.x * a, b, -I.x);
float3 b2 = float3(b, 1.0f - I.y * I.y * a, -I.y);
float2 matcap_uv = float2(dot(b1, N), dot(b2, N));
if (flipped) {
matcap_uv.x = -matcap_uv.x;
}
return matcap_uv * 0.496f + 0.5f;
}
float3 get_matcap_lighting(
sampler2D diffuse_matcap, sampler2D specular_matcap, float3 base_color, float3 N, float3 I)
{
bool flipped = world_data.matcap_orientation != 0;
float2 uv = matcap_uv_compute(I, N, flipped);
float3 diffuse = textureLod(diffuse_matcap, uv, 0.0f).rgb;
float3 specular = textureLod(specular_matcap, uv, 0.0f).rgb;
return diffuse * base_color + specular * float(world_data.use_specular);
}
float3 get_matcap_lighting(sampler2DArray matcap, float3 base_color, float3 N, float3 I)
{
bool flipped = world_data.matcap_orientation != 0;
float2 uv = matcap_uv_compute(I, N, flipped);
float3 diffuse = textureLod(matcap, float3(uv, 0.0f), 0.0f).rgb;
float3 specular = textureLod(matcap, float3(uv, 1.0f), 0.0f).rgb;
return diffuse * base_color + specular * float(world_data.use_specular);
}

View file

@ -1,13 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/workbench_depth_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_merge_depth)
void main()
{
float2 screen_uv = gl_FragCoord.xy / float2(textureSize(depth_tx, 0));
gl_FragDepth = texture(depth_tx, screen_uv).r;
}

View file

@ -1,16 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* Prepare the Depth Buffer for the Overlay Engine. */
#include "infos/workbench_depth_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_overlay_depth)
void main()
{
/* Set the depth to 0 for "In Front" objects,
* so the Overlay engine doesn't draw on top of them. */
gl_FragDepth = 0.0f;
}

View file

@ -4,14 +4,11 @@
#pragma once
#include "draw_view_infos.hh" // IWYU pragma: export
#include "draw_curves_lib.glsl"
#include "draw_curves.bsl.hh"
#include "draw_gsplat_lib.bsl.hh"
#include "draw_model.bsl.hh"
#include "draw_pointcloud_lib.glsl"
#include "draw_pointcloud.bsl.hh"
#include "draw_view.bsl.hh"
#include "draw_view_clipping_lib.glsl"
#include "gpu_shader_common_hash.bsl.hh"
#include "gpu_shader_math_base.bsl.hh"
#include "workbench_common.bsl.hh"
@ -27,6 +24,33 @@ namespace workbench::prepass {
#define WORKBENCH_LIGHTING_MATCAP 1
#define WORKBENCH_LIGHTING_FLAT 2
struct ClippingConstant {
[[compilation_constant]] const bool use_clipping;
};
struct Clipping {
[[resource_table]] ClippingConstant constants;
[[uniform(DRW_CLIPPING_UBO_SLOT)]] const float4 (&drw_clipping_)[6];
void set_clipping_distances(float3 ws_P,
float &dist0,
float &dist1,
float &dist2,
float &dist3,
float &dist4,
float &dist5) const
{
float4 pos_4d = float4(ws_P, 1.0f);
dist0 = dot(drw_clipping_[0], pos_4d);
dist1 = dot(drw_clipping_[1], pos_4d);
dist2 = dot(drw_clipping_[2], pos_4d);
dist3 = dot(drw_clipping_[3], pos_4d);
dist4 = dot(drw_clipping_[4], pos_4d);
dist5 = dot(drw_clipping_[5], pos_4d);
}
};
/* Special function only to be used with calculate_transparent_weight(). */
float linear_zdepth(float depth, float4x4 proj_mat)
{
@ -114,21 +138,12 @@ struct MeshIn {
[[attribute(3)]] float2 au;
};
struct Mesh {
[[legacy_info]] ShaderCreateInfo drw_clipped;
/**
* WORKAROUND: This exact compilation constant is checked in Metal backend to enable clip
* distances.
*/
[[compilation_constant]] const bool use_clipping;
};
[[vertex]] void vert_mesh([[resource_table]] Mesh &mesh,
[[resource_table]] color::Materials &materials,
[[vertex]] void vert_mesh([[resource_table]] color::Materials &materials,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table]] draw::ResourceCustomID &resources,
[[resource_table]] const Clipping &clip,
[[clip_distance]] [[condition(use_clipping)]] float (&clip_distances)[6],
[[instance_index]] const int inst_id,
[[in]] const MeshIn &v_in,
[[out]] VertOut &v_out,
@ -143,8 +158,14 @@ struct Mesh {
float3 world_pos = obj.point_object_to_world(v_in.pos);
out_position = view.point_world_to_homogenous(world_pos);
if (mesh.use_clipping) [[static_branch]] {
view_clipping_distances(world_pos);
if (clip.constants.use_clipping) [[static_branch]] {
clip.set_clipping_distances(world_pos,
clip_distances[0],
clip_distances[1],
clip_distances[2],
clip_distances[3],
clip_distances[4],
clip_distances[5]);
}
v_out.uv = v_in.au;
@ -158,30 +179,24 @@ struct Mesh {
}
struct Curves {
[[legacy_info]] ShaderCreateInfo draw_curves;
[[legacy_info]] ShaderCreateInfo draw_curves_infos;
[[legacy_info]] ShaderCreateInfo drw_clipped;
/**
* WORKAROUND: This exact compilation constant is checked in Metal backend to enable clip
* distances.
*/
[[compilation_constant]] const bool use_clipping;
[[sampler(WB_CURVES_COLOR_SLOT) /*, frequency(batch)*/]] samplerBuffer ac;
[[sampler(WB_CURVES_UV_SLOT) /*, frequency(batch)*/]] samplerBuffer au;
[[sampler(WB_CURVES_COLOR_SLOT), frequency(BATCH)]] samplerBuffer ac;
[[sampler(WB_CURVES_UV_SLOT), frequency(BATCH)]] samplerBuffer au;
[[push_constant]] const int emitter_object_id;
};
[[vertex]] void vert_curves([[resource_table]] Curves &curves,
[[resource_table]] color::Materials &materials,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table]] draw::ResourceCustomID &resources,
[[instance_index]] const int inst_id,
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
[[vertex]] void vert_curves(
[[resource_table]] Curves &srt,
[[resource_table]] color::Materials &materials,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table]] draw::ResourceCustomID &resources,
[[resource_table]] draw::Curves &curves,
[[instance_index]] const int inst_id,
[[resource_table]] const Clipping &clip,
[[clip_distance]] [[condition(use_clipping)]] float (&clip_distances)[6],
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
{
int custom_id = int(resources.get_custom_id(inst_id));
@ -189,12 +204,10 @@ struct Curves {
ViewMatrices view = views.get(id.view_id<1>());
ObjectMatrices obj = models.get(id.resource_id<1>());
const auto &drw_curves = buffer_get(draw_curves_infos, drw_curves);
const curves::Point ls_pt = curves::point_get(uint(vert_id));
const curves::Point ws_pt = curves::object_to_world(ls_pt, obj.model);
const curves::ShapePoint pt = curves::shape_point_get(ws_pt,
view.world_incident_vector(ws_pt.P));
const draw::curves::Point ls_pt = curves.point_get(uint(vert_id));
const draw::curves::Point ws_pt = curves.object_to_world(ls_pt, obj.model);
const draw::curves::ShapePoint pt = curves.shape_point_get(ws_pt,
view.world_incident_vector(ws_pt.P));
float3 world_pos = pt.P;
out_position = view.point_world_to_homogenous(world_pos);
@ -202,26 +215,32 @@ struct Curves {
float hair_rand = workbench::prepass::integer_noise(ws_pt.curve_id);
float3 nor = pt.N;
if (drw_curves.half_cylinder_face_count == 1) {
if (curves.drw_curves.half_cylinder_face_count == 1) {
/* Very cheap smooth normal using attribute interpolator.
* Using the correct normals over the cylinder (-1..1) leads to unwanted result as the
* interpolation is not spherical but linear. So we use a smaller range (-SQRT2..SQRT2) in
* which the linear interpolation is close enough to the desired result. */
nor = pt.N + pt.curve_N;
}
else if (drw_curves.half_cylinder_face_count == 0) {
else if (curves.drw_curves.half_cylinder_face_count == 0) {
nor = hair_random_normal(pt.curve_T, pt.curve_B, pt.curve_N, hair_rand);
}
if (curves.use_clipping) [[static_branch]] {
view_clipping_distances(world_pos);
if (clip.constants.use_clipping) [[static_branch]] {
clip.set_clipping_distances(world_pos,
clip_distances[0],
clip_distances[1],
clip_distances[2],
clip_distances[3],
clip_distances[4],
clip_distances[5]);
}
v_out.uv = curves::get_customdata_vec2(ws_pt.curve_id, curves.au);
v_out.uv = draw::curves::get_customdata_vec2(ws_pt.curve_id, srt.au);
v_out.normal = normalize(view.normal_world_to_view(nor));
float3 vert_col = curves::get_customdata_vec3(ws_pt.curve_id, curves.ac);
float3 vert_col = draw::curves::get_customdata_vec3(ws_pt.curve_id, srt.ac);
materials.material_data_get(
custom_id, vert_col, v_out.color, v_out.alpha, v_out.roughness, v_out.metallic);
@ -233,31 +252,24 @@ struct Curves {
v_out.object_id = int(id.resource_id<1>() & 0xFFFFu) + 1;
if (curves.emitter_object_id != 0) {
v_out.object_id = int(uint(curves.emitter_object_id) & 0xFFFFu) + 1;
if (srt.emitter_object_id != 0) {
v_out.object_id = int(uint(srt.emitter_object_id) & 0xFFFFu) + 1;
}
}
struct PointCloud {
[[legacy_info]] ShaderCreateInfo draw_pointcloud;
[[legacy_info]] ShaderCreateInfo drw_clipped;
/**
* WORKAROUND: This exact compilation constant is checked in Metal backend to enable clip
* distances.
*/
[[compilation_constant]] const bool use_clipping;
};
[[vertex]] void vert_pointcloud([[resource_table]] PointCloud &point_cloud,
[[resource_table]] color::Materials &materials,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table]] draw::ResourceCustomID &resources,
[[instance_index]] const int inst_id,
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
[[vertex]] void vert_pointcloud(
[[resource_table]] color::Materials &materials,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Infos &infos,
[[resource_table]] draw::Model &models,
[[resource_table]] draw::PointCloud &pt_cloud,
[[resource_table]] draw::ResourceCustomID &resources,
[[resource_table]] const Clipping &clip,
[[clip_distance]] [[condition(use_clipping)]] float (&clip_distances)[6],
[[instance_index]] const int inst_id,
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
{
int custom_id = int(resources.get_custom_id(inst_id));
@ -266,20 +278,26 @@ struct PointCloud {
ViewMatrices view = views.get(id.view_id<1>());
ObjectMatrices obj = models.get(res_id);
const ObjectInfos ob_infos = infos.get(res_id);
const eObjectInfoFlag ob_flag = ob_infos.flag;
const eObjectInfoFlag ob_flag = buffer_get(draw_object_infos, drw_infos)[res_id].flag;
const pointcloud::Point ls_pt = pointcloud::point_get(uint(vert_id));
const pointcloud::Point ws_pt = pointcloud::object_to_world(ls_pt, obj.model);
const pointcloud::ShapePoint pt = pointcloud::shape_point_get(
const draw::pointcloud::Point ls_pt = pt_cloud.point_get(uint(vert_id));
const draw::pointcloud::Point ws_pt = draw::pointcloud::object_to_world(ls_pt, obj.model);
const draw::pointcloud::ShapePoint pt = draw::pointcloud::shape_point_get(
ws_pt, view.world_incident_vector(ws_pt.P), view.up(), ob_flag);
v_out.normal = normalize(view.normal_world_to_view(pt.N));
out_position = view.point_world_to_homogenous(pt.P);
if (point_cloud.use_clipping) [[static_branch]] {
view_clipping_distances(pt.P);
if (clip.constants.use_clipping) [[static_branch]] {
clip.set_clipping_distances(pt.P,
clip_distances[0],
clip_distances[1],
clip_distances[2],
clip_distances[3],
clip_distances[4],
clip_distances[5]);
}
v_out.uv = float2(0.0f);
@ -290,24 +308,18 @@ struct PointCloud {
v_out.object_id = int(id.resource_id<1>() & 0xFFFFu) + 1;
}
struct GSplat {
[[legacy_info]] ShaderCreateInfo drw_clipped;
/** WORKAROUND: This exact compilation constant is checked in Metal backend to enable clip
* distances. */
[[compilation_constant]] const bool use_clipping;
};
[[vertex]] void vert_gsplat([[resource_table]] GSplat &gsplat,
[[resource_table]] const color::Materials &materials,
[[resource_table]] const draw::gsplat::ShapeResource &shape,
[[resource_table]] const draw::View &views,
[[resource_table]] const draw::Model &models,
[[resource_table]] const draw::ResourceCustomID &resources,
[[instance_index]] const int inst_id,
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
[[vertex]] void vert_gsplat(
[[resource_table]] const color::Materials &materials,
[[resource_table]] const draw::gsplat::ShapeResource &shape,
[[resource_table]] const draw::View &views,
[[resource_table]] const draw::Model &models,
[[resource_table]] const draw::ResourceCustomID &resources,
[[resource_table]] const Clipping &clip,
[[clip_distance]] [[condition(use_clipping)]] float (&clip_distances)[6],
[[instance_index]] const int inst_id,
[[vertex_id]] const int vert_id,
[[out]] VertOut &v_out,
[[position]] float4 &out_position)
{
int custom_id = int(resources.get_custom_id(inst_id));
@ -329,8 +341,14 @@ struct GSplat {
out_position = gs.hP;
if (gsplat.use_clipping) [[static_branch]] {
view_clipping_distances(gs.wP);
if (clip.constants.use_clipping) [[static_branch]] {
clip.set_clipping_distances(gs.wP,
clip_distances[0],
clip_distances[1],
clip_distances[2],
clip_distances[3],
clip_distances[4],
clip_distances[5]);
}
materials.material_data_get(
@ -447,102 +465,102 @@ struct TransparentOut {
}
/* clang-format off */
PipelineGraphic mesh_opaque_studio_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_studio_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_opaque_studio_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_studio_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_opaque_matcap_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_matcap_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_opaque_matcap_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_matcap_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_opaque_flat_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_flat_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_opaque_flat_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_opaque_flat_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic curves_opaque_studio_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_studio_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_opaque_studio_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_studio_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_opaque_matcap_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_matcap_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_opaque_matcap_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_matcap_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_opaque_flat_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_flat_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_opaque_flat_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_opaque_flat_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic ptcloud_opaque_studio_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_studio_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_opaque_studio_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_studio_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_opaque_matcap_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_matcap_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_opaque_matcap_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_matcap_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_opaque_flat_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_flat_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_opaque_flat_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_opaque_flat_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic gsplat_opaque_studio_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_studio_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_opaque_studio_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_studio_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_opaque_matcap_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_matcap_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_opaque_matcap_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_matcap_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_opaque_flat_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_flat_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_opaque_flat_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_opaque_flat_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic mesh_transparent_studio_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_studio_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_transparent_studio_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_studio_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_transparent_matcap_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_matcap_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_transparent_matcap_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_matcap_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_transparent_flat_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_flat_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic mesh_transparent_flat_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = true });
PipelineGraphic mesh_transparent_flat_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Mesh{.use_clipping = false});
PipelineGraphic curves_transparent_studio_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_studio_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_transparent_studio_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_studio_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_transparent_matcap_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_matcap_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_transparent_matcap_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_matcap_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_transparent_flat_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_flat_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic curves_transparent_flat_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = true });
PipelineGraphic curves_transparent_flat_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, Curves{.use_clipping = false});
PipelineGraphic ptcloud_transparent_studio_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_studio_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_transparent_studio_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_studio_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_transparent_matcap_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_matcap_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_transparent_matcap_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_matcap_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_transparent_flat_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_flat_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic ptcloud_transparent_flat_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = true });
PipelineGraphic ptcloud_transparent_flat_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, PointCloud{.use_clipping = false});
PipelineGraphic gsplat_transparent_studio_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_studio_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_transparent_studio_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_studio_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_transparent_matcap_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_matcap_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_transparent_matcap_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_matcap_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_transparent_flat_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_flat_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic gsplat_transparent_flat_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = true });
PipelineGraphic gsplat_transparent_flat_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, GSplat{.use_clipping = false});
PipelineGraphic mesh_opaque_studio_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_studio_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_opaque_studio_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_studio_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_opaque_matcap_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_matcap_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_opaque_matcap_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_matcap_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_opaque_flat_material_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_flat_material_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_opaque_flat_texture_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_opaque_flat_texture_no_clip( vert_mesh, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_studio_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_studio_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_studio_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_studio_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_matcap_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_matcap_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_matcap_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_matcap_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_flat_material_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_flat_material_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_opaque_flat_texture_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_opaque_flat_texture_no_clip( vert_curves, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_studio_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_studio_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_studio_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_studio_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_matcap_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_matcap_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_matcap_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_matcap_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_flat_material_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_flat_material_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_opaque_flat_texture_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_opaque_flat_texture_no_clip( vert_pointcloud, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_studio_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_studio_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_studio_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_studio_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_matcap_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_matcap_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_matcap_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_matcap_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_flat_material_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_flat_material_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_opaque_flat_texture_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_opaque_flat_texture_no_clip( vert_gsplat, frag_opaque, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_studio_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_studio_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_studio_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_studio_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_matcap_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_matcap_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_matcap_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_matcap_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_flat_material_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_flat_material_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic mesh_transparent_flat_texture_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic mesh_transparent_flat_texture_no_clip( vert_mesh, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_studio_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_studio_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_studio_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_studio_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_matcap_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_matcap_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_matcap_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_matcap_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_flat_material_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_flat_material_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic curves_transparent_flat_texture_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic curves_transparent_flat_texture_no_clip( vert_curves, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_studio_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_studio_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_studio_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_studio_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_matcap_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_matcap_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_matcap_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_matcap_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_flat_material_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_flat_material_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic ptcloud_transparent_flat_texture_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = true });
PipelineGraphic ptcloud_transparent_flat_texture_no_clip( vert_pointcloud, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = false}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_studio_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_studio_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_studio_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_studio_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 0 /* WORKBENCH_LIGHTING_STUDIO */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_matcap_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_matcap_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_matcap_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_matcap_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 1 /* WORKBENCH_LIGHTING_MATCAP */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_flat_material_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_flat_material_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = false, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
PipelineGraphic gsplat_transparent_flat_texture_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = true });
PipelineGraphic gsplat_transparent_flat_texture_no_clip( vert_gsplat, frag_transparent, Resources{.lighting_mode = 2 /* WORKBENCH_LIGHTING_FLAT */, .use_texture = true, .use_gsplat = true}, ClippingConstant{.use_clipping = false});
/* clang-format on */
} // namespace workbench::prepass

View file

@ -19,13 +19,10 @@
#pragma once
#include "draw_view_infos.hh"
#include "gpu_index_load_infos.hh"
#include "draw_model_lib.glsl"
#include "draw_view_lib.glsl"
#include "draw_model.bsl.hh"
#include "draw_view.bsl.hh"
#include "gpu_shader_attribute_load_lib.glsl"
#include "gpu_shader_index_load_lib.glsl"
#include "gpu_shader_index_load.bsl.hh"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_shader_shared.hh"
@ -49,9 +46,10 @@ struct GeomOut {
};
struct Resources {
[[legacy_info]] ShaderCreateInfo gpu_index_buffer_load;
[[legacy_info]] ShaderCreateInfo draw_view;
[[legacy_info]] ShaderCreateInfo draw_modelmat;
[[resource_table]] IndexLoad index_load;
[[resource_table]] draw::View views;
[[resource_table]] draw::Model models;
/* WORKAROUND: Needed to support OpenSubdiv vertex format. Should be removed. */
[[push_constant]] const int2 gpu_attr_3;
@ -64,20 +62,25 @@ struct Resources {
VertIn input_assembly(uint in_vertex_id) const
{
uint v_i = gpu_index_load(in_vertex_id);
uint v_i = index_load.load(in_vertex_id);
VertIn vert_in;
vert_in.lP = gpu_attr_load_float3(this->pos, this->gpu_attr_3, v_i);
vert_in.lP = float3(pos[gpu_attr_load_index(v_i, gpu_attr_3) + 0],
pos[gpu_attr_load_index(v_i, gpu_attr_3) + 1],
pos[gpu_attr_load_index(v_i, gpu_attr_3) + 2]);
return vert_in;
}
VertOut vertex_main(VertIn vert_in) const
VertOut vertex_main(VertIn vert_in, uint resource_id) const
{
VertOut vert_out;
vert_out.lP = vert_in.lP;
float3 L = this->pass_data.light_direction_ws;
float3 ws_P = drw_point_object_to_world(vert_in.lP);
ObjectMatrices model = models.get(resource_id);
ViewMatrices view = views.get(0);
float3 ws_P = model.point_object_to_world(vert_in.lP);
float extrude_distance = 1e5f;
float L_FP = dot(L, this->pass_data.far_plane.xyz);
if (L_FP > 0.0f) {
@ -87,8 +90,9 @@ struct Resources {
/* Ensure we don't overlap the far plane. */
extrude_distance -= 1e-3f;
}
vert_out.backPosition = drw_point_world_to_homogenous(ws_P + L * extrude_distance);
vert_out.frontPosition = drw_point_world_to_homogenous(drw_point_object_to_world(vert_in.lP));
vert_out.backPosition = view.point_world_to_homogenous(ws_P + L * extrude_distance);
vert_out.frontPosition = view.point_world_to_homogenous(
model.point_object_to_world(vert_in.lP));
return vert_out;
}
};
@ -176,11 +180,12 @@ struct GeometryShaderEmulator {
emit_triangle_vert(2, out_vertex_id, geom_out);
}
void geometry_main([[resource_table]] const Resources &srt,
void geometry_main(const Resources &srt,
VertOut geom_in[4],
uint out_vertex_id,
uint out_primitive_id,
uint out_invocation_id)
uint out_invocation_id,
uint resource_id)
{
float3 v10 = geom_in[0].lP - geom_in[1].lP;
float3 v12 = geom_in[2].lP - geom_in[1].lP;
@ -189,7 +194,7 @@ struct GeometryShaderEmulator {
float3 n1 = cross(v12, v10);
float3 n2 = cross(v13, v12);
#ifdef DEGENERATE_TRIS_WORKAROUND
#if 0 /* DEGENERATE_TRIS_WORKAROUND */
/* Check if area is null */
float2 faces_area = float2(length_squared(n1), length_squared(n2));
bool2 degen_faces = lessThan(abs(faces_area), float2(DEGENERATE_TRIS_AREA_THRESHOLD));
@ -199,8 +204,9 @@ struct GeometryShaderEmulator {
return;
}
#endif
ObjectMatrices model = srt.models.get(resource_id);
float3 ls_light_direction = drw_normal_world_to_object(
float3 ls_light_direction = model.normal_world_to_object(
float3(srt.pass_data.light_direction_ws));
float2 facing = float2(dot(n1, ls_light_direction), dot(n2, ls_light_direction));
@ -210,7 +216,7 @@ struct GeometryShaderEmulator {
/* WATCH: maybe unpredictable in some cases. */
bool is_manifold = any(notEqual(geom_in[0].lP, geom_in[3].lP));
#ifdef DEGENERATE_TRIS_WORKAROUND
#if 0 /* DEGENERATE_TRIS_WORKAROUND */
if (srt.double_manifold == false) [[static_branch]] {
/* If the mesh is known to be manifold and we don't use double count,
* only create an quad if the we encounter a facing geom. */
@ -243,14 +249,17 @@ struct GeometryShaderEmulator {
void geometry_main_caps([[resource_table]] const Resources &srt,
VertOut geom_in[3],
uint out_vertex_id,
uint out_invocation_id)
uint out_invocation_id,
uint resource_id)
{
float3 v10 = geom_in[0].lP - geom_in[1].lP;
float3 v12 = geom_in[2].lP - geom_in[1].lP;
float3 Ng = cross(v12, v10);
float3 ls_light_direction = drw_normal_world_to_object(
ObjectMatrices model = srt.models.get(resource_id);
float3 ls_light_direction = model.normal_world_to_object(
float3(srt.pass_data.light_direction_ws));
float facing = dot(Ng, ls_light_direction);
@ -275,7 +284,9 @@ struct GeometryShaderEmulator {
[[vertex]]
void vert_main([[resource_table]] const Resources &srt,
[[resource_table]] const draw::Resource &res,
[[vertex_id]] const int vert_id,
[[instance_index]] const int inst_index,
[[position]] float4 &out_position)
{
/* Line adjacency primitive. */
@ -302,6 +313,8 @@ void vert_main([[resource_table]] const Resources &srt,
uint out_invocation_id = (uint(vert_id) / output_vertex_count_per_invocation) %
output_invocation_count;
uint resource_id = res.get(inst_index).resource_id<1>();
VertIn vert_in[input_primitive_vertex_count];
vert_in[0] = srt.input_assembly(in_primitive_first_vertex + 0u);
vert_in[1] = srt.input_assembly(in_primitive_first_vertex + 1u);
@ -309,21 +322,23 @@ void vert_main([[resource_table]] const Resources &srt,
vert_in[3] = srt.input_assembly(in_primitive_first_vertex + 3u);
VertOut vert_out[input_primitive_vertex_count];
vert_out[0] = srt.vertex_main(vert_in[0]);
vert_out[1] = srt.vertex_main(vert_in[1]);
vert_out[2] = srt.vertex_main(vert_in[2]);
vert_out[3] = srt.vertex_main(vert_in[3]);
vert_out[0] = srt.vertex_main(vert_in[0], resource_id);
vert_out[1] = srt.vertex_main(vert_in[1], resource_id);
vert_out[2] = srt.vertex_main(vert_in[2], resource_id);
vert_out[3] = srt.vertex_main(vert_in[3], resource_id);
GeometryShaderEmulator gs;
/* Discard by default. */
gs.out_pos = float4(NAN_FLT);
gs.geometry_main(srt, vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
gs.geometry_main(srt, vert_out, out_vertex_id, out_primitive_id, out_invocation_id, resource_id);
out_position = gs.out_pos;
}
[[vertex]]
void vert_main_caps([[resource_table]] const Resources &srt,
[[resource_table]] const draw::Resource &res,
[[vertex_id]] const int vert_id,
[[instance_index]] const int inst_index,
[[position]] float4 &out_position)
{
/* Triangle list primitive. */
@ -345,20 +360,22 @@ void vert_main_caps([[resource_table]] const Resources &srt,
uint out_invocation_id = (uint(vert_id) / output_vertex_count_per_invocation) %
output_invocation_count;
uint resource_id = res.get(inst_index).resource_id<1>();
VertIn vert_in[input_primitive_vertex_count];
vert_in[0] = srt.input_assembly(in_primitive_first_vertex + 0u);
vert_in[1] = srt.input_assembly(in_primitive_first_vertex + 1u);
vert_in[2] = srt.input_assembly(in_primitive_first_vertex + 2u);
VertOut vert_out[input_primitive_vertex_count];
vert_out[0] = srt.vertex_main(vert_in[0]);
vert_out[1] = srt.vertex_main(vert_in[1]);
vert_out[2] = srt.vertex_main(vert_in[2]);
vert_out[0] = srt.vertex_main(vert_in[0], resource_id);
vert_out[1] = srt.vertex_main(vert_in[1], resource_id);
vert_out[2] = srt.vertex_main(vert_in[2], resource_id);
GeometryShaderEmulator gs;
/* Discard by default. */
gs.out_pos = float4(NAN_FLT);
gs.geometry_main_caps(srt, vert_out, out_vertex_id, out_invocation_id);
gs.geometry_main_caps(srt, vert_out, out_vertex_id, out_invocation_id, resource_id);
out_position = gs.out_pos;
}

View file

@ -4,7 +4,7 @@
#pragma once
#include "draw_view_lib.glsl"
#include "draw_view.bsl.hh"
#include "gpu_shader_fullscreen.bsl.hh"
#include "gpu_shader_utildefines.bsl.hh"
#include "workbench_common.bsl.hh"
@ -13,8 +13,6 @@
namespace workbench::shadow::rt {
struct Resources {
[[legacy_info]] ShaderCreateInfo draw_view;
[[uniform(1)]] const ShadowPassData &pass_data;
[[sampler(2)]] const sampler2DDepth depth_tx;
[[sampler(3)]] const sampler2D normal_tx;
@ -26,7 +24,9 @@ struct Resources {
fullscreen_vertex(vert_id, out_pos);
}
[[fragment]] void frag([[frag_coord]] const float4 &frag_coord, [[resource_table]] Resources &srt)
[[fragment]] void frag([[frag_coord]] const float4 &frag_coord,
[[resource_table]] Resources &srt,
[[resource_table]] const draw::View &views)
{
const float2 resolution = float2(textureSize(srt.depth_tx, 0).xy);
const float2 screen_uv = frag_coord.xy / resolution;
@ -37,7 +37,9 @@ struct Resources {
return;
}
const float3 N = drw_normal_view_to_world(
ViewMatrices view = views.get(0);
const float3 N = view.normal_view_to_world(
workbench::normal_decode(texture(srt.normal_tx, screen_uv)));
if (dot(N, srt.pass_data.light_direction_ws) >= 0.0f) {
/* We already know the fragment is in shadow. No need to query. */
@ -45,11 +47,11 @@ struct Resources {
}
/* Offset depth to compensate for depth buffer precision. */
float3 P = drw_point_screen_to_world(
float3 P = view.point_screen_to_world(
float3(screen_uv, intBitsToFloat(floatBitsToInt(depth) - 2)));
const float pixel_size = srt.pass_data.pixel_size *
(drw_view_is_perspective() ? drw_view_z_distance(P) : 1.0f);
(view.is_perspective() ? view.z_distance(P) : 1.0f);
/* Offset by pixel size to compensate for floating point precision. */
const float tMin = pixel_size / max(dot(N, -srt.pass_data.light_direction_ws), 0.1f);

View file

@ -8,10 +8,7 @@
#pragma once
#include "draw_view_infos.hh"
#include "gpu_index_load_infos.hh"
#include "draw_intersect_lib.glsl"
#include "draw_intersect.bsl.hh"
#include "workbench_shader_shared.hh"
namespace workbench::shadow::visibility {
@ -19,8 +16,7 @@ namespace workbench::shadow::visibility {
struct Resources {
[[compilation_constant]] const bool dynamic_pass_selection;
[[legacy_info]] ShaderCreateInfo draw_view;
[[legacy_info]] ShaderCreateInfo draw_view_culling;
[[resource_table]] draw::ViewCulling view_culling;
[[storage(0, read)]] const ObjectBounds (&bounds_buf)[];
[[push_constant]] const int resource_len;
@ -57,7 +53,7 @@ struct Resources {
bool intersects_near_plane(IsectBox box)
{
float4 near_plane = drw_view_culling().frustum_planes.planes[4];
float4 near_plane = view_culling.get(0).frustum_planes.planes[4];
bool on_positive_side = false;
bool on_negative_side = false;

View file

@ -1,93 +0,0 @@
/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/workbench_prepass_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_prepass)
FRAGMENT_SHADER_CREATE_INFO(workbench_transparent_accum)
FRAGMENT_SHADER_CREATE_INFO(workbench_lighting_matcap)
#include "draw_view_lib.glsl"
#include "workbench_common_lib.glsl"
#include "workbench_image_lib.glsl"
#include "workbench_matcap_lib.glsl"
#include "workbench_world_light_lib.glsl"
/* Special function only to be used with calculate_transparent_weight(). */
float linear_zdepth(float depth, float4x4 proj_mat)
{
if (proj_mat[3][3] == 0.0f) {
float d = 2.0f * depth - 1.0f;
return -proj_mat[3][2] / (d + proj_mat[2][2]);
}
else {
/* Return depth from near plane. */
float z_delta = -2.0f / proj_mat[2][2];
return depth * z_delta;
}
}
/* Based on :
* McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
* Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
*/
float calculate_transparent_weight()
{
float z = linear_zdepth(gl_FragCoord.z, drw_view().winmat);
#if 0
/* Eq 10 : Good for surfaces with varying opacity (like particles) */
float a = min(1.0f, alpha * 10.0f) + 0.01f;
float b = -gl_FragCoord.z * 0.95f + 1.0f;
float w = a * a * a * 3e2f * b * b * b;
#else
/* Eq 7 put more emphasis on surfaces closer to the view. */
// float w = 10.0f / (1e-5f + pow(abs(z) / 5.0f, 2.0f) + pow(abs(z) / 200.0f, 6.0f)); /* Eq 7 */
// float w = 10.0f / (1e-5f + pow(abs(z) / 10.0f, 3.0f) + pow(abs(z) / 200.0f, 6.0f)); /* Eq 8 */
// float w = 10.0f / (1e-5f + pow(abs(z) / 200.0f, 4.0f)); /* Eq 9 */
/* Same as eq 7, but optimized. */
float a = abs(z) / 5.0f;
float b = abs(z) / 200.0f;
b *= b;
float w = 10.0f / ((1e-5f + a * a) + b * (b * b)); /* Eq 7 */
#endif
return clamp(w, 1e-2f, 3e2f);
}
void main()
{
/* Normal and Incident vector are in view-space. Lighting is evaluated in view-space. */
float2 uv_viewport = gl_FragCoord.xy * world_data.viewport_size_inv;
float3 vP = drw_point_screen_to_view(float3(uv_viewport, 0.5f));
float3 I = drw_view_incident_vector(vP);
float3 N = normalize(normal_interp);
float3 color = color_interp;
#ifdef WORKBENCH_COLOR_TEXTURE
color = workbench_image_color(uv_interp);
#endif
float3 shaded_color;
#ifdef WORKBENCH_LIGHTING_MATCAP
shaded_color = get_matcap_lighting(matcap_tx, color, N, I);
#endif
#ifdef WORKBENCH_LIGHTING_STUDIO
shaded_color = get_world_lighting(color, _roughness, metallic, N, I);
#endif
#ifdef WORKBENCH_LIGHTING_FLAT
shaded_color = color;
#endif
shaded_color *= get_shadow(N, force_shadowing);
/* Listing 4 */
float alpha = alpha_interp * world_data.xray_alpha;
float weight = calculate_transparent_weight() * alpha;
out_transparent_accum = float4(shaded_color * weight, alpha);
out_revealage_accum = float4(weight);
out_object_id = uint(object_id);
}

View file

@ -0,0 +1,53 @@
/* SPDX-FileCopyrightText: 2020-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* Based on :
* McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
* Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
*/
#pragma once
#include "gpu_shader_fullscreen.bsl.hh"
namespace workbench::transparency {
[[vertex]]
void vert([[vertex_id]] const int vert_id, [[position]] float4 &position)
{
fullscreen_vertex(vert_id, position);
}
struct Resolve {
[[sampler(0)]] sampler2D transparent_accum;
[[sampler(1)]] sampler2D transparent_revealage;
};
struct FragOut {
[[frag_color(0)]] float4 color;
};
[[fragment]]
void resolve_weight_blended_order_independant_transparency([[resource_table]] const Resolve &srt,
[[frag_coord]] const float4 frag_co,
[[out]] FragOut &frag_out)
{
float2 screen_uv = frag_co.xy / float2(textureSize(srt.transparent_accum, 0).xy);
/* Revealage is actually stored in transparent_accum alpha channel.
* This is a workaround to older hardware not having separate blend equation per render target.
*/
float4 trans_accum = texture(srt.transparent_accum, screen_uv);
float trans_weight = texture(srt.transparent_revealage, screen_uv).r;
float trans_reveal = trans_accum.a;
/* Listing 4 */
frag_out.color.rgb = trans_accum.rgb / clamp(trans_weight, 1e-4f, 5e4f);
frag_out.color.a = 1.0f - trans_reveal;
}
} // namespace workbench::transparency
PipelineGraphic workbench_transparent_resolve(
workbench::transparency::vert,
workbench::transparency::resolve_weight_blended_order_independant_transparency);

View file

@ -1,27 +0,0 @@
/* SPDX-FileCopyrightText: 2020-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* Based on :
* McGuire and Bavoil, Weighted Blended Order-Independent Transparency, Journal of
* Computer Graphics Techniques (JCGT), vol. 2, no. 2, 122–141, 2013
*/
#include "infos/workbench_transparent_resolve_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(workbench_transparent_resolve)
void main()
{
float2 screen_uv = gl_FragCoord.xy / float2(textureSize(transparent_accum, 0).xy);
/* Revealage is actually stored in transparent_accum alpha channel.
* This is a workaround to older hardware not having separate blend equation per render target.
*/
float4 trans_accum = texture(transparent_accum, screen_uv);
float trans_weight = texture(transparent_revealage, screen_uv).r;
float trans_reveal = trans_accum.a;
/* Listing 4 */
frag_color.rgb = trans_accum.rgb / clamp(trans_weight, 1e-4f, 5e4f);
frag_color.a = 1.0f - trans_reveal;
}

View file

@ -4,13 +4,9 @@
#pragma once
#include "gpu_shader_compat.hh"
#include "draw_object_infos_infos.hh"
#include "draw_model_lib.glsl"
#include "draw_object_infos_lib.glsl"
#include "draw_view_lib.glsl"
#include "draw_model.bsl.hh"
#include "draw_view.bsl.hh"
#include "draw_volume.bsl.hh"
#include "gpu_shader_math_constants.bsl.hh"
#include "gpu_shader_math_vector_compare.bsl.hh"
#include "gpu_shader_math_vector_reduce.bsl.hh"
@ -74,7 +70,7 @@ float4 sample_closest(sampler3D ima, float3 co)
/* Legacy Fluid Simulation Modifier. */
struct Smoke {
[[legacy_info]] const ShaderCreateInfo draw_modelmat;
[[resource_table]] draw::Model model;
[[sampler(2)]] const sampler3D flame_tx;
[[sampler(3)]] const sampler1D flame_color_tx;
@ -82,8 +78,6 @@ struct Smoke {
/* Volume Objects. */
struct Volume {
[[legacy_info]] const ShaderCreateInfo draw_volume;
[[push_constant]] const float4x4 volume_texture_to_object;
[[push_constant]] const float4x4 volume_object_to_texture;
};
@ -108,10 +102,6 @@ struct ColorUniform {
};
struct Resources {
[[legacy_info]] const ShaderCreateInfo draw_view;
[[legacy_info]] const ShaderCreateInfo draw_object_infos;
[[legacy_info]] const ShaderCreateInfo draw_resource_id_varying;
[[compilation_constant]] const bool use_slice;
[[compilation_constant]] const bool use_color_band;
[[compilation_constant]] const bool is_legacy_smoke;
@ -269,8 +259,6 @@ void eval_volume_step(float3 &Lscat, float extinction, float step_len, float &Tr
Lscat = (Lscat - Lscat * Tr) / extinction;
}
#define P(x) ((x + 0.5f) * (1.0f / 16.0f))
float4 volume_integration([[resource_table]] Resources &srt,
float4 frag_coord,
float3 ray_ori,
@ -281,10 +269,10 @@ float4 volume_integration([[resource_table]] Resources &srt,
{
/* NOTE: Constant array declared inside function scope to reduce shader core thread memory
* pressure on Apple Silicon. */
constexpr float4 dither_mat[4] = {float4(P(0.0f), P(8.0f), P(2.0f), P(10.0f)),
float4(P(12.0f), P(4.0f), P(14.0f), P(6.0f)),
float4(P(3.0f), P(11.0f), P(1.0f), P(9.0f)),
float4(P(15.0f), P(7.0f), P(13.0f), P(5.0f))};
const float4 dither_mat[4] = {(float4(0.0f, 8.0f, 2.0f, 10.0f) + 0.5f) / 16.0f,
(float4(12.0f, 4.0f, 14.0f, 6.0f) + 0.5f) / 16.0f,
(float4(3.0f, 11.0f, 1.0f, 9.0f) + 0.5f) / 16.0f,
(float4(15.0f, 7.0f, 13.0f, 5.0f) + 0.5f) / 16.0f};
/* Start with full transmittance and no scattered light. */
float3 final_scattering = float3(0.0f);
float final_transmittance = 1.0f;
@ -318,18 +306,29 @@ struct VertIn {
[[attribute(0)]] float3 pos;
};
struct ResourceIDOut {
[[flat]] uint id;
};
struct VertOut {
[[smooth]] float3 local_pos;
};
[[vertex]] void vertex_function([[resource_table]] Resources &srt,
[[resource_table]] draw::Resource &ids,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table, condition(is_legacy_smoke)]] draw::Infos &infos,
[[instance_index]] const int inst_index,
[[in]] const VertIn &v_in,
[[out]] ResourceIDOut &res_id_out,
[[out, condition(use_slice)]] VertOut &v_out,
[[position]] float4 &out_position)
{
SHADER_LIBRARY_CREATE_INFO(draw_resource_id_varying);
res_id_out.id = ids.get(inst_index).resource_id<1>();
drw_ResourceID_iface.resource_id = drw_resource_id_raw();
ObjectMatrices model = models.get(res_id_out.id);
ViewMatrices view = views.get(0);
float3 final_pos;
@ -350,24 +349,29 @@ struct VertOut {
}
if (srt.is_legacy_smoke) [[static_branch]] {
ObjectInfos info = drw_object_infos();
ObjectInfos info = infos.get(res_id_out.id);
final_pos = ((final_pos * 0.5f + 0.5f) - info.orco_add) / info.orco_mul;
}
else {
[[resource_table]] Volume &volume = srt.volume;
final_pos = (volume.volume_texture_to_object * float4(final_pos * 0.5f + 0.5f, 1.0f)).xyz;
}
out_position = drw_point_world_to_homogenous(drw_point_object_to_world(final_pos));
out_position = view.point_world_to_homogenous(model.point_object_to_world(final_pos));
}
struct FragOut {
[[frag_color(0)]] float4 color;
};
[[fragment]] void fragment_function([[resource_table]] Resources &srt,
[[frag_coord]] const float4 &frag_coord,
[[in, condition(use_slice)]] const VertOut &v_out,
[[out]] FragOut &frag_out)
[[fragment]] void fragment_function(
[[resource_table]] Resources &srt,
[[resource_table]] draw::View &views,
[[resource_table]] draw::Model &models,
[[resource_table]] [[condition(is_legacy_smoke)]] draw::Infos &infos,
[[frag_coord]] const float4 &frag_coord,
[[in]] const ResourceIDOut &res_id,
[[in, condition(use_slice)]] const VertOut &v_out,
[[out]] FragOut &frag_out)
{
uint stencil = texelFetch(srt.stencil_tx, int2(frag_coord.xy), 0).r;
@ -378,6 +382,9 @@ struct FragOut {
return;
}
ObjectMatrices model = models.get(res_id.id);
ViewMatrices view = views.get(0);
if (srt.use_slice) [[static_branch]] {
/* Manual depth test. TODO: remove. */
float depth = texelFetch(srt.depth_buffer, int2(frag_coord.xy), 0).r;
@ -402,24 +409,25 @@ struct FragOut {
}
else {
float2 screen_uv = frag_coord.xy / float2(textureSize(srt.depth_buffer, 0).xy);
bool is_persp = drw_view().winmat[3][3] == 0.0f;
bool is_persp = view.winmat[3][3] == 0.0f;
float depth = srt.do_depth_test ? texelFetch(srt.depth_buffer, int2(frag_coord.xy), 0).r :
1.0f;
float depth_end = min(depth, frag_coord.z);
float3 vs_ray_end = drw_point_screen_to_view(float3(screen_uv, depth_end));
float3 vs_ray_ori = drw_point_screen_to_view(float3(screen_uv, 0.0f));
float3 vs_ray_end = view.point_screen_to_view(float3(screen_uv, depth_end));
float3 vs_ray_ori = view.point_screen_to_view(float3(screen_uv, 0.0f));
float3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : float3(0.0f, 0.0f, -1.0f);
vs_ray_dir /= abs(vs_ray_dir.z);
float3 ls_ray_dir = drw_point_view_to_object(vs_ray_ori + vs_ray_dir);
float3 ls_ray_ori = drw_point_view_to_object(vs_ray_ori);
float3 ls_ray_end = drw_point_view_to_object(vs_ray_end);
float3 ls_ray_dir = model.point_view_to_object(view, vs_ray_ori + vs_ray_dir);
float3 ls_ray_ori = model.point_view_to_object(view, vs_ray_ori);
float3 ls_ray_end = model.point_view_to_object(view, vs_ray_end);
if (srt.is_legacy_smoke) [[static_branch]] {
ls_ray_dir = (drw_object_orco(ls_ray_dir)) * 2.0f - 1.0f;
ls_ray_ori = (drw_object_orco(ls_ray_ori)) * 2.0f - 1.0f;
ls_ray_end = (drw_object_orco(ls_ray_end)) * 2.0f - 1.0f;
ObjectInfos ob_infos = infos.get(res_id.id);
ls_ray_dir = (ob_infos.orco_mul * ls_ray_dir + ob_infos.orco_add) * 2.0f - 1.0f;
ls_ray_ori = (ob_infos.orco_mul * ls_ray_ori + ob_infos.orco_add) * 2.0f - 1.0f;
ls_ray_end = (ob_infos.orco_mul * ls_ray_end + ob_infos.orco_add) * 2.0f - 1.0f;
}
else {
[[resource_table]] Volume &volume = srt.volume;

View file

@ -1,151 +0,0 @@
/* SPDX-FileCopyrightText: 2018-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "infos/workbench_prepass_infos.hh"
#ifdef GPU_LIBRARY_SHADER
SHADER_LIBRARY_CREATE_INFO(workbench_prepass)
#endif
/* [Drobot2014a] Low Level Optimizations for GCN */
float4 fast_rcp(float4 v)
{
return intBitsToFloat(0x7eef370b - floatBitsToInt(v));
}
float3 brdf_approx(float3 spec_color, float roughness, float NV)
{
/* Very rough approximation. We don't need it to be correct, just fast.
* Just simulate fresnel effect with roughness attenuation. */
float fresnel = exp2(-8.35f * NV) * (1.0f - roughness);
return mix(spec_color, float3(1.0f), fresnel);
}
void prep_specular(
float3 L, float3 I, float3 N, float3 R, float &NL, float &wrapped_NL, float &spec_angle)
{
wrapped_NL = dot(L, R);
float3 half_dir = normalize(L + I);
spec_angle = clamp(dot(half_dir, N), 0.0f, 1.0f);
NL = clamp(dot(L, N), 0.0f, 1.0f);
}
/* Normalized Blinn shading */
float4 blinn_specular(float4 shininess, float4 spec_angle, float4 NL)
{
/* Pi is already divided in the light power.
* normalization_factor = (shininess + 8.0f) / (8.0f * M_PI) */
float4 normalization_factor = shininess * 0.125f + 1.0f;
float4 spec_light = pow(spec_angle, shininess) * NL * normalization_factor;
return spec_light;
}
/* NL need to be unclamped. w in [0..1] range. */
float4 wrapped_lighting(float4 NL, float4 w)
{
float4 w_1 = w + 1.0f;
float4 denom = fast_rcp(w_1 * w_1);
return clamp((NL + w) * denom, 0.0f, 1.0f);
}
float3 get_world_lighting(float3 base_color, float roughness, float metallic, float3 N, float3 I)
{
float3 specular_color, diffuse_color;
if (world_data.use_specular) {
diffuse_color = mix(base_color, float3(0.0f), metallic);
specular_color = mix(float3(0.05f), base_color, metallic);
}
else {
diffuse_color = base_color;
specular_color = float3(0.0f);
}
float3 specular_light = world_data.ambient_color.rgb;
float3 diffuse_light = world_data.ambient_color.rgb;
float4 wrap = float4(world_data.lights[0].diffuse_color_wrap.a,
world_data.lights[1].diffuse_color_wrap.a,
world_data.lights[2].diffuse_color_wrap.a,
world_data.lights[3].diffuse_color_wrap.a);
if (world_data.use_specular) {
/* Prepare Specular computation. Eval 4 lights at once. */
float3 R = -reflect(I, N);
#ifdef GPU_METAL
/* Split vectors into arrays of floats. Partial vector references are unsupported by MSL. */
float spec_angle[4], spec_NL[4], wrap_NL[4];
# define AS_VEC4(a) float4(a[0], a[1], a[2], a[3])
#else
float4 spec_angle, spec_NL, wrap_NL;
# define AS_VEC4(a) a
#endif
prep_specular(
world_data.lights[0].direction.xyz, I, N, R, spec_NL[0], wrap_NL[0], spec_angle[0]);
prep_specular(
world_data.lights[1].direction.xyz, I, N, R, spec_NL[1], wrap_NL[1], spec_angle[1]);
prep_specular(
world_data.lights[2].direction.xyz, I, N, R, spec_NL[2], wrap_NL[2], spec_angle[2]);
prep_specular(
world_data.lights[3].direction.xyz, I, N, R, spec_NL[3], wrap_NL[3], spec_angle[3]);
float4 gloss = float4(1.0f - roughness);
/* Reduce gloss for smooth light. (simulate bigger light) */
gloss *= 1.0f - wrap;
float4 shininess = exp2(10.0f * gloss + 1.0f);
float4 spec_light = blinn_specular(shininess, AS_VEC4(spec_angle), AS_VEC4(spec_NL));
/* Simulate Env. light. */
float4 w = mix(wrap, float4(1.0f), roughness);
float4 spec_env = wrapped_lighting(AS_VEC4(wrap_NL), w);
#undef AS_VEC4
spec_light = mix(spec_light, spec_env, wrap * wrap);
/* Multiply result by lights specular colors. */
specular_light += spec_light.x * world_data.lights[0].specular_color.rgb;
specular_light += spec_light.y * world_data.lights[1].specular_color.rgb;
specular_light += spec_light.z * world_data.lights[2].specular_color.rgb;
specular_light += spec_light.w * world_data.lights[3].specular_color.rgb;
float NV = clamp(dot(N, I), 0.0f, 1.0f);
specular_color = brdf_approx(specular_color, roughness, NV);
}
specular_light *= specular_color;
/* Prepare diffuse computation. Eval 4 lights at once. */
float4 diff_NL;
diff_NL.x = dot(world_data.lights[0].direction.xyz, N);
diff_NL.y = dot(world_data.lights[1].direction.xyz, N);
diff_NL.z = dot(world_data.lights[2].direction.xyz, N);
diff_NL.w = dot(world_data.lights[3].direction.xyz, N);
float4 diff_light = wrapped_lighting(diff_NL, wrap);
/* Multiply result by lights diffuse colors. */
diffuse_light += diff_light.x * world_data.lights[0].diffuse_color_wrap.rgb;
diffuse_light += diff_light.y * world_data.lights[1].diffuse_color_wrap.rgb;
diffuse_light += diff_light.z * world_data.lights[2].diffuse_color_wrap.rgb;
diffuse_light += diff_light.w * world_data.lights[3].diffuse_color_wrap.rgb;
/* Energy conservation with colored specular look strange.
* Limit this strangeness by using mono-chromatic specular intensity. */
float spec_energy = dot(specular_color, float3(0.33333f));
diffuse_light *= diffuse_color * (1.0f - spec_energy);
return diffuse_light + specular_light;
}
float get_shadow(float3 N, bool force_shadow)
{
float light_factor = -dot(N, world_data.shadow_direction_vs.xyz);
float shadow_mix = smoothstep(world_data.shadow_shift, world_data.shadow_focus, light_factor);
shadow_mix *= force_shadow ? 0.0f : world_data.shadow_mul;
return shadow_mix + world_data.shadow_add;
}

View file

@ -24,3 +24,7 @@
/* UBOs (Storage buffers in Workbench Next). */
#define WB_MATERIAL_SLOT 0
#define WB_WORLD_SLOT 1
[[maybe_unused]] static constexpr int WORKBENCH_LIGHTING_STUDIO = 0;
[[maybe_unused]] static constexpr int WORKBENCH_LIGHTING_MATCAP = 1;
[[maybe_unused]] static constexpr int WORKBENCH_LIGHTING_FLAT = 2;

View file

@ -186,7 +186,10 @@ int main(int argc, char **argv)
if (/* Add non-ported files here. */
filename.ends_with("gpu_shader_material_radial_tiling.bsl.hh") ||
filename.ends_with("gpu_shader_material_tex_voronoi.bsl.hh") ||
/* Need new compiler to have support for raytracing API. */
filename.ends_with("workbench_shadow_raytrace.bsl.hh") ||
(filename.find("gpu/shaders/") == std::string::npos &&
filename.find("workbench/shaders/") == std::string::npos &&
filename.find("eevee/shaders/") == std::string::npos))
{
language = Language::BLENDER_GLSL;