[Bf-blender-cvs] [687f09a8ad5] blender2.8: Workbench: Optimize Shadows.

Clément Foucault noreply at git.blender.org
Sun May 20 19:20:10 CEST 2018


Commit: 687f09a8ad508b0f736b35337e589935296ecd0f
Author: Clément Foucault
Date:   Sat May 19 13:31:44 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB687f09a8ad508b0f736b35337e589935296ecd0f

Workbench: Optimize Shadows.

This makes the shadows ~10 times faster in the general case.

This only create extrusion geometry on the outline edges. Also we increment
or decrement the stencil buffer by 2 for each manifold edge and only by 1
for non manifold. This make the algorithm robust yet less heavy than creating
one prism for each triangles.

===================================================================

M	source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
M	source/blender/draw/engines/workbench/workbench_materials.c
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/draw/intern/draw_cache_impl_mesh.c

===================================================================

diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
index 854cbee571d..a6cadfcfc54 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
@@ -1,51 +1,53 @@
-layout(triangles) in;
-layout(triangle_strip, max_vertices=9) out;
+layout(lines_adjacency) in;
+layout(triangle_strip, max_vertices = 8) out;
 
-uniform mat4 ModelMatrix;
-uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrixInverse;
 
 uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
 
 in VertexData {
-	flat vec4 lightDirectionMS;
-	vec4 frontPosition;
+	vec3 pos;           /* local position */
+	vec4 frontPosition; /* final ndc position */
 	vec4 backPosition;
-} vertexData[];
+} vData[];
 
-vec3 face_normal(vec3 v1, vec3 v2, vec3 v3) {
-	return normalize(cross(v2 - v1, v3 - v1));
-}
 void main()
 {
-	vec4 light_direction = vertexData[0].lightDirectionMS;
-	vec4 v1 = gl_in[0].gl_Position;
-	vec4 v2 = gl_in[1].gl_Position;
-	vec4 v3 = gl_in[2].gl_Position;
-	bool backface = dot(face_normal(v1.xyz, v2.xyz, v3.xyz), light_direction.xyz) > 0.0;
-
-	int index0 = backface?0:2;
-	int index2 = backface?2:0;
-
-	/* back cap */
-	gl_Position = vertexData[index0].backPosition;
-	EmitVertex();
-	gl_Position = vertexData[1].backPosition;
-	EmitVertex();
-	gl_Position = vertexData[index2].backPosition;
-	EmitVertex();
-
-	/* sides */
-	gl_Position = vertexData[index2].frontPosition;
-	EmitVertex();
-	gl_Position = vertexData[index0].backPosition;
-	EmitVertex();
-	gl_Position = vertexData[index0].frontPosition;
-	EmitVertex();
-	gl_Position = vertexData[1].backPosition;
-	EmitVertex();
-	gl_Position = vertexData[1].frontPosition;
-	EmitVertex();
-	gl_Position = vertexData[index2].frontPosition;
-	EmitVertex();
+	/* TODO precompute light_direction */
+	vec3 light_dir = mat3(ModelMatrixInverse) * lightDirection;
+
+	vec3 v10 = vData[0].pos - vData[1].pos;
+	vec3 v12 = vData[2].pos - vData[1].pos;
+	vec3 v13 = vData[3].pos - vData[1].pos;
+	vec3 n1 = cross(v12, v10);
+	vec3 n2 = cross(v13, v12);
+	vec2 facing = vec2(dot(n1, light_dir),
+	                   dot(n2, light_dir));
+	bvec2 backface = greaterThan(facing, vec2(0.0));
+
+	if (backface.x == backface.y) {
+		/* Both faces face the same direction. Not an outline edge. */
+		return;
+	}
+
+	/* Reverse order if backfacing the light. */
+	ivec2 idx = ivec2(1, 2);
+	idx = (backface.x) ? idx.yx : idx.xy;
+
+	/* WATCH: maybe unpredictable in some cases. */
+	bool is_manifold = any(notEqual(vData[0].pos, vData[3].pos));
+
+	gl_Position = vData[idx.x].frontPosition; EmitVertex();
+	gl_Position = vData[idx.y].frontPosition; EmitVertex();
+	gl_Position = vData[idx.x].backPosition; EmitVertex();
+	gl_Position = vData[idx.y].backPosition; EmitVertex();
 	EndPrimitive();
+
+	if (is_manifold) {
+		gl_Position = vData[idx.x].frontPosition; EmitVertex();
+		gl_Position = vData[idx.y].frontPosition; EmitVertex();
+		gl_Position = vData[idx.x].backPosition; EmitVertex();
+		gl_Position = vData[idx.y].backPosition; EmitVertex();
+		EndPrimitive();
+	}
 }
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
index 8ef1a8b589b..8f02ce26626 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
@@ -1,23 +1,24 @@
 #define EPSILON 0.0001
-#define INFINITE 100.0
+#define INFINITE 10000.0
 
 uniform mat4 ModelMatrixInverse;
 uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ViewProjectionMatrix;
 uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
 
-in vec4 pos;
+in vec3 pos;
 
 out VertexData {
-	flat vec4 lightDirectionMS;
-	vec4 frontPosition;
+	vec3 pos;           /* local position */
+	vec4 frontPosition; /* final ndc position */
 	vec4 backPosition;
-} vertexData;
+} vData;
 
 void main()
 {
-	gl_Position = pos;
-	vertexData.lightDirectionMS = normalize(ModelMatrixInverse * vec4(lightDirection, 0.0));
-	vertexData.lightDirectionMS.w = 0.0;
-	vertexData.frontPosition = ModelViewProjectionMatrix * (pos + vertexData.lightDirectionMS * EPSILON);
-	vertexData.backPosition = ModelViewProjectionMatrix * (pos + vertexData.lightDirectionMS * INFINITE);
+	/* TODO precompute light_direction */
+	vec3 light_direction = mat3(ModelMatrixInverse) * lightDirection;
+	vData.pos = pos;
+	vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0);
+	vData.backPosition  = ModelViewProjectionMatrix * vec4(pos + light_direction * INFINITE, 1.0);
 }
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 1dcc8d0ec6d..944572729c1 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -620,10 +620,13 @@ void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob
 		}
 
 		if (SHADOW_ENABLED(wpd) && (ob->display.flag & OB_SHOW_SHADOW) > 0) {
-			struct Gwn_Batch *geom_shadow = DRW_cache_object_surface_get(ob);
+			struct Gwn_Batch *geom_shadow = DRW_cache_object_edge_detection_get(ob);
 			if (geom_shadow) {
 				if (is_sculpt_mode) {
-					DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat);
+					/* Currently unsupported in sculpt mode. We could revert to the slow
+					 * method in this case but i'm not sure if it's a good idea given that
+					 * sculped meshes are heavy to begin with. */
+					// DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat);
 				}
 				else {
 					DRW_shgroup_call_object_add(wpd->shadow_shgrp, geom_shadow, ob);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 96a6a616072..3197ba799be 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -501,6 +501,19 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob)
 	}
 }
 
+/* Returns a buffer texture. */
+Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob)
+{
+	switch (ob->type) {
+		case OB_MESH:
+			return DRW_cache_mesh_edge_detection_get(ob);
+
+		/* TODO, should match 'DRW_cache_object_surface_get' */
+		default:
+			return NULL;
+	}
+}
+
 Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
 {
 	switch (ob->type) {
@@ -2493,6 +2506,14 @@ Gwn_Batch *DRW_cache_mesh_wire_outline_get(Object *ob)
 	return DRW_mesh_batch_cache_get_fancy_edges(me);
 }
 
+Gwn_Batch *DRW_cache_mesh_edge_detection_get(Object *ob)
+{
+	BLI_assert(ob->type == OB_MESH);
+
+	Mesh *me = ob->data;
+	return DRW_mesh_batch_cache_get_edge_detection(me);
+}
+
 Gwn_Batch *DRW_cache_mesh_surface_get(Object *ob)
 {
 	BLI_assert(ob->type == OB_MESH);
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index b9a569b3ace..8bc609ffe1f 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -48,6 +48,7 @@ struct Gwn_Batch *DRW_cache_screenspace_circle_get(void);
 
 /* Common Object */
 struct Gwn_Batch *DRW_cache_object_wire_outline_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_object_edge_detection_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob);
 struct Gwn_Batch **DRW_cache_object_surface_material_get(
         struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
@@ -116,6 +117,7 @@ void DRW_cache_mesh_normals_overlay_get(
         struct Gwn_Batch **r_tris, struct Gwn_Batch **r_ledges, struct Gwn_Batch **r_lverts);
 struct Gwn_Batch *DRW_cache_face_centers_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
+struct Gwn_Batch *DRW_cache_mesh_edge_detection_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_mesh_surface_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_mesh_surface_weights_get(struct Object *ob);
 struct Gwn_Batch *DRW_cache_mesh_surface_vert_colors_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 7f745192f2f..3ca53b92946 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -109,6 +109,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mes
 struct Gwn_Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
 struct Gwn_Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
 struct Gwn_Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
+struct Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me);
 struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
 struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
 struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index a33cd49e776..bc805bfed0d 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -36,6 +36,7 @@
 #include "BLI_math_bits.h"
 #include "BLI_string.h"
 #include "BLI_alloca.h"
+#include "BLI_edgehash.h"
 
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -55,6 +56,9 @@
 #include "GPU_batch.h"
 #include "GPU_draw.h"
 #include "GPU_material.h"
+#include "GPU_texture.h"
+
+#include "DRW_render.h"
 
 #include "draw_cache_impl.h"  /* own include */
 
@@ -1229,6 +1233,8 @@ static bool mesh_render_data_edge_vcos_manifold_pnors(
 			*r_is_manifold = true;
 		}
 		else {
+			*r_pnor1 = eed->l->f->no;
+			*r_pnor2 = eed->l->f->no;
 			*r_is_manifold = false;
 		}
 	}
@@ -1268,12 +1274,27 @@ static bool mesh_render_data_edge_vcos_manifold_pnors(
 
 		*r_vco1 = mvert[medge[edge_index].v1].co;
 		*r_vco2 = mvert[medge[edge_index].v2].co;
+		*r_pnor1 = pnors[eap[edge_index].face_index[0]];
+
+		float nor[3], v1[3], v2[3], r_c

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list