From 1545c37cdb7e8ca485cb9defcca0352a9b8ee3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Thu, 27 Feb 2020 17:58:14 +0100 Subject: Workbench: Refactor: Code reorganization --- source/blender/draw/CMakeLists.txt | 6 + .../workbench/shaders/workbench_common_lib.glsl | 103 ++---------- .../shaders/workbench_composite_frag.glsl | 31 ++++ .../workbench/shaders/workbench_data_lib.glsl | 6 + .../workbench/shaders/workbench_image_lib.glsl | 94 +++++++++++ .../workbench/shaders/workbench_prepass_frag.glsl | 92 ----------- .../shaders/workbench_prepass_hair_vert.glsl | 129 +++++++++++++++ .../workbench/shaders/workbench_prepass_vert.glsl | 140 ++++++----------- .../shaders/workbench_world_light_lib.glsl | 5 +- .../draw/engines/workbench/workbench_data.c | 43 ++++- .../engines/workbench/workbench_effect_cavity.c | 78 +++++++++ .../draw/engines/workbench/workbench_engine.c | 137 +++++++++++++++- .../draw/engines/workbench/workbench_opaque.c | 106 +++++++++++++ .../draw/engines/workbench/workbench_private.h | 25 +++ .../draw/engines/workbench/workbench_shader.c | 174 +++++++++++++++++++++ .../draw/engines/workbench/workbench_shadow.c | 25 +++ .../draw/engines/workbench/workbench_transparent.c | 26 +++ source/blender/draw/intern/DRW_render.h | 2 + source/blender/draw/intern/draw_manager.c | 33 +--- source/blender/draw/intern/draw_manager_texture.c | 7 + 20 files changed, 960 insertions(+), 302 deletions(-) create mode 100644 source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl create mode 100644 source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl create mode 100644 source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl create mode 100644 source/blender/draw/engines/workbench/workbench_effect_cavity.c create mode 100644 source/blender/draw/engines/workbench/workbench_opaque.c create mode 100644 source/blender/draw/engines/workbench/workbench_shader.c create mode 100644 source/blender/draw/engines/workbench/workbench_shadow.c create mode 100644 source/blender/draw/engines/workbench/workbench_transparent.c (limited to 'source') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 6d7b422c4fb..8538defa7f1 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -101,14 +101,19 @@ set(SRC engines/workbench/workbench_data.c engines/workbench/workbench_deferred.c engines/workbench/workbench_effect_aa.c + engines/workbench/workbench_effect_cavity.c engines/workbench/workbench_effect_dof.c engines/workbench/workbench_effect_fxaa.c engines/workbench/workbench_effect_taa.c engines/workbench/workbench_engine.c engines/workbench/workbench_forward.c engines/workbench/workbench_materials.c + engines/workbench/workbench_opaque.c engines/workbench/workbench_render.c + engines/workbench/workbench_shader.c + engines/workbench/workbench_shadow.c engines/workbench/workbench_studiolight.c + engines/workbench/workbench_transparent.c engines/workbench/workbench_volume.c engines/external/external_engine.c engines/gpencil/gpencil_cache_utils.c @@ -246,6 +251,7 @@ data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_cavity_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_cavity_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_deferred_background_frag.glsl SRC) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index c0d7719180b..4af03d8b82e 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -2,21 +2,13 @@ #define EPSILON 0.00001 #define M_PI 3.14159265358979323846 -#define CAVITY_BUFFER_RANGE 4.0 - -/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ -#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) -const vec4 dither_mat4x4[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)), - vec4(P(12.0), P(4.0), P(14.0), P(6.0)), - vec4(P(3.0), P(11.0), P(1.0), P(9.0)), - vec4(P(15.0), P(7.0), P(13.0), P(5.0))); +#ifdef GPU_VERTEX_SHADER +# define IN_OUT out +#else +# define IN_OUT in +#endif -float bayer_dither_noise() -{ - ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4; - ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2; - return dither_mat4x4[tx1.x][tx1.y]; -} +#define CAVITY_BUFFER_RANGE 4.0 #ifdef WORKBENCH_ENCODE_NORMALS @@ -24,7 +16,7 @@ float bayer_dither_noise() /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ -vec3 workbench_normal_decode(WB_Normal enc) +vec3 workbench_normal_decode(vec4 enc) { vec2 fenc = enc.xy * 4.0 - 2.0; float f = dot(fenc, fenc); @@ -37,8 +29,9 @@ vec3 workbench_normal_decode(WB_Normal enc) /* From http://aras-p.info/texts/CompactNormalStorage.html * Using Method #4: Spheremap Transform */ -WB_Normal workbench_normal_encode(vec3 n) +WB_Normal workbench_normal_encode(bool front_face, vec3 n) { + n = normalize(front_face ? n : -n); float p = sqrt(n.z * 8.0 + 8.0); n.xy = clamp(n.xy / p + 0.5, 0.0, 1.0); return n.xy; @@ -47,8 +40,8 @@ WB_Normal 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) +# define workbench_normal_encode(f, a) (a) +# define workbench_normal_decode(a) (a.xyz) #endif /* WORKBENCH_ENCODE_NORMALS */ /* Encoding into the alpha of a RGBA8 UNORM texture. */ @@ -122,8 +115,12 @@ float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat) vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat) { - return (proj_mat[3][3] == 0.0) ? normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz) : - vec3(0.0, 0.0, 1.0); + if (proj_mat[3][3] == 0.0) { + return normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz); + } + else { + return vec3(0.0, 0.0, 1.0); + } } vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped) @@ -139,69 +136,3 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped) } return matcap_uv * 0.496 + 0.5; } - -bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) -{ - vec2 tile_pos = floor(co.xy); - - if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) - return false; - - float tile = 10.0 * tile_pos.y + tile_pos.x; - if (tile >= textureSize(map, 0).x) - return false; - - /* Fetch tile information. */ - float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x; - if (tile_layer < 0.0) - return false; - - vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0); - - co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer); - return true; -} - -vec4 workbench_sample_texture(sampler2D image, - vec2 coord, - bool nearest_sampling, - bool premultiplied) -{ - vec2 tex_size = vec2(textureSize(image, 0).xy); - /* TODO(fclem) We could do the same with sampler objects. - * But this is a quick workaround instead of messing with the GPUTexture itself. */ - vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord; - vec4 color = texture(image, uv); - - /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ - if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { - color.rgb = color.rgb / color.a; - } - - return color; -} - -vec4 workbench_sample_texture_array(sampler2DArray tile_array, - sampler1DArray tile_data, - vec2 coord, - bool nearest_sampling, - bool premultiplied) -{ - vec2 tex_size = vec2(textureSize(tile_array, 0).xy); - - vec3 uv = vec3(coord, 0); - if (!node_tex_tile_lookup(uv, tile_array, tile_data)) - return vec4(1.0, 0.0, 1.0, 1.0); - - /* TODO(fclem) We could do the same with sampler objects. - * But this is a quick workaround instead of messing with the GPUTexture itself. */ - uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy; - vec4 color = texture(tile_array, uv); - - /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ - if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { - color.rgb = color.rgb / color.a; - } - - return color; -} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl new file mode 100644 index 00000000000..effa0a8f4df --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl @@ -0,0 +1,31 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_common_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_world_light_lib.glsl) + +uniform sampler2D materialBuffer; +uniform sampler2D normalBuffer; + +in vec4 uvcoordsvar; + +out vec4 fragColor; + +void main() +{ + vec3 normal = workbench_normal_decode(texture(normalBuffer, uvcoordsvar.st)); + vec4 mat_data = texture(materialBuffer, uvcoordsvar.st); + + vec3 I_vs = view_vector_from_screen_uv(uvcoordsvar.st, world_data.viewvecs, ProjectionMatrix); + + vec3 base_color = mat_data.rgb; + + float roughness, metallic; + workbench_float_pair_decode(mat_data.a, roughness, metallic); + + vec3 specular_color = mix(vec3(0.05), base_color.rgb, metallic); + vec3 diffuse_color = mix(base_color.rgb, vec3(0.0), metallic); + + fragColor.rgb = get_world_lighting(diffuse_color, specular_color, roughness, normal, I_vs); + + fragColor.a = 1.0; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl index 0c984b094d3..008be393509 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -5,6 +5,7 @@ struct LightData { }; struct WorldData { + vec4 viewvecs[3]; vec4 object_outline_color; vec4 shadow_direction_vs; LightData lights[4]; @@ -14,3 +15,8 @@ struct WorldData { float curvature_ridge; float curvature_valley; }; + +layout(std140) uniform world_block +{ + WorldData world_data; +}; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl new file mode 100644 index 00000000000..f014804eecc --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_image_lib.glsl @@ -0,0 +1,94 @@ + +bool node_tex_tile_lookup(inout vec3 co, sampler2DArray ima, sampler1DArray map) +{ + vec2 tile_pos = floor(co.xy); + + if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) + return false; + + float tile = 10.0 * tile_pos.y + tile_pos.x; + if (tile >= textureSize(map, 0).x) + return false; + + /* Fetch tile information. */ + float tile_layer = texelFetch(map, ivec2(tile, 0), 0).x; + if (tile_layer < 0.0) + return false; + + vec4 tile_info = texelFetch(map, ivec2(tile, 1), 0); + + co = vec3(((co.xy - tile_pos) * tile_info.zw) + tile_info.xy, tile_layer); + return true; +} + +vec4 workbench_sample_texture(sampler2D image, + vec2 coord, + bool nearest_sampling, + bool premultiplied) +{ + vec2 tex_size = vec2(textureSize(image, 0).xy); + /* TODO(fclem) We could do the same with sampler objects. + * But this is a quick workaround instead of messing with the GPUTexture itself. */ + vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord; + vec4 color = texture(image, uv); + + /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ + if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { + color.rgb = color.rgb / color.a; + } + + return color; +} + +vec4 workbench_sample_texture_array(sampler2DArray tile_array, + sampler1DArray tile_data, + vec2 coord, + bool nearest_sampling, + bool premultiplied) +{ + vec2 tex_size = vec2(textureSize(tile_array, 0).xy); + + vec3 uv = vec3(coord, 0); + if (!node_tex_tile_lookup(uv, tile_array, tile_data)) + return vec4(1.0, 0.0, 1.0, 1.0); + + /* TODO(fclem) We could do the same with sampler objects. + * But this is a quick workaround instead of messing with the GPUTexture itself. */ + uv.xy = nearest_sampling ? (floor(uv.xy * tex_size) + 0.5) / tex_size : uv.xy; + vec4 color = texture(tile_array, uv); + + /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */ + if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) { + color.rgb = color.rgb / color.a; + } + + return color; +} + +uniform sampler2DArray image_tile_array; +uniform sampler1DArray image_tile_data; +uniform sampler2D image; + +uniform float imageTransparencyCutoff = 0.1; +uniform bool imageNearest; +uniform bool imagePremultiplied; + +vec3 workbench_image_color(vec2 uvs) +{ +#if defined(V3D_SHADING_TEXTURE_COLOR) +# ifdef TEXTURE_IMAGE_ARRAY + vec4 color = workbench_sample_texture_array( + image_tile_array, image_tile_data, uvs, imageNearest, imagePremultiplied); +# else + vec4 color = workbench_sample_texture(image, uvs, imageNearest, imagePremultiplied); +# endif + + if (color.a < ImageTransparencyCutoff) { + discard; + } + + return color.rgb; +#else + return vec3(1.0); +#endif +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 94e41b4bcd4..e69de29bb2d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -1,92 +0,0 @@ - -uniform vec4 materialColorAndMetal; -uniform float materialRoughness; - -#ifdef TEXTURE_IMAGE_ARRAY -uniform sampler2DArray image_tile_array; -uniform sampler1DArray image_tile_data; -#else -uniform sampler2D image; -#endif -uniform float ImageTransparencyCutoff = 0.1; -uniform bool imageNearest; -uniform bool imagePremultiplied; - -#ifdef NORMAL_VIEWPORT_PASS_ENABLED -in vec3 normal_viewport; -#endif - -#ifdef V3D_SHADING_TEXTURE_COLOR -in vec2 uv_interp; -#endif -#ifdef V3D_SHADING_VERTEX_COLOR -in vec3 vertexColor; -#endif - -#ifdef HAIR_SHADER -flat in float hair_rand; -#endif - -#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 -layout(location = 2) out WB_Normal normalViewport; -#endif - -void main() -{ -#ifdef MATDATA_PASS_ENABLED - float metallic, roughness; - vec4 color; - -# if defined(V3D_SHADING_TEXTURE_COLOR) -# ifdef TEXTURE_IMAGE_ARRAY - color = workbench_sample_texture_array( - image_tile_array, image_tile_data, uv_interp, imageNearest, imagePremultiplied); -# else - color = workbench_sample_texture(image, uv_interp, imageNearest, imagePremultiplied); -# endif - if (color.a < ImageTransparencyCutoff) { - discard; - } -# elif defined(V3D_SHADING_VERTEX_COLOR) - color.rgb = vertexColor; -# else - color.rgb = materialColorAndMetal.rgb; -# endif - -# ifdef V3D_LIGHTING_MATCAP - /* Encode front facing in metallic channel. */ - metallic = float(gl_FrontFacing); - roughness = 0.0; -# else - metallic = materialColorAndMetal.a; - roughness = materialRoughness; -# endif - -# 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(materialColorAndMetal.a - 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(resource_id + 1) & 0xFFu; -#endif - -#ifdef NORMAL_VIEWPORT_PASS_ENABLED - vec3 n = (gl_FrontFacing) ? normal_viewport : -normal_viewport; - n = normalize(n); - normalViewport = workbench_normal_encode(n); -#endif -} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl new file mode 100644 index 00000000000..4252c20a551 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl @@ -0,0 +1,129 @@ + +#ifndef HAIR_SHADER +in vec3 pos; +in vec3 nor; +in vec2 au; /* active texture layer */ +# ifdef V3D_SHADING_VERTEX_COLOR +in vec4 ac; /* active color */ +# endif +# define uv au +#else /* HAIR_SHADER */ + +# ifdef V3D_SHADING_TEXTURE_COLOR +uniform samplerBuffer au; /* active texture layer */ +# endif +# ifdef V3D_SHADING_VERTEX_COLOR +uniform samplerBuffer ac; /* active color layer */ +# endif + +flat out float hair_rand; +#endif /* HAIR_SHADER */ + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +out vec3 normal_viewport; +#endif + +#ifdef V3D_SHADING_TEXTURE_COLOR +out vec2 uv_interp; +#endif +#ifdef V3D_SHADING_VERTEX_COLOR +out vec3 vertexColor; +#endif + +#ifdef OBJECT_ID_PASS_ENABLED +RESOURCE_ID_VARYING +#endif + +/* From http://libnoise.sourceforge.net/noisegen/index.html */ +float integer_noise(int n) +{ + n = (n >> 13) ^ n; + int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return (float(nn) / 1073741824.0); +} + +vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand) +{ + /* To "simulate" anisotropic shading, randomize hair normal per strand. */ + vec3 nor = cross(tan, binor); + nor = normalize(mix(nor, -tan, rand * 0.1)); + float cos_theta = (rand * 2.0 - 1.0) * 0.2; + float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); + nor = nor * sin_theta + binor * cos_theta; + return nor; +} + +void main() +{ +#ifdef HAIR_SHADER +# ifdef V3D_SHADING_TEXTURE_COLOR + vec2 uv = hair_get_customdata_vec2(au); +# endif + float time, thick_time, thickness; + vec3 world_pos, tan, binor; + hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), + ModelMatrixInverse, + ViewMatrixInverse[3].xyz, + ViewMatrixInverse[2].xyz, + world_pos, + tan, + binor, + time, + thickness, + thick_time); + + hair_rand = integer_noise(hair_get_strand_id()); + vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand); +#else + vec3 world_pos = point_object_to_world(pos); +#endif + gl_Position = point_world_to_ndc(world_pos); + +#ifdef V3D_SHADING_TEXTURE_COLOR + uv_interp = uv; +#endif + +#ifdef V3D_SHADING_VERTEX_COLOR +# ifndef HAIR_SHADER + vertexColor = ac.rgb; +# else + vertexColor = hair_get_customdata_vec4(ac).rgb; +# endif +#endif + +#ifdef NORMAL_VIEWPORT_PASS_ENABLED +# ifndef HAIR_SHADER + normal_viewport = normal_object_to_view(nor); + normal_viewport = normalize(normal_viewport); +# else + normal_viewport = normal_world_to_view(nor); +# endif +#endif + +#ifdef OBJECT_ID_PASS_ENABLED + PASS_RESOURCE_ID +#endif + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif + +#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(materialColorAndMetal.a - hair_variation, 0.0, 1.0); + roughness = clamp(materialRoughness - hair_variation, 0.0, 1.0); +#endif + +#ifdef V3D_LIGHTING_MATCAP + /* Encode front facing in metallic channel. */ + metallic = float(gl_FrontFacing); + roughness = 0.0; +#else + metallic = materialColorAndMetal.a; + roughness = materialRoughness; +#endif + + workbench_float_pair_encode(roughness, metallic) +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 0a3252f0b9b..c7e74a789ac 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -1,110 +1,74 @@ -#ifndef HAIR_SHADER +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_common_lib.glsl) + +IN_OUT ShaderStageInterface +{ + vec3 normal_interp; + vec3 color_interp; + vec2 uv_interp; + flat float packed_rough_metal; + flat int object_id; +}; + +#ifdef GPU_VERTEX_SHADER + in vec3 pos; in vec3 nor; -in vec2 au; /* active texture layer */ -# ifdef V3D_SHADING_VERTEX_COLOR in vec4 ac; /* active color */ -# endif -# define uv au -#else /* HAIR_SHADER */ +in vec2 au; /* active texture layer */ -# ifdef V3D_SHADING_TEXTURE_COLOR -uniform samplerBuffer au; /* active texture layer */ -# endif -# ifdef V3D_SHADING_VERTEX_COLOR -uniform samplerBuffer ac; /* active color layer */ +void main() +{ + vec3 world_pos = point_object_to_world(pos); + gl_Position = point_world_to_ndc(world_pos); + +# ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); # endif -flat out float hair_rand; -#endif /* HAIR_SHADER */ + uv_interp = au; + color_interp = vec3(0.9); // ac.rgb; -#ifdef NORMAL_VIEWPORT_PASS_ENABLED -out vec3 normal_viewport; -#endif + normal_interp = normalize(normal_object_to_view(nor)); -#ifdef V3D_SHADING_TEXTURE_COLOR -out vec2 uv_interp; -#endif -#ifdef V3D_SHADING_VERTEX_COLOR -out vec3 vertexColor; -#endif + // float metallic = materialColorAndMetal.a; + // float roughness = materialRoughness; -#ifdef OBJECT_ID_PASS_ENABLED -RESOURCE_ID_VARYING -#endif + float metallic = 0.0; + float roughness = 0.0; -/* From http://libnoise.sourceforge.net/noisegen/index.html */ -float integer_noise(int n) -{ - n = (n >> 13) ^ n; - int nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return (float(nn) / 1073741824.0); -} + if (metallic == -1.0) { + /* Matcap Case. */ + packed_rough_metal = -1.0; + } + else { + packed_rough_metal = workbench_float_pair_encode(roughness, metallic); + } -vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand) -{ - /* To "simulate" anisotropic shading, randomize hair normal per strand. */ - vec3 nor = cross(tan, binor); - nor = normalize(mix(nor, -tan, rand * 0.1)); - float cos_theta = (rand * 2.0 - 1.0) * 0.2; - float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta)); - nor = nor * sin_theta + binor * cos_theta; - return nor; + object_id = int((uint(resource_id) + 1u) & 0xFFu); } +#else + +layout(location = 0) out vec4 materialData; +layout(location = 1) out WB_Normal normalData; +layout(location = 2) out uint objectId; + void main() { -#ifdef HAIR_SHADER -# ifdef V3D_SHADING_TEXTURE_COLOR - vec2 uv = hair_get_customdata_vec2(au); -# endif - float time, thick_time, thickness; - vec3 world_pos, tan, binor; - hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), - ModelMatrixInverse, - ViewMatrixInverse[3].xyz, - ViewMatrixInverse[2].xyz, - world_pos, - tan, - binor, - time, - thickness, - thick_time); - - hair_rand = integer_noise(hair_get_strand_id()); - vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand); -#else - vec3 world_pos = point_object_to_world(pos); -#endif - gl_Position = point_world_to_ndc(world_pos); + normalData = workbench_normal_encode(gl_FrontFacing, normal_interp); -#ifdef V3D_SHADING_TEXTURE_COLOR - uv_interp = uv; -#endif + materialData = vec4(color_interp, packed_rough_metal); -#ifdef V3D_SHADING_VERTEX_COLOR -# ifndef HAIR_SHADER - vertexColor = ac.rgb; -# else - vertexColor = hair_get_customdata_vec4(ac).rgb; -# endif -#endif + objectId = uint(object_id); -#ifdef NORMAL_VIEWPORT_PASS_ENABLED -# ifndef HAIR_SHADER - normal_viewport = normal_object_to_view(nor); - normal_viewport = normalize(normal_viewport); -# else - normal_viewport = normal_world_to_view(nor); -# endif -#endif + if (materialData.a == -1.0) { + /* For matcaps, save front facing in alpha channel. */ + materialData.a = float(gl_FrontFacing); + } -#ifdef OBJECT_ID_PASS_ENABLED - PASS_RESOURCE_ID -#endif + // materialData.rgb *= workbench_image_color(uv_interp); +} -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); #endif -} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl index 690ce5d527f..58e8370537a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(workbench_data_lib.glsl) + /* [Drobot2014a] Low Level Optimizations for GCN */ vec4 fast_rcp(vec4 v) { @@ -41,8 +43,7 @@ vec4 wrapped_lighting(vec4 NL, vec4 w) return clamp((NL + w) * denom, 0.0, 1.0); } -vec3 get_world_lighting( - WorldData world_data, vec3 diffuse_color, vec3 specular_color, float roughness, vec3 N, vec3 I) +vec3 get_world_lighting(vec3 diffuse_color, vec3 specular_color, float roughness, vec3 N, vec3 I) { vec3 specular_light = world_data.ambient_color.rgb; vec3 diffuse_light = world_data.ambient_color.rgb; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 056e6a6c364..a2cc2a52b7e 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -102,6 +102,43 @@ static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateDat /* \} */ +static void workbench_viewvecs_update(float r_viewvecs[3][4]) +{ + float invproj[4][4]; + const bool is_persp = DRW_view_is_persp_get(NULL); + DRW_view_winmat_get(NULL, invproj, true); + + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + copy_v4_fl4(r_viewvecs[0], -1.0f, -1.0f, -1.0f, 1.0f); + copy_v4_fl4(r_viewvecs[1], 1.0f, -1.0f, -1.0f, 1.0f); + copy_v4_fl4(r_viewvecs[2], -1.0f, 1.0f, -1.0f, 1.0f); + + /* convert the view vectors to view space */ + for (int i = 0; i < 3; i++) { + mul_m4_v4(invproj, r_viewvecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][3]); + if (is_persp) { + mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][2]); + } + r_viewvecs[i][3] = 1.0; + } + + /* we need to store the differences */ + r_viewvecs[1][0] -= r_viewvecs[0][0]; + r_viewvecs[1][1] = r_viewvecs[2][1] - r_viewvecs[0][1]; + + /* calculate a depth offset as well */ + if (!is_persp) { + float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; + mul_m4_v4(invproj, vec_far); + mul_v3_fl(vec_far, 1.0f / vec_far[3]); + r_viewvecs[1][2] = vec_far[2] - r_viewvecs[0][2]; + } +} + void workbench_clear_color_get(float color[4]) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -130,9 +167,10 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) { const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene = draw_ctx->scene; - wpd->material_hash = BLI_ghash_ptr_new(__func__); - wpd->material_transp_hash = BLI_ghash_ptr_new(__func__); + // wpd->material_hash = BLI_ghash_ptr_new(__func__); + // wpd->material_transp_hash = BLI_ghash_ptr_new(__func__); wpd->preferences = &U; + wpd->sh_cfg = draw_ctx->sh_cfg; View3D *v3d = draw_ctx->v3d; RegionView3D *rv3d = draw_ctx->rv3d; @@ -190,6 +228,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) workbench_world_data_update_shadow_direction_vs(wpd); workbench_world_data_ubo_ensure(scene, wpd); + workbench_viewvecs_update(wpd->world_data.viewvecs); /* Cavity settings */ { diff --git a/source/blender/draw/engines/workbench/workbench_effect_cavity.c b/source/blender/draw/engines/workbench/workbench_effect_cavity.c new file mode 100644 index 00000000000..42652cf4299 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_effect_cavity.c @@ -0,0 +1,78 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "workbench_engine.h" +#include "workbench_private.h" + +#if 0 +{ + + { + /* AO Samples Tex */ + int num_iterations = workbench_taa_calculate_num_iterations(vedata); + + const int ssao_samples_single_iteration = scene->display.matcap_ssao_samples; + const int ssao_samples = MIN2(num_iterations * ssao_samples_single_iteration, 500); + + if (e_data.sampling_ubo && (e_data.cached_sample_num != ssao_samples)) { + DRW_UBO_FREE_SAFE(e_data.sampling_ubo); + DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx); + } + + if (e_data.sampling_ubo == NULL) { + float *samples = create_disk_samples(ssao_samples_single_iteration, num_iterations); + e_data.jitter_tx = create_jitter_texture(ssao_samples); + e_data.sampling_ubo = DRW_uniformbuffer_create(sizeof(float[4]) * ssao_samples, samples); + e_data.cached_sample_num = ssao_samples; + MEM_freeN(samples); + } + } +} + + if (CAVITY_ENABLED(wpd)) { + int state = DRW_STATE_WRITE_COLOR; + GPUShader *shader = workbench_cavity_shader_get(SSAO_ENABLED(wpd), CURVATURE_ENABLED(wpd)); + psl->cavity_pass = DRW_pass_create("Cavity", state); + DRWShadingGroup *grp = DRW_shgroup_create(shader, psl->cavity_pass); + DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &e_data.normal_buffer_tx); + DRW_shgroup_uniform_block(grp, "samples_block", e_data.sampling_ubo); + + if (SSAO_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); + DRW_shgroup_uniform_vec4(grp, "ssao_params", wpd->ssao_params, 1); + DRW_shgroup_uniform_vec4(grp, "ssao_settings", wpd->ssao_settings, 1); + DRW_shgroup_uniform_mat4(grp, "WinMatrix", wpd->winmat); + DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx); + } + + if (CURVATURE_ENABLED(wpd)) { + DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx); + DRW_shgroup_uniform_vec2(grp, "curvature_settings", &wpd->world_data.curvature_ridge, 1); + } + + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); + } +#endif \ No newline at end of file diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 62a192bbb25..68ef7b6ce60 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -19,8 +19,7 @@ /** \file * \ingroup draw_engine * - * Simple engine for drawing color and/or depth. - * When we only need simple flat shaders. + * Optimized engine to draw the working viewport with solid and transparent geometry. */ #include "DRW_render.h" @@ -30,7 +29,137 @@ #define WORKBENCH_ENGINE "BLENDER_WORKBENCH" -/* Note: currently unused, we may want to register so we can see this when debugging the view. */ +static void workbench_engine_init(void *ved) +{ + WORKBENCH_Data *vedata = ved; + WORKBENCH_StorageList *stl = vedata->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + RegionView3D *rv3d = draw_ctx->rv3d; + View3D *v3d = draw_ctx->v3d; + Scene *scene = draw_ctx->scene; + Object *camera; + + workbench_shader_library_ensure(); + + if (v3d && rv3d) { + camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL; + } + else { + camera = scene->camera; + } + + if (!stl->wpd) { + stl->wpd = MEM_callocN(sizeof(*stl->wpd), __func__); + } + + if (!stl->effects) { + stl->effects = MEM_callocN(sizeof(*stl->effects), __func__); + workbench_effect_info_init(stl->effects); + } + + WORKBENCH_PrivateData *wpd = stl->wpd; + workbench_private_data_init(wpd); + + workbench_opaque_engine_init(vedata); + // workbench_volume_engine_init(); + // workbench_fxaa_engine_init(); + // workbench_taa_engine_init(vedata); + // workbench_dof_engine_init(vedata, camera); +} + +static void workbench_cache_init(void *ved) +{ + WORKBENCH_Data *vedata = ved; + + workbench_opaque_cache_init(vedata); + + return; + + // workbench_aa_create_pass(vedata); + // workbench_dof_create_pass(vedata); +} + +static void workbench_cache_populate(void *ved, Object *ob) +{ + WORKBENCH_Data *vedata = ved; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_StorageList *stl = vedata->stl; + WORKBENCH_PrivateData *wpd = stl->wpd; + + if (!DRW_object_is_renderable(ob)) { + return; + } + + // if (ob->type == OB_MESH) { + // workbench_cache_populate_particles(vedata, ob); + // } + + /* TODO volume */ + + // if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { + // return; + // } + + if ((ob->dt < OB_SOLID) && !DRW_state_is_scene_render()) { + return; + } + + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { + struct GPUBatch *geom = DRW_cache_object_surface_get(ob); + + if (geom) { + DRW_shgroup_call(wpd->prepass_shgrp, geom, ob); + } + } +} + +static void workbench_cache_finish(void *ved) +{ +} + +static void workbench_draw_scene(void *ved) +{ + WORKBENCH_Data *vedata = ved; + WORKBENCH_FramebufferList *fbl = vedata->fbl; + WORKBENCH_PassList *psl = vedata->psl; + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + GPU_framebuffer_bind(fbl->prepass_fb); + DRW_draw_pass(psl->prepass_pass); + + GPU_framebuffer_bind(fbl->composite_fb); + GPU_framebuffer_clear_color(fbl->composite_fb, clear_col); + + DRW_draw_pass(psl->composite_pass); +} + +static void workbench_engine_free(void) +{ + workbench_shader_free(); +} + +static void workbench_view_update(void *ved) +{ +} + +static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data); + +DrawEngineType draw_engine_workbench = { + NULL, + NULL, + N_("Workbench"), + &workbench_data_size, + &workbench_engine_init, + &workbench_engine_free, + &workbench_cache_init, + &workbench_cache_populate, + &workbench_cache_finish, + &workbench_draw_scene, + &workbench_view_update, + NULL, + NULL, +}; + RenderEngineType DRW_engine_viewport_workbench_type = { NULL, NULL, @@ -44,7 +173,7 @@ RenderEngineType DRW_engine_viewport_workbench_type = { NULL, NULL, &workbench_render_update_passes, - &draw_engine_workbench_solid, + &draw_engine_workbench, {NULL, NULL, NULL}, }; diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c new file mode 100644 index 00000000000..32260623be8 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_opaque.c @@ -0,0 +1,106 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "GPU_extensions.h" + +#include "workbench_engine.h" +#include "workbench_private.h" + +void workbench_opaque_engine_init(WORKBENCH_Data *data) +{ + WORKBENCH_FramebufferList *fbl = data->fbl; + WORKBENCH_PrivateData *wpd = data->stl->wpd; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const eGPUTextureFormat nor_tex_format = NORMAL_ENCODING_ENABLED() ? GPU_RG16 : GPU_RGBA32F; + const eGPUTextureFormat col_tex_format = workbench_color_texture_format(wpd); + const eGPUTextureFormat id_tex_format = OBJECT_ID_PASS_ENABLED(wpd) ? GPU_R32UI : GPU_R8; + + wpd->composite_buffer_tx = dtxl->color; + + wpd->material_buffer_tx = DRW_texture_pool_query_fullscreen(col_tex_format, + &draw_engine_workbench_solid); + wpd->object_id_tx = DRW_texture_pool_query_fullscreen(id_tex_format, + &draw_engine_workbench_solid); + wpd->normal_buffer_tx = DRW_texture_pool_query_fullscreen(nor_tex_format, + &draw_engine_workbench_solid); + + GPU_framebuffer_ensure_config(&fbl->prepass_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(wpd->material_buffer_tx), + GPU_ATTACHMENT_TEXTURE(wpd->normal_buffer_tx), + GPU_ATTACHMENT_TEXTURE(wpd->object_id_tx), + }); + + GPU_framebuffer_ensure_config(&fbl->composite_fb, + { + GPU_ATTACHMENT_TEXTURE(dtxl->depth), + GPU_ATTACHMENT_TEXTURE(dtxl->color), + }); +} + +void workbench_opaque_cache_init(WORKBENCH_Data *data) +{ + WORKBENCH_PassList *psl = data->psl; + WORKBENCH_PrivateData *wpd = data->stl->wpd; + struct GPUShader *sh; + DRWShadingGroup *grp; + + { + DRWState clip_state = WORLD_CLIPPING_ENABLED(wpd) ? DRW_STATE_CLIP_PLANES : 0; + DRWState cull_state = CULL_BACKFACE_ENABLED(wpd) ? DRW_STATE_CULL_BACK : 0; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + + sh = workbench_shader_opaque_get(wpd); + + DRW_PASS_CREATE(psl->prepass_pass, state | cull_state | clip_state); + wpd->prepass_shgrp = grp = DRW_shgroup_create(sh, psl->prepass_pass); + + // DRW_PASS_CREATE(psl->ghost_prepass_pass, state | cull_state | clip_state); + // grp = DRW_shgroup_create(sh, psl->ghost_prepass_pass); + + // sh = workbench_shader_opaque_hair_get(wpd); + + // DRW_PASS_CREATE(psl->prepass_hair_pass, state | clip_state); + // DRW_PASS_CREATE(psl->ghost_prepass_hair_pass, state | clip_state); + + // grp = DRW_shgroup_create(sh, psl->composite_pass); + // grp = DRW_shgroup_create(sh, psl->ghost_prepass_hair_pass); + } + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER; + + DRW_PASS_CREATE(psl->composite_pass, state); + + sh = workbench_shader_composite_get(wpd); + + grp = DRW_shgroup_create(sh, psl->composite_pass); + DRW_shgroup_stencil_mask(grp, 0x00); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx); + DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } +} diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index faf85e4a7de..87518137f8a 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -125,6 +125,7 @@ typedef struct WORKBENCH_TextureList { typedef struct WORKBENCH_StorageList { struct WORKBENCH_PrivateData *g_data; + struct WORKBENCH_PrivateData *wpd; struct WORKBENCH_EffectInfo *effects; float *dof_ubo_data; } WORKBENCH_StorageList; @@ -181,6 +182,7 @@ typedef struct WORKBENCH_UBO_Light { } WORKBENCH_UBO_Light; typedef struct WORKBENCH_UBO_World { + float viewvecs[3][4]; float object_outline_color[4]; float shadow_direction_vs[4]; WORKBENCH_UBO_Light lights[4]; @@ -243,6 +245,15 @@ typedef struct WORKBENCH_PrivateData { float (*world_clip_planes)[4]; + /* Opaque pipeline */ + struct GPUTexture *object_id_tx; + struct GPUTexture *material_buffer_tx; + struct GPUTexture *composite_buffer_tx; + struct GPUTexture *normal_buffer_tx; + struct GPUTexture *cavity_buffer_tx; + + struct DRWShadingGroup *prepass_shgrp; + /* Volumes */ bool volumes_do; ListBase smoke_domains; @@ -270,6 +281,8 @@ typedef struct WORKBENCH_PrivateData { /* Color Management */ bool use_color_management; bool use_color_render_settings; + + eGPUShaderConfig sh_cfg; } WORKBENCH_PrivateData; /* Transient data */ typedef struct WORKBENCH_EffectInfo { @@ -431,6 +444,18 @@ BLI_INLINE eGPUTextureFormat workbench_color_texture_format(const WORKBENCH_Priv return result; } +/* workbench_opaque.c */ +void workbench_opaque_engine_init(WORKBENCH_Data *data); +void workbench_opaque_cache_init(WORKBENCH_Data *data); + +/* workbench_shader.c */ +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd); +GPUShader *workbench_shader_opaque_hair_get(WORKBENCH_PrivateData *wpd); +GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd); + +void workbench_shader_library_ensure(void); +void workbench_shader_free(void); + /* workbench_deferred.c */ void workbench_deferred_engine_init(WORKBENCH_Data *vedata); void workbench_deferred_engine_free(void); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c new file mode 100644 index 00000000000..378f621f319 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -0,0 +1,174 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "BLI_dynstr.h" + +#include "workbench_engine.h" +#include "workbench_private.h" + +extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + +extern char datatoc_workbench_prepass_vert_glsl[]; +extern char datatoc_workbench_prepass_frag_glsl[]; +// extern char datatoc_workbench_cavity_frag_glsl[]; +// extern char datatoc_workbench_forward_composite_frag_glsl[]; +// extern char datatoc_workbench_deferred_composite_frag_glsl[]; +// extern char datatoc_workbench_deferred_background_frag_glsl[]; +// extern char datatoc_workbench_ghost_resolve_frag_glsl[]; + +extern char datatoc_workbench_composite_frag_glsl[]; + +extern char datatoc_workbench_shadow_vert_glsl[]; +extern char datatoc_workbench_shadow_geom_glsl[]; +extern char datatoc_workbench_shadow_caps_geom_glsl[]; +extern char datatoc_workbench_shadow_debug_frag_glsl[]; + +extern char datatoc_workbench_cavity_lib_glsl[]; +extern char datatoc_workbench_common_lib_glsl[]; +extern char datatoc_workbench_data_lib_glsl[]; +extern char datatoc_workbench_object_outline_lib_glsl[]; +extern char datatoc_workbench_curvature_lib_glsl[]; +extern char datatoc_workbench_world_light_lib_glsl[]; + +extern char datatoc_gpu_shader_depth_only_frag_glsl[]; + +static struct { + struct GPUShader *prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_PREPASS_SHADERS]; + + struct GPUShader *composite_sh[MAX_COMPOSITE_SHADERS]; + struct GPUShader *cavity_sh[MAX_CAVITY_SHADERS]; + struct GPUShader *ghost_resolve_sh; + struct GPUShader *oit_resolve_sh; + + struct GPUShader *shadow_fail_sh[2]; + struct GPUShader *shadow_pass_sh[2]; + struct GPUShader *shadow_caps_sh[2]; + + struct DRWShaderLibrary *lib; +} e_data = {{{NULL}}}; + +void workbench_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + + DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_cavity_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_common_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_data_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_object_outline_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_curvature_lib); + DRW_SHADER_LIB_ADD(e_data.lib, workbench_world_light_lib); + } +} + +static char *workbench_build_defines(WORKBENCH_PrivateData *UNUSED(wpd)) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + + if (NORMAL_ENCODING_ENABLED()) { + BLI_dynstr_append(ds, "#define WORKBENCH_ENCODE_NORMALS\n"); + } + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + return str; +} + +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd) +{ + int index = 0; + if (e_data.prepass_sh_cache[wpd->sh_cfg][index] == NULL) { + char *defines = workbench_build_defines(wpd); + char *sh_src = DRW_shader_library_create_shader_string(e_data.lib, + datatoc_workbench_prepass_vert_glsl); + const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[wpd->sh_cfg]; + + e_data.prepass_sh_cache[wpd->sh_cfg][index] = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg_data->lib, sh_src, NULL}, + .frag = (const char *[]){sh_src, NULL}, + .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, + }); + + MEM_freeN(defines); + MEM_freeN(sh_src); + } + return e_data.prepass_sh_cache[wpd->sh_cfg][index]; +} + +GPUShader *workbench_shader_opaque_hair_get(WORKBENCH_PrivateData *wpd) +{ + // if (e_data.prepass_sh_cache[wpd->sh_cfg][index] == NULL) { + // char *vert = DRW_shader_library_create_shader_string(e_data.lib, char *shader_code); + // char *frag = DRW_shader_library_create_shader_string(e_data.lib, char *shader_code); + // char *defines = ; + + // e_data.prepass_sh_cache[wpd->sh_cfg][index] = GPU_shader_create_from_arrays({ + // .vert = (const char *[]){sh_cfg_data->lib, vert, NULL}, + // .frag = (const char *[]){frag, NULL}, + // .defs = (const char *[]){sh_cfg_data->def, defines, NULL}, + // }); + + // MEM_freeN(vert); + // MEM_freeN(frag); + // MEM_freeN(defines); + // } + // return e_data.prepass_sh_cache[wpd->sh_cfg][index]; + return NULL; +} + +GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd) +{ + int index = 0; + if (e_data.composite_sh[index] == NULL) { + char *defines = workbench_build_defines(wpd); + char *frag = DRW_shader_library_create_shader_string(e_data.lib, + datatoc_workbench_composite_frag_glsl); + + e_data.composite_sh[index] = DRW_shader_create_fullscreen(frag, defines); + + MEM_freeN(defines); + MEM_freeN(frag); + } + return e_data.composite_sh[index]; +} + +void workbench_shader_free(void) +{ + for (int j = 0; j < ARRAY_SIZE(e_data.prepass_sh_cache); j++) { + for (int i = 0; i < MAX_PREPASS_SHADERS; i++) { + DRW_SHADER_FREE_SAFE(e_data.prepass_sh_cache[j][i]); + } + } + + for (int i = 0; i < MAX_COMPOSITE_SHADERS; i++) { + DRW_SHADER_FREE_SAFE(e_data.composite_sh[i]); + } + + DRW_SHADER_LIB_FREE_SAFE(e_data.lib); +} diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c new file mode 100644 index 00000000000..5be863e387d --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -0,0 +1,25 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "workbench_engine.h" \ No newline at end of file diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c new file mode 100644 index 00000000000..1ad3f41ef79 --- /dev/null +++ b/source/blender/draw/engines/workbench/workbench_transparent.c @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_render.h" + +#include "workbench_engine.h" +#include "workbench_private.h" \ No newline at end of file diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 1eb4a903d90..cbd39331680 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -149,6 +149,8 @@ struct GPUTexture *DRW_texture_pool_query_2d(int w, int h, eGPUTextureFormat format, DrawEngineType *engine_type); +struct GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format, + DrawEngineType *engine_type); struct GPUTexture *DRW_texture_create_1d(int w, eGPUTextureFormat format, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 80001144cc0..5fedba246e7 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1118,45 +1118,23 @@ static void use_drw_engine(DrawEngineType *engine) BLI_addtail(&DST.enabled_engines, ld); } -/** - * Use for external render engines. - */ -static void drw_engines_enable_external(void) -{ - use_drw_engine(DRW_engine_viewport_external_type.draw_engine); -} - -/* TODO revisit this when proper layering is implemented */ /* Gather all draw engines needed and store them in DST.enabled_engines * That also define the rendering order of engines */ -static void drw_engines_enable_from_engine(RenderEngineType *engine_type, - int drawtype, - bool use_xray) +static void drw_engines_enable_from_engine(RenderEngineType *engine_type, int drawtype) { switch (drawtype) { case OB_WIRE: - use_drw_engine(&draw_engine_workbench_transparent); - break; - case OB_SOLID: - if (use_xray) { - use_drw_engine(&draw_engine_workbench_transparent); - } - else { - use_drw_engine(&draw_engine_workbench_solid); - } + use_drw_engine(DRW_engine_viewport_workbench_type.draw_engine); break; - case OB_MATERIAL: case OB_RENDER: default: - /* TODO layers */ if (engine_type->draw_engine != NULL) { use_drw_engine(engine_type->draw_engine); } - - if ((engine_type->flag & RE_INTERNAL) == 0) { - drw_engines_enable_external(); + else if ((engine_type->flag & RE_INTERNAL) == 0) { + use_drw_engine(DRW_engine_viewport_external_type.draw_engine); } break; } @@ -1180,9 +1158,8 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer), { View3D *v3d = DST.draw_ctx.v3d; const int drawtype = v3d->shading.type; - const bool use_xray = XRAY_ENABLED(v3d); - drw_engines_enable_from_engine(engine_type, drawtype, use_xray); + drw_engines_enable_from_engine(engine_type, drawtype); if (gpencil_engine_needed) { use_drw_engine(&draw_engine_gpencil_type); } diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 373810b2f7f..c75299158a3 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -134,6 +134,13 @@ GPUTexture *DRW_texture_pool_query_2d(int w, return tex; } +GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format, + DrawEngineType *engine_type) +{ + const float *size = DRW_viewport_size_get(); + return DRW_texture_pool_query_2d((int)size[0], (int)size[1], format, engine_type); +} + void DRW_texture_ensure_fullscreen_2d(GPUTexture **tex, eGPUTextureFormat format, DRWTextureFlag flags) -- cgit v1.2.3