Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-02-15 19:51:19 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-02-15 19:53:22 +0300
commit48b26d9c2e0f4f4b6b5b7279c5bfc40c3ec77a6f (patch)
tree87ac7bfedae5d3e64c5fcac71a740bb02872ff94 /source/blender/draw
parent430ced76d559d828b6f47c5fbb22530dcc70c257 (diff)
Fix T95697: GPU subdivision ignores custom normals
Similarly to the CPU subdivision, we interpolate custom loop normals from the coarse mesh, and this for the final normals.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc32
-rw-r--r--source/blender/draw/intern/draw_subdivision.h5
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc39
-rw-r--r--source/blender/draw/intern/shaders/common_subdiv_normals_finalize_comp.glsl21
4 files changed, 93 insertions, 4 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index ea05ae799b0..e4c53604370 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -1355,8 +1355,9 @@ void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
drw_subdiv_compute_dispatch(cache, shader, 0, dst_offset, cache->num_subdiv_quads);
- /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. */
- GPU_memory_barrier(GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
+ /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array. Put
+ * a barrier on the shader storage as we may use the result in another compute shader. */
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE | GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
/* Cleanup. */
GPU_shader_unbind();
@@ -1437,6 +1438,28 @@ void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
GPU_shader_unbind();
}
+void draw_subdiv_finalize_custom_normals(const DRWSubdivCache *cache,
+ GPUVertBuf *src_custom_normals,
+ GPUVertBuf *pos_nor)
+{
+ GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_NORMALS_FINALIZE, "#define CUSTOM_NORMALS");
+ GPU_shader_bind(shader);
+
+ GPU_vertbuf_bind_as_ssbo(src_custom_normals, 0);
+ /* outputPosNor is bound at index 2 in the base shader. */
+ GPU_vertbuf_bind_as_ssbo(pos_nor, 2);
+
+ drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_quads);
+
+ /* This generates a vertex buffer, so we need to put a barrier on the vertex attribute array.
+ * We also need it for subsequent compute shaders, so a barrier on the shader storage is also
+ * needed. */
+ GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE | GPU_BARRIER_VERTEX_ATTRIB_ARRAY);
+
+ /* Cleanup. */
+ GPU_shader_unbind();
+}
+
void draw_subdiv_build_tris_buffer(const DRWSubdivCache *cache,
GPUIndexBuf *subdiv_tris,
const int material_count)
@@ -1828,6 +1851,11 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
/* We can only evaluate limit normals if the patches are adaptive. */
draw_cache->do_limit_normals = settings.is_adaptive;
+ draw_cache->use_custom_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
+ (mesh_eval->flag & ME_AUTOSMOOTH) &&
+ CustomData_has_layer(&mesh_eval->ldata,
+ CD_CUSTOMLOOPNORMAL);
+
if (DRW_ibo_requested(mbc->buff.ibo.tris)) {
draw_subdiv_cache_ensure_mat_offsets(draw_cache, mesh_eval, batch_cache->mat_len);
}
diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h
index 65e845c21a4..78313441a70 100644
--- a/source/blender/draw/intern/draw_subdivision.h
+++ b/source/blender/draw/intern/draw_subdivision.h
@@ -67,6 +67,7 @@ typedef struct DRWSubdivCache {
struct Subdiv *subdiv;
bool optimal_display;
bool do_limit_normals;
+ bool use_custom_loop_normals;
/* Coordinates used to evaluate patches for UVs, positions, and normals. */
struct GPUVertBuf *patch_coords;
@@ -186,6 +187,10 @@ void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
struct GPUVertBuf *subdiv_loop_subdiv_vert_index,
struct GPUVertBuf *pos_nor);
+void draw_subdiv_finalize_custom_normals(const DRWSubdivCache *cache,
+ GPUVertBuf *src_custom_normals,
+ GPUVertBuf *pos_nor);
+
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
struct GPUVertBuf *pos_nor,
bool do_limit_normals);
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
index c92cf554fda..ef88a34021e 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -216,6 +216,16 @@ static GPUVertFormat *get_normals_format()
return &format;
}
+static GPUVertFormat *get_custom_normals_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "lnor");
+ }
+ return &format;
+}
+
static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
@@ -223,7 +233,8 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
void *UNUSED(data))
{
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
- const bool do_limit_normals = subdiv_cache->do_limit_normals;
+ const bool do_limit_normals = subdiv_cache->do_limit_normals &&
+ !subdiv_cache->use_custom_loop_normals;
/* Initialize the vertex buffer, it was already allocated. */
GPU_vertbuf_init_build_on_device(
@@ -231,7 +242,31 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
draw_subdiv_extract_pos_nor(subdiv_cache, vbo, do_limit_normals);
- if (!do_limit_normals) {
+ if (subdiv_cache->use_custom_loop_normals) {
+ Mesh *coarse_mesh = subdiv_cache->mesh;
+ float(*lnors)[3] = static_cast<float(*)[3]>(
+ CustomData_get_layer(&coarse_mesh->ldata, CD_NORMAL));
+ BLI_assert(lnors != NULL);
+
+ GPUVertBuf *src_custom_normals = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_with_format(src_custom_normals, get_custom_normals_format());
+ GPU_vertbuf_data_alloc(src_custom_normals, coarse_mesh->totloop);
+
+ memcpy(
+ GPU_vertbuf_get_data(src_custom_normals), lnors, sizeof(float[3]) * coarse_mesh->totloop);
+
+ GPUVertBuf *dst_custom_normals = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_build_on_device(
+ dst_custom_normals, get_custom_normals_format(), subdiv_cache->num_subdiv_loops);
+
+ draw_subdiv_interp_custom_data(subdiv_cache, src_custom_normals, dst_custom_normals, 3, 0);
+
+ draw_subdiv_finalize_custom_normals(subdiv_cache, dst_custom_normals, vbo);
+
+ GPU_vertbuf_discard(src_custom_normals);
+ GPU_vertbuf_discard(dst_custom_normals);
+ }
+ else if (!do_limit_normals) {
/* We cannot evaluate vertex normals using the limit surface, so compute them manually. */
GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
diff --git a/source/blender/draw/intern/shaders/common_subdiv_normals_finalize_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_normals_finalize_comp.glsl
index 84cd65d4161..c2e0e752783 100644
--- a/source/blender/draw/intern/shaders/common_subdiv_normals_finalize_comp.glsl
+++ b/source/blender/draw/intern/shaders/common_subdiv_normals_finalize_comp.glsl
@@ -1,6 +1,18 @@
/* To be compile with common_subdiv_lib.glsl */
+#ifdef CUSTOM_NORMALS
+struct CustomNormal {
+ float x;
+ float y;
+ float z;
+};
+
+layout(std430, binding = 0) readonly buffer inputNormals
+{
+ CustomNormal custom_normals[];
+};
+#else
layout(std430, binding = 0) readonly buffer inputNormals
{
vec3 vertex_normals[];
@@ -10,6 +22,7 @@ layout(std430, binding = 1) readonly buffer inputSubdivVertLoopMap
{
uint vert_loop_map[];
};
+#endif
layout(std430, binding = 2) buffer outputPosNor
{
@@ -26,9 +39,17 @@ void main()
uint start_loop_index = quad_index * 4;
+#ifdef CUSTOM_NORMALS
+ for (int i = 0; i < 4; i++) {
+ CustomNormal custom_normal = custom_normals[start_loop_index + i];
+ vec3 nor = vec3(custom_normal.x, custom_normal.y, custom_normal.z);
+ set_vertex_nor(pos_nor[start_loop_index + i], normalize(nor));
+ }
+#else
for (int i = 0; i < 4; i++) {
uint subdiv_vert_index = vert_loop_map[start_loop_index + i];
vec3 nor = vertex_normals[subdiv_vert_index];
set_vertex_nor(pos_nor[start_loop_index + i], nor);
}
+#endif
}