DRW: support clipping for all lamp types
authorCampbell Barton <ideasman42@gmail.com>
Tue, 29 Jan 2019 08:57:35 +0000 (19:57 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 29 Jan 2019 09:27:28 +0000 (20:27 +1100)
source/blender/draw/intern/draw_builtin_shader.c
source/blender/draw/intern/draw_common.c
source/blender/draw/intern/draw_common.h
source/blender/draw/modes/object_mode.c
source/blender/draw/modes/shaders/common_world_clip_lib.glsl
source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl
source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl

index 0b3fc45f5e70da63a8e3495ec953088bac1b339d..2c3d656da2c9ec990c2de94758eacea7e5ac61e7 100644 (file)
@@ -50,7 +50,11 @@ extern char datatoc_common_world_clip_lib_glsl[];
             GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, \
             GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, \
             GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, \
-            GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED)
+            GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, \
+            GPU_SHADER_3D_GROUNDLINE, \
+            GPU_SHADER_3D_GROUNDPOINT, \
+            GPU_SHADER_DISTANCE_LINES, \
+            GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR)
 
 /* cache of built-in shaders (each is created on first use) */
 static struct {
@@ -70,9 +74,10 @@ static GPUShader *drw_shader_get_builtin_shader_clipped(eGPUBuiltinShader shader
                &shader_code.geom,
                &shader_code.defs);
 
+       /* In rare cases geometry shaders calculate clipping themselves. */
        return DRW_shader_create_from_arrays({
                .vert = (const char *[]){world_clip_lib, shader_code.vert, NULL},
-               .geom = (const char *[]){shader_code.geom, NULL},
+               .geom = (const char *[]){shader_code.geom ? world_clip_lib : NULL, shader_code.geom, NULL},
                .frag = (const char *[]){shader_code.frag, NULL},
                .defs = (const char *[]){world_clip_def, shader_code.defs, NULL}});
 }
index 28bd39e9090bdb6f9ed292910af7cd52fc09b72c..676c401cf44d8cfd56138745f4b9c4e4e4a14ee9 100644 (file)
@@ -358,24 +358,28 @@ DRWShadingGroup *shgroup_dynpoints_uniform_color(
        return grp;
 }
 
-DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, const float color[4])
+DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, const float color[4], eDRW_ShaderSlot shader_slot)
 {
-       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
+       GPUShader *sh = DRW_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE, shader_slot);
 
        DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
        DRW_shgroup_uniform_vec4(grp, "color", color, 1);
-
+       if (shader_slot == DRW_SHADER_SLOT_CLIPPED) {
+               DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+       }
        return grp;
 }
 
-DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, const float color[4])
+DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, const float color[4], eDRW_ShaderSlot shader_slot)
 {
-       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
+       GPUShader *sh = DRW_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT, shader_slot);
 
        DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
        DRW_shgroup_uniform_vec4(grp, "color", color, 1);
        DRW_shgroup_state_enable(grp, DRW_STATE_POINT);
-
+       if (shader_slot == DRW_SHADER_SLOT_CLIPPED) {
+               DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+       }
        return grp;
 }
 
@@ -561,9 +565,9 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct GPUBatch *geom, e
        return grp;
 }
 
-DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct GPUBatch *geom)
+DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot)
 {
-       GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
+       GPUShader *sh_inst = DRW_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES, shader_slot);
        static float point_size = 4.0f;
 
        DRW_shgroup_instance_format(g_formats.instance_distance_lines, {
@@ -575,13 +579,15 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct GPUBatch
 
        DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_distance_lines);
        DRW_shgroup_uniform_float(grp, "size", &point_size, 1);
-
+       if (shader_slot == DRW_SHADER_SLOT_CLIPPED) {
+               DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+       }
        return grp;
 }
 
-DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct GPUBatch *geom)
+DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot)
 {
-       GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
+       GPUShader *sh_inst = DRW_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, shader_slot);
        static const int True = true;
        static const int False = false;
 
@@ -594,7 +600,9 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct GPUBatch *geom)
        DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
        DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
        DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
-
+       if (shader_slot == DRW_SHADER_SLOT_CLIPPED) {
+               DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+       }
        return grp;
 }
 
index 39a895632bdf3c78ef1961670d642e0e8ee7e433..dffe4f2ebc9a32e816981768dd3d05909fbe0f2c 100644 (file)
@@ -143,8 +143,8 @@ void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp, cons
 struct DRWShadingGroup *shgroup_dynlines_flat_color(struct DRWPass *pass);
 struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pass, const float color[4]);
 struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, const float color[4], const float *size, eDRW_ShaderSlot shader_slot);
-struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, const float color[4]);
-struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, const float color[4]);
+struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, const float color[4], eDRW_ShaderSlot shader_slot);
+struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, const float color[4], eDRW_ShaderSlot shader_slot);
 struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct GPUBatch *geom, const float *size, eDRW_ShaderSlot shader_slot);
 struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct GPUBatch *geom);
 struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct GPUBatch *geom);
@@ -155,8 +155,8 @@ struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct GPUBatch *
 struct DRWShadingGroup *shgroup_instance_alpha(struct DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot);
 struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass, struct GPUBatch *geom, int *baseid);
 struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot);
-struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct GPUBatch *geom);
-struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot);
+struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct GPUBatch *geom, eDRW_ShaderSlot shader_slot);
 struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass);
 struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass);
 struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass);
index ed047b93f9f235eff7272269b6fa5ed30bae4c88..a64d7f288ca3888e8c9b35ddddc4dd33724de072 100644 (file)
@@ -1252,12 +1252,12 @@ static void OBJECT_cache_init(void *vedata)
                sgl->camera_focus = shgroup_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_single_line_get();
-               sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom);
-               sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom);
+               sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
+               sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_single_line_endpoints_get();
-               sgl->camera_clip_points = shgroup_distance_lines_instance(sgl->non_meshes, geom);
-               sgl->camera_mist_points = shgroup_distance_lines_instance(sgl->non_meshes, geom);
+               sgl->camera_clip_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
+               sgl->camera_mist_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_quad_get();
                sgl->camera_stereo_plane = shgroup_instance_alpha(sgl->non_meshes, geom, draw_ctx->shader_slot);
@@ -1310,7 +1310,7 @@ static void OBJECT_cache_init(void *vedata)
 
                /* start with buflimit because we don't want stipples */
                geom = DRW_cache_single_line_get();
-               sgl->lamp_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom);
+               sgl->lamp_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                sgl->lamp_center = shgroup_dynpoints_uniform_color(sgl->non_meshes, gb->colorLampNoAlpha, &gb->sizeLampCenter, draw_ctx->shader_slot);
 
@@ -1322,8 +1322,8 @@ static void OBJECT_cache_init(void *vedata)
                geom = DRW_cache_lamp_sunrays_get();
                sgl->lamp_sunrays = shgroup_instance_screenspace(sgl->non_meshes, geom, &gb->sizeLampCircle, draw_ctx->shader_slot);
 
-               sgl->lamp_groundline = shgroup_groundlines_uniform_color(sgl->non_meshes, gb->colorLamp);
-               sgl->lamp_groundpoint = shgroup_groundpoints_uniform_color(sgl->non_meshes, gb->colorLamp);
+               sgl->lamp_groundline = shgroup_groundlines_uniform_color(sgl->non_meshes, gb->colorLamp, draw_ctx->shader_slot);
+               sgl->lamp_groundpoint = shgroup_groundpoints_uniform_color(sgl->non_meshes, gb->colorLamp, draw_ctx->shader_slot);
 
                geom = DRW_cache_screenspace_circle_get();
                sgl->lamp_area_sphere = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->shader_slot);
@@ -1338,13 +1338,13 @@ static void OBJECT_cache_init(void *vedata)
                sgl->lamp_hemi = shgroup_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_single_line_get();
-               sgl->lamp_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom);
+               sgl->lamp_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_single_line_endpoints_get();
-               sgl->lamp_buflimit_points = shgroup_distance_lines_instance(sgl->non_meshes, geom);
+               sgl->lamp_buflimit_points = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_lamp_spot_get();
-               sgl->lamp_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom);
+               sgl->lamp_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
 
                geom = DRW_cache_circle_get();
                sgl->lamp_spot_blend = shgroup_instance(sgl->non_meshes, geom, draw_ctx->shader_slot);
index b889780751e0f150f94a8fda967f484513cae895..6964b2a0c39bc9add246c9aa3ca11ccca194b737 100644 (file)
@@ -1,5 +1,5 @@
 #ifdef USE_WORLD_CLIP_PLANES
-#ifdef GPU_VERTEX_SHADER
+#if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER)
 uniform vec4 WorldClipPlanes[6];
 void world_clip_planes_calc_clip_distance(vec3 wpos)
 {
index f16fa21b3428faab69f26f1ad358b356f943a3a1..29bdd03f7e36b54431021f5f086e44f830396453 100644 (file)
@@ -8,9 +8,18 @@ layout(line_strip, max_vertices = 2) out;
 void main()
 {
        vec3 vert = gl_in[0].gl_Position.xyz;
+
        gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0);
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance);
+#endif
        EmitVertex();
+
        gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0);
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_calc_clip_distance(vec3(vert.xy, 0.0));
+#endif
        EmitVertex();
+
        EndPrimitive();
 }
index 55f410eb25d2e3ce0db4c431fb640ce4346a95a3..b08d87cdfa610681fec85a6161cb3f326c2ab10f 100644 (file)
@@ -6,6 +6,11 @@ in vec3 pos;
 
 void main()
 {
-       gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0);
+       vec4 pos_4d = vec4(pos.xy, 0.0, 1.0);
+       gl_Position = ViewProjectionMatrix * pos_4d;
        gl_PointSize = 2.0;
+
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_calc_clip_distance(pos_4d.xyz);
+#endif
 }
index 60793bf56b6f45db72758f3a56cc35ad27f0ae63..4196dbbad0220ac73c2e9c321ca2f3309c49c980 100644 (file)
@@ -1,8 +1,16 @@
+#ifdef USE_WORLD_CLIP_PLANES
+uniform mat4 ModelMatrix;
+#endif
 
 /* Does Nothing */
 in vec3 pos;
 
 void main()
 {
-       gl_Position = vec4(pos, 1.0);
+       vec4 pos_4d = vec4(pos, 1.0);
+       gl_Position = pos_4d;
+
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+#endif
 }
index 432b6cac0492a4b7ffc2941c625c8627ed42e62b..2097b900666411d2d604e3390adab9acd128c47a 100644 (file)
@@ -18,8 +18,13 @@ void main()
 {
        float len = end - start;
        vec3 sta = vec3(0.0, 0.0, -start);
+       vec4 pos_4d = vec4(pos * -len + sta, 1.0);
 
-       gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * -len + sta, 1.0);
+       gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d;
        gl_PointSize = size;
        finalColor = vec4(color, 1.0);
+
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_calc_clip_distance((InstanceModelMatrix * pos_4d).xyz);
+#endif
 }
index e26f419b8cd105f0f9c7a95000186c6e84f7caa6..c19598ea8ab3211abb7f0df38bddc2a646e5adf4 100644 (file)
@@ -28,10 +28,18 @@ flat out vec4 finalColor;
 void emitLine(vec4 color)
 {
        gl_Position = ProjectionMatrix * MV_pos[0];
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance);
+#endif
        EmitVertex();
+
        gl_Position = ProjectionMatrix * MV_pos[1];
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance);
+#endif
        finalColor = color;
        EmitVertex();
+
        EndPrimitive();
 }
 
index 9de50246a40b42f5429b17be397f4ff92cef75d8..3877c63d00a9b7e6e202ed7932a33b2e74b1bbda 100644 (file)
@@ -37,7 +37,8 @@ void main()
 
        mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
 
-       MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+       vec4 pos_4d = vec4(pos, 1.0);
+       MV_pos = ModelViewMatrix * pos_4d;
 
        mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
 
@@ -60,4 +61,8 @@ void main()
                edgeClass = -1.0; // back-facing edge
 
        fCol = color;
+
+#ifdef USE_WORLD_CLIP_PLANES
+       world_clip_planes_calc_clip_distance((InstanceModelMatrix * vec4(pos, 1.0)).xyz);
+#endif
 }