Workbench: Cleanups and reduce shader variations
Also optimize deferred engine by only outputing material data if needed. This make the bare flat shading mode (no effects) only a depth prepass.
This commit is contained in:
@@ -21,9 +21,11 @@ float bayer_dither_noise() {
|
||||
|
||||
#ifdef WORKBENCH_ENCODE_NORMALS
|
||||
|
||||
#define WB_Normal vec2
|
||||
|
||||
/* From http://aras-p.info/texts/CompactNormalStorage.html
|
||||
* Using Method #4: Spheremap Transform */
|
||||
vec3 workbench_normal_decode(vec2 enc)
|
||||
vec3 workbench_normal_decode(WB_Normal enc)
|
||||
{
|
||||
vec2 fenc = enc.xy * 4.0 - 2.0;
|
||||
float f = dot(fenc, fenc);
|
||||
@@ -36,7 +38,7 @@ vec3 workbench_normal_decode(vec2 enc)
|
||||
|
||||
/* From http://aras-p.info/texts/CompactNormalStorage.html
|
||||
* Using Method #4: Spheremap Transform */
|
||||
vec2 workbench_normal_encode(vec3 n)
|
||||
WB_Normal workbench_normal_encode(vec3 n)
|
||||
{
|
||||
float p = sqrt(n.z * 8.0 + 8.0);
|
||||
n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0);
|
||||
@@ -44,6 +46,7 @@ vec2 workbench_normal_encode(vec3 n)
|
||||
}
|
||||
|
||||
#else
|
||||
#define WB_Normal vec3
|
||||
/* Well just do nothing... */
|
||||
# define workbench_normal_encode(a) (a)
|
||||
# define workbench_normal_decode(a) (a)
|
||||
|
||||
@@ -17,6 +17,8 @@ uniform float lightMultiplier;
|
||||
uniform float shadowShift = 0.1;
|
||||
uniform float shadowFocus = 1.0;
|
||||
|
||||
uniform vec3 materialSingleColor;
|
||||
|
||||
layout(std140) uniform world_block {
|
||||
WorldData world_data;
|
||||
};
|
||||
@@ -26,8 +28,18 @@ void main()
|
||||
ivec2 texel = ivec2(gl_FragCoord.xy);
|
||||
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
|
||||
|
||||
float roughness, metallic;
|
||||
vec3 base_color;
|
||||
|
||||
#ifndef MATDATA_PASS_ENABLED
|
||||
base_color = materialSingleColor;
|
||||
metallic = 0.0;
|
||||
roughness = 0.5;
|
||||
#else
|
||||
vec4 material_data = texelFetch(materialBuffer, texel, 0);
|
||||
vec3 base_color = material_data.rgb;
|
||||
base_color = material_data.rgb;
|
||||
workbench_float_pair_decode(material_data.a, roughness, metallic);
|
||||
#endif
|
||||
|
||||
/* Do we need normals */
|
||||
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
|
||||
@@ -41,9 +53,8 @@ void main()
|
||||
vec3 shaded_color = base_color;
|
||||
|
||||
#elif defined(V3D_LIGHTING_MATCAP)
|
||||
/* When using matcaps, the material_data.a is the backface sign. */
|
||||
float flipped_nor = material_data.a;
|
||||
normal_viewport = (flipped_nor > 0.0) ? normal_viewport : -normal_viewport;
|
||||
/* When using matcaps, the metallic is the backface sign. */
|
||||
normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport;
|
||||
bool flipped = world_data.matcap_orientation != 0;
|
||||
vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
|
||||
vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
|
||||
@@ -52,12 +63,10 @@ void main()
|
||||
#elif defined(V3D_LIGHTING_STUDIO)
|
||||
|
||||
# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
|
||||
float roughness, metallic;
|
||||
workbench_float_pair_decode(material_data.a, roughness, metallic);
|
||||
vec3 specular_color = mix(vec3(0.05), base_color, metallic);
|
||||
vec3 diffuse_color = mix(base_color, vec3(0.0), metallic);
|
||||
# else
|
||||
float roughness = 0.0;
|
||||
roughness = 0.0;
|
||||
vec3 specular_color = vec3(0.0);
|
||||
vec3 diffuse_color = base_color;
|
||||
# endif
|
||||
|
||||
@@ -13,25 +13,23 @@ void main()
|
||||
{
|
||||
ivec2 texel = ivec2(gl_FragCoord.xy);
|
||||
vec2 uv_viewport = gl_FragCoord.xy * invertedViewportSize;
|
||||
uint object_id = texelFetch(objectId, texel, 0).r;
|
||||
|
||||
/* Listing 4 */
|
||||
vec4 trans_accum = texelFetch(transparentAccum, texel, 0);
|
||||
float trans_revealage = trans_accum.a;
|
||||
trans_accum.a = texelFetch(transparentRevealage, texel, 0).r;
|
||||
|
||||
#ifdef V3D_SHADING_OBJECT_OUTLINE
|
||||
float outline = calculate_object_outline(objectId, texel, object_id);
|
||||
#else /* V3D_SHADING_OBJECT_OUTLINE */
|
||||
float outline = 1.0;
|
||||
#endif /* V3D_SHADING_OBJECT_OUTLINE */
|
||||
vec3 bg_color = background_color(world_data, uv_viewport.y);
|
||||
|
||||
/* TODO: Bypass the whole shader if there is no xray pass and no outline pass. */
|
||||
vec3 trans_color = trans_accum.rgb / clamp(trans_accum.a, 1e-4, 5e4);
|
||||
vec3 color = mix(trans_color, bg_color, trans_revealage);
|
||||
|
||||
#ifdef V3D_SHADING_OBJECT_OUTLINE
|
||||
uint object_id = texelFetch(objectId, texel, 0).r;
|
||||
float outline = calculate_object_outline(objectId, texel, object_id);
|
||||
color = mix(world_data.object_outline_color.rgb, color, outline);
|
||||
#endif
|
||||
|
||||
fragColor = vec4(color, 1.0);
|
||||
}
|
||||
|
||||
@@ -4,69 +4,70 @@ uniform vec3 materialDiffuseColor;
|
||||
uniform float materialMetallic;
|
||||
uniform float materialRoughness;
|
||||
|
||||
#ifdef V3D_SHADING_TEXTURE_COLOR
|
||||
uniform sampler2D image;
|
||||
uniform float ImageTransparencyCutoff = 0.1;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
|
||||
in vec3 normal_viewport;
|
||||
#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
|
||||
#endif
|
||||
|
||||
#ifdef V3D_SHADING_TEXTURE_COLOR
|
||||
in vec2 uv_interp;
|
||||
#endif /* V3D_SHADING_TEXTURE_COLOR */
|
||||
#endif
|
||||
|
||||
#ifdef HAIR_SHADER
|
||||
flat in float hair_rand;
|
||||
#endif
|
||||
|
||||
layout(location=0) out uint objectId;
|
||||
layout(location=1) out vec4 materialData;
|
||||
#ifdef MATDATA_PASS_ENABLED
|
||||
layout(location=0) out vec4 materialData;
|
||||
#endif
|
||||
#ifdef OBJECT_ID_PASS_ENABLED
|
||||
layout(location=1) out uint objectId;
|
||||
#endif
|
||||
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
|
||||
# ifdef WORKBENCH_ENCODE_NORMALS
|
||||
layout(location=2) out vec2 normalViewport;
|
||||
# else /* WORKBENCH_ENCODE_NORMALS */
|
||||
layout(location=2) out vec3 normalViewport;
|
||||
# endif /* WORKBENCH_ENCODE_NORMALS */
|
||||
#endif /* NORMAL_VIEWPORT_PASS_ENABLED */
|
||||
layout(location=2) out WB_Normal normalViewport;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
objectId = uint(object_id);
|
||||
#ifdef MATDATA_PASS_ENABLED
|
||||
float metallic, roughness;
|
||||
vec4 color;
|
||||
|
||||
vec4 color_roughness;
|
||||
#ifdef V3D_SHADING_TEXTURE_COLOR
|
||||
color_roughness = texture(image, uv_interp);
|
||||
if (color_roughness.a < ImageTransparencyCutoff) {
|
||||
# ifdef V3D_SHADING_TEXTURE_COLOR
|
||||
color = texture(image, uv_interp);
|
||||
if (color.a < ImageTransparencyCutoff) {
|
||||
discard;
|
||||
}
|
||||
color_roughness.a = materialRoughness;
|
||||
#else
|
||||
color_roughness = vec4(materialDiffuseColor, materialRoughness);
|
||||
#endif /* V3D_SHADING_TEXTURE_COLOR */
|
||||
|
||||
#ifdef HAIR_SHADER
|
||||
float hair_color_variation = hair_rand * 0.1;
|
||||
color_roughness = clamp(color_roughness - hair_color_variation, 0.0, 1.0);
|
||||
#endif
|
||||
|
||||
float metallic;
|
||||
#ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
|
||||
# ifdef HAIR_SHADER
|
||||
metallic = clamp(materialMetallic - hair_color_variation, 0.0, 1.0);
|
||||
# else
|
||||
metallic = materialMetallic;
|
||||
color.rgb = materialDiffuseColor;
|
||||
# endif
|
||||
#elif defined(V3D_LIGHTING_MATCAP)
|
||||
|
||||
# ifdef V3D_LIGHTING_MATCAP
|
||||
/* Encode front facing in metallic channel. */
|
||||
metallic = float(gl_FrontFacing);
|
||||
color_roughness.a = 0.0;
|
||||
#endif
|
||||
roughness = 0.0;
|
||||
# else
|
||||
metallic = materialMetallic;
|
||||
roughness = materialRoughness;
|
||||
# endif
|
||||
|
||||
materialData.rgb = color_roughness.rgb;
|
||||
materialData.a = workbench_float_pair_encode(color_roughness.a, metallic);
|
||||
# ifdef HAIR_SHADER
|
||||
/* Add some variation to the hairs to avoid uniform look. */
|
||||
float hair_variation = hair_rand * 0.1;
|
||||
color = clamp(color - hair_variation, 0.0, 1.0);
|
||||
metallic = clamp(materialMetallic - hair_variation, 0.0, 1.0);
|
||||
roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0);
|
||||
# endif
|
||||
|
||||
materialData.rgb = color.rgb;
|
||||
materialData.a = workbench_float_pair_encode(roughness, metallic);
|
||||
#endif /* MATDATA_PASS_ENABLED */
|
||||
|
||||
#ifdef OBJECT_ID_PASS_ENABLED
|
||||
objectId = uint(object_id);
|
||||
#endif
|
||||
|
||||
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
|
||||
vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
#include "GPU_extensions.h"
|
||||
|
||||
#include "../eevee/eevee_lut.h" /* TODO find somewhere to share blue noise Table */
|
||||
|
||||
@@ -58,8 +59,8 @@
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
struct GPUShader *prepass_sh_cache[MAX_SHADERS];
|
||||
struct GPUShader *composite_sh_cache[MAX_SHADERS];
|
||||
struct GPUShader *prepass_sh_cache[MAX_PREPASS_SHADERS];
|
||||
struct GPUShader *composite_sh_cache[MAX_COMPOSITE_SHADERS];
|
||||
struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS];
|
||||
struct GPUShader *background_sh[2];
|
||||
struct GPUShader *ghost_resolve_sh;
|
||||
@@ -215,64 +216,63 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
|
||||
return *sh;
|
||||
}
|
||||
|
||||
static void ensure_deferred_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair)
|
||||
static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
|
||||
{
|
||||
int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair);
|
||||
if (e_data.prepass_sh_cache[index] == NULL) {
|
||||
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
|
||||
char *composite_frag = workbench_build_composite_frag(wpd);
|
||||
char *prepass_vert = workbench_build_prepass_vert(is_hair);
|
||||
char *prepass_frag = workbench_build_prepass_frag();
|
||||
e_data.prepass_sh_cache[index] = DRW_shader_create(
|
||||
prepass_vert, NULL,
|
||||
prepass_frag, defines);
|
||||
if (!use_textures && !is_hair) {
|
||||
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
|
||||
}
|
||||
MEM_freeN(prepass_vert);
|
||||
MEM_freeN(prepass_frag);
|
||||
MEM_freeN(defines);
|
||||
}
|
||||
return e_data.prepass_sh_cache[index];
|
||||
}
|
||||
|
||||
static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
int index = workbench_material_get_composite_shader_index(wpd);
|
||||
if (e_data.composite_sh_cache[index] == NULL) {
|
||||
char *defines = workbench_material_build_defines(wpd, false, false);
|
||||
char *composite_frag = workbench_build_composite_frag(wpd);
|
||||
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
|
||||
MEM_freeN(composite_frag);
|
||||
MEM_freeN(defines);
|
||||
}
|
||||
return e_data.composite_sh_cache[index];
|
||||
}
|
||||
|
||||
static void ensure_background_shaders(const bool use_outline)
|
||||
static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
if (e_data.background_sh[use_outline] == NULL) {
|
||||
const char *defines = (use_outline) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL;
|
||||
const int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
|
||||
if (e_data.background_sh[index] == NULL) {
|
||||
const char *defines = (index) ? "#define V3D_SHADING_OBJECT_OUTLINE\n" : NULL;
|
||||
char *frag = BLI_string_joinN(
|
||||
datatoc_workbench_data_lib_glsl,
|
||||
datatoc_workbench_common_lib_glsl,
|
||||
datatoc_workbench_background_lib_glsl,
|
||||
datatoc_workbench_object_outline_lib_glsl,
|
||||
datatoc_workbench_deferred_background_frag_glsl);
|
||||
e_data.background_sh[use_outline] = DRW_shader_create_fullscreen(frag, defines);
|
||||
e_data.background_sh[index] = DRW_shader_create_fullscreen(frag, defines);
|
||||
MEM_freeN(frag);
|
||||
}
|
||||
return e_data.background_sh[index];
|
||||
}
|
||||
|
||||
static void select_deferred_shaders(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
const bool use_outline = OBJECT_OUTLINE_ENABLED(wpd);
|
||||
int index_solid = workbench_material_get_shader_index(wpd, false, false);
|
||||
int index_solid_hair = workbench_material_get_shader_index(wpd, false, true);
|
||||
int index_texture = workbench_material_get_shader_index(wpd, true, false);
|
||||
int index_texture_hair = workbench_material_get_shader_index(wpd, true, true);
|
||||
|
||||
ensure_deferred_shaders(wpd, index_solid, false, false);
|
||||
ensure_deferred_shaders(wpd, index_solid_hair, false, true);
|
||||
ensure_deferred_shaders(wpd, index_texture, true, false);
|
||||
ensure_deferred_shaders(wpd, index_texture_hair, true, true);
|
||||
ensure_background_shaders(use_outline);
|
||||
|
||||
wpd->prepass_solid_sh = e_data.prepass_sh_cache[index_solid];
|
||||
wpd->prepass_solid_hair_sh = e_data.prepass_sh_cache[index_solid_hair];
|
||||
wpd->prepass_texture_sh = e_data.prepass_sh_cache[index_texture];
|
||||
wpd->prepass_texture_hair_sh = e_data.prepass_sh_cache[index_texture_hair];
|
||||
wpd->composite_sh = e_data.composite_sh_cache[index_solid];
|
||||
wpd->background_sh = e_data.background_sh[use_outline];
|
||||
wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false);
|
||||
wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true);
|
||||
wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false);
|
||||
wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true);
|
||||
wpd->composite_sh = ensure_deferred_composite_shader(wpd);
|
||||
wpd->background_sh = ensure_background_shader(wpd);
|
||||
}
|
||||
|
||||
|
||||
/* Using Hammersley distribution */
|
||||
static float *create_disk_samples(int num_samples, int num_iterations)
|
||||
{
|
||||
@@ -346,8 +346,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
|
||||
}
|
||||
|
||||
if (!e_data.next_object_id) {
|
||||
memset(e_data.prepass_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
|
||||
memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
|
||||
memset(e_data.prepass_sh_cache, 0, sizeof(e_data.prepass_sh_cache));
|
||||
memset(e_data.composite_sh_cache, 0, sizeof(e_data.composite_sh_cache));
|
||||
e_data.next_object_id = 1;
|
||||
#ifdef DEBUG_SHADOW_VOLUME
|
||||
const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl;
|
||||
@@ -411,9 +411,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
|
||||
e_data.normal_buffer_tx = NULL;
|
||||
e_data.cavity_buffer_tx = NULL;
|
||||
|
||||
e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
|
||||
e_data.composite_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], comp_tex_format, &draw_engine_workbench_solid);
|
||||
|
||||
if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
|
||||
e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
|
||||
}
|
||||
if (OBJECT_ID_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
|
||||
e_data.object_id_tx = DRW_texture_pool_query_2D(size[0], size[1], id_tex_format, &draw_engine_workbench_solid);
|
||||
}
|
||||
@@ -426,8 +428,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
|
||||
|
||||
GPU_framebuffer_ensure_config(&fbl->prepass_fb, {
|
||||
GPU_ATTACHMENT_TEXTURE(dtxl->depth),
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.normal_buffer_tx),
|
||||
});
|
||||
GPU_framebuffer_ensure_config(&fbl->cavity_fb, {
|
||||
@@ -442,6 +444,11 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
|
||||
GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
|
||||
});
|
||||
|
||||
if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) {
|
||||
e_data.color_buffer_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8, &draw_engine_workbench_solid);
|
||||
}
|
||||
|
||||
GPU_framebuffer_ensure_config(&fbl->effect_fb, {
|
||||
GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(e_data.color_buffer_tx),
|
||||
@@ -543,8 +550,10 @@ static void workbench_setup_ghost_framebuffer(WORKBENCH_FramebufferList *fbl)
|
||||
|
||||
void workbench_deferred_engine_free(void)
|
||||
{
|
||||
for (int index = 0; index < MAX_SHADERS; index++) {
|
||||
for (int index = 0; index < MAX_PREPASS_SHADERS; index++) {
|
||||
DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[index]);
|
||||
}
|
||||
for (int index = 0; index < MAX_COMPOSITE_SHADERS; index++) {
|
||||
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
|
||||
}
|
||||
for (int index = 0; index < MAX_CAVITY_SHADERS; ++index) {
|
||||
@@ -571,7 +580,12 @@ void workbench_deferred_engine_free(void)
|
||||
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
|
||||
{
|
||||
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx);
|
||||
if (MATDATA_PASS_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_uniform_vec3(grp, "materialSingleColor", wpd->shading.single_color, 1);
|
||||
}
|
||||
if (OBJECT_OUTLINE_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
|
||||
}
|
||||
@@ -721,7 +735,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
workbench_material_copy(material, &material_template);
|
||||
DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
|
||||
DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1);
|
||||
workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true);
|
||||
workbench_material_shgroup_uniform(wpd, material->shgrp, material, ob, true, true);
|
||||
|
||||
BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material);
|
||||
}
|
||||
@@ -764,7 +778,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
|
||||
shader);
|
||||
DRW_shgroup_stencil_mask(shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
|
||||
DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
|
||||
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true);
|
||||
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
/* *********** STATIC *********** */
|
||||
static struct {
|
||||
struct GPUShader *composite_sh_cache[MAX_SHADERS];
|
||||
struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS];
|
||||
struct GPUShader *composite_sh_cache[2];
|
||||
struct GPUShader *transparent_accum_sh_cache[MAX_ACCUM_SHADERS];
|
||||
struct GPUShader *object_outline_sh;
|
||||
struct GPUShader *object_outline_texture_sh;
|
||||
struct GPUShader *object_outline_hair_sh;
|
||||
@@ -176,7 +176,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
|
||||
}
|
||||
|
||||
workbench_material_shgroup_uniform(wpd, grp, material, ob, false);
|
||||
workbench_material_shgroup_uniform(wpd, grp, material, ob, false, false);
|
||||
material->shgrp = grp;
|
||||
|
||||
/* Depth */
|
||||
@@ -197,16 +197,9 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
return material;
|
||||
}
|
||||
|
||||
static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair)
|
||||
static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
|
||||
{
|
||||
if (e_data.composite_sh_cache[index] == NULL && !use_textures && !is_hair) {
|
||||
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
|
||||
char *composite_frag = workbench_build_forward_composite_frag();
|
||||
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
|
||||
MEM_freeN(composite_frag);
|
||||
MEM_freeN(defines);
|
||||
}
|
||||
|
||||
int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair);
|
||||
if (e_data.transparent_accum_sh_cache[index] == NULL) {
|
||||
char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
|
||||
char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
|
||||
@@ -218,25 +211,29 @@ static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool u
|
||||
MEM_freeN(transparent_accum_frag);
|
||||
MEM_freeN(defines);
|
||||
}
|
||||
return e_data.transparent_accum_sh_cache[index];
|
||||
}
|
||||
|
||||
static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
|
||||
if (e_data.composite_sh_cache[index] == NULL) {
|
||||
char *defines = workbench_material_build_defines(wpd, false, false);
|
||||
char *composite_frag = workbench_build_forward_composite_frag();
|
||||
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
|
||||
MEM_freeN(composite_frag);
|
||||
MEM_freeN(defines);
|
||||
}
|
||||
return e_data.composite_sh_cache[index];
|
||||
}
|
||||
|
||||
static void select_forward_shaders(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
int index_solid = workbench_material_get_shader_index(wpd, false, false);
|
||||
int index_solid_hair = workbench_material_get_shader_index(wpd, false, true);
|
||||
int index_texture = workbench_material_get_shader_index(wpd, true, false);
|
||||
int index_texture_hair = workbench_material_get_shader_index(wpd, true, true);
|
||||
|
||||
ensure_forward_shaders(wpd, index_solid, false, false);
|
||||
ensure_forward_shaders(wpd, index_solid_hair, false, true);
|
||||
ensure_forward_shaders(wpd, index_texture, true, false);
|
||||
ensure_forward_shaders(wpd, index_texture_hair, true, true);
|
||||
|
||||
wpd->composite_sh = e_data.composite_sh_cache[index_solid];
|
||||
wpd->transparent_accum_sh = e_data.transparent_accum_sh_cache[index_solid];
|
||||
wpd->transparent_accum_hair_sh = e_data.transparent_accum_sh_cache[index_solid_hair];
|
||||
wpd->transparent_accum_texture_sh = e_data.transparent_accum_sh_cache[index_texture];
|
||||
wpd->transparent_accum_texture_hair_sh = e_data.transparent_accum_sh_cache[index_texture_hair];
|
||||
wpd->composite_sh = ensure_forward_composite_shaders(wpd);
|
||||
wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false);
|
||||
wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true);
|
||||
wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false);
|
||||
wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true);
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
@@ -264,8 +261,8 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
|
||||
|
||||
if (!e_data.next_object_id) {
|
||||
e_data.next_object_id = 1;
|
||||
memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
|
||||
memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
|
||||
memset(e_data.composite_sh_cache, 0x00, sizeof(e_data.composite_sh_cache));
|
||||
memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(e_data.transparent_accum_sh_cache));
|
||||
|
||||
char *defines = workbench_material_build_defines(wpd, false, false);
|
||||
char *defines_texture = workbench_material_build_defines(wpd, true, false);
|
||||
@@ -391,8 +388,10 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
|
||||
|
||||
void workbench_forward_engine_free()
|
||||
{
|
||||
for (int index = 0; index < MAX_SHADERS; index++) {
|
||||
for (int index = 0; index < 2; index++) {
|
||||
DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
|
||||
}
|
||||
for (int index = 0; index < MAX_ACCUM_SHADERS; index++) {
|
||||
DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]);
|
||||
}
|
||||
DRW_SHADER_FREE_SAFE(e_data.object_outline_sh);
|
||||
@@ -444,7 +443,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
|
||||
psl->transparent_accum_pass,
|
||||
shader);
|
||||
DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
|
||||
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false);
|
||||
workbench_material_shgroup_uniform(wpd, shgrp, material, ob, false, false);
|
||||
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
|
||||
/* Hairs have lots of layer and can rapidly become the most prominent surface.
|
||||
* So lower their alpha artificially. */
|
||||
|
||||
@@ -81,6 +81,12 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
|
||||
if (MATCAP_ENABLED(wpd)) {
|
||||
BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_MATCAP\n");
|
||||
}
|
||||
if (OBJECT_ID_PASS_ENABLED(wpd)) {
|
||||
BLI_dynstr_appendf(ds, "#define OBJECT_ID_PASS_ENABLED\n");
|
||||
}
|
||||
if (MATDATA_PASS_ENABLED(wpd)) {
|
||||
BLI_dynstr_appendf(ds, "#define MATDATA_PASS_ENABLED\n");
|
||||
}
|
||||
if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
|
||||
BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
|
||||
}
|
||||
@@ -127,21 +133,41 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool
|
||||
return result;
|
||||
}
|
||||
|
||||
int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
|
||||
int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
/* NOTE: change MAX_SHADERS accordingly when modifying this function. */
|
||||
/* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */
|
||||
int index = 0;
|
||||
/* 1 bit V3D_SHADING_TEXTURE_COLOR */
|
||||
SET_FLAG_FROM_TEST(index, use_textures, 1 << 0);
|
||||
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
|
||||
int ligh_flag = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.light, ligh_flag << 1);
|
||||
/* 3 bits for flags */
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 3);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 4);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 5);
|
||||
/* 1 bit for hair */
|
||||
SET_FLAG_FROM_TEST(index, is_hair, 1 << 6);
|
||||
index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
|
||||
SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5);
|
||||
return index;
|
||||
}
|
||||
|
||||
int workbench_material_get_prepass_shader_index(
|
||||
WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
|
||||
{
|
||||
/* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */
|
||||
int index = 0;
|
||||
SET_FLAG_FROM_TEST(index, is_hair, 1 << 0);
|
||||
SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1);
|
||||
SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2);
|
||||
SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3);
|
||||
SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4);
|
||||
SET_FLAG_FROM_TEST(index, use_textures, 1 << 5);
|
||||
return index;
|
||||
}
|
||||
|
||||
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
|
||||
{
|
||||
/* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
|
||||
int index = 0;
|
||||
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
|
||||
index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
|
||||
SET_FLAG_FROM_TEST(index, use_textures, 1 << 2);
|
||||
SET_FLAG_FROM_TEST(index, is_hair, 1 << 3);
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -156,8 +182,12 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i
|
||||
|
||||
void workbench_material_shgroup_uniform(
|
||||
WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob,
|
||||
const bool use_metallic)
|
||||
const bool use_metallic, const bool deferred)
|
||||
{
|
||||
if (deferred && !MATDATA_PASS_ENABLED(wpd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) {
|
||||
GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
|
||||
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
|
||||
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
|
||||
#define MAX_SHADERS (1 << 7)
|
||||
#define MAX_COMPOSITE_SHADERS (1 << 6)
|
||||
#define MAX_PREPASS_SHADERS (1 << 6)
|
||||
#define MAX_ACCUM_SHADERS (1 << 4)
|
||||
#define MAX_CAVITY_SHADERS (1 << 3)
|
||||
|
||||
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type & V3D_SHADING_TEXTURE_COLOR)
|
||||
@@ -65,6 +67,7 @@
|
||||
#define SPECULAR_HIGHLIGHT_ENABLED(wpd) (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
|
||||
#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
|
||||
#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
|
||||
#define MATDATA_PASS_ENABLED(wpd) (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd))
|
||||
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) (MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd))
|
||||
#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) (NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) || SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
|
||||
#define NORMAL_ENCODING_ENABLED() (true)
|
||||
@@ -298,10 +301,12 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *i
|
||||
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
|
||||
void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data);
|
||||
uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost);
|
||||
int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
|
||||
int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd);
|
||||
int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
|
||||
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair);
|
||||
void workbench_material_shgroup_uniform(
|
||||
WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob,
|
||||
const bool use_metallic);
|
||||
const bool use_metallic, const bool deferred);
|
||||
void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material);
|
||||
|
||||
/* workbench_studiolight.c */
|
||||
|
||||
Reference in New Issue
Block a user