[Bf-blender-cvs] [b171e40d0c5] greasepencil-refactor: GPencil: Refactor: Fix outline depth mixing
Clément Foucault
noreply at git.blender.org
Wed Jan 8 14:59:52 CET 2020
Commit: b171e40d0c541d13ffd10cc833d13edb0190b292
Author: Clément Foucault
Date: Wed Jan 8 14:56:57 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBb171e40d0c541d13ffd10cc833d13edb0190b292
GPencil: Refactor: Fix outline depth mixing
This uses a costly depth reprojection in the fragment shader. This might
get optimized a bit in the future.
Unfortunately it's the only way to get the same accurate depth as what the
gpencil engine outputs.
===================================================================
M source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
M source/blender/draw/engines/overlay/overlay_outline.c
M source/blender/draw/engines/overlay/overlay_shader.c
M source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
===================================================================
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 08319ecd405..b1d851a394f 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -176,12 +176,12 @@ float stroke_round_cap_mask(vec2 p1, vec2 p2, float thickness)
#endif
-#ifdef GPU_VERTEX_SHADER
-
/* TODO UBO */
uniform vec2 sizeViewport;
uniform vec2 sizeViewportInv;
+#ifdef GPU_VERTEX_SHADER
+
/* Per Object */
uniform bool strokeOrder3d;
uniform float thicknessScale;
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 83385239ba7..72755e480f5 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -25,13 +25,66 @@
#include "BKE_global.h"
#include "BKE_gpencil.h"
-// #include "DNA_lightprobe_types.h"
+#include "BKE_object.h"
+
#include "DNA_gpencil_types.h"
#include "UI_resources.h"
#include "overlay_private.h"
+/* Modified copy of gpencil_object_cache_add().
+ * Returns the normal plane in ndc space. */
+static void gpencil_depth_plane(Object *ob, float r_plane[4])
+{
+ /* TODO put that into private data. */
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
+ float *camera_z_axis = viewinv[2];
+ float *camera_pos = viewinv[3];
+
+ /* Find the normal most likely to represent the gpObject. */
+ /* TODO: This does not work quite well if you use
+ * strokes not aligned with the object axes. Maybe we could try to
+ * compute the minimum axis of all strokes. But this would be more
+ * computationaly heavy and should go into the GPData evaluation. */
+ BoundBox *bbox = BKE_object_boundbox_get(ob);
+ /* Convert bbox to matrix */
+ float mat[4][4], size[3], center[3];
+ BKE_boundbox_calc_size_aabb(bbox, size);
+ BKE_boundbox_calc_center_aabb(bbox, center);
+ unit_m4(mat);
+ copy_v3_v3(mat[3], center);
+ /* Avoid division by 0.0 later. */
+ add_v3_fl(size, 1e-8f);
+ rescale_m4(mat, size);
+ /* BBox space to World. */
+ mul_m4_m4m4(mat, ob->obmat, mat);
+ /* BBox center in world space. */
+ copy_v3_v3(center, mat[3]);
+ /* View Vector. */
+ if (DRW_view_is_persp_get(NULL)) {
+ /* BBox center to camera vector. */
+ sub_v3_v3v3(r_plane, camera_pos, mat[3]);
+ }
+ else {
+ copy_v3_v3(r_plane, camera_z_axis);
+ }
+ /* World to BBox space. */
+ invert_m4(mat);
+ /* Normalize the vector in BBox space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ transpose_m4(mat);
+ /* mat is now a "normal" matrix which will transform
+ * BBox space normal to world space. */
+ mul_mat3_m4_v3(mat, r_plane);
+ normalize_v3(r_plane);
+
+ plane_from_point_normal_v3(r_plane, center, r_plane);
+}
+
void OVERLAY_outline_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
@@ -119,6 +172,7 @@ typedef struct iterData {
DRWShadingGroup *stroke_grp;
DRWShadingGroup *fill_grp;
int cfra;
+ float plane[4];
} iterData;
static void gp_layer_cache_populate(bGPDlayer *gpl,
@@ -130,6 +184,7 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
bGPdata *gpd = (bGPdata *)iter->ob->data;
const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
+ const bool is_stroke_order_3d = (gpd->draw_mode == GP_DRAWMODE_3D);
float object_scale = mat4_to_scale(iter->ob->obmat);
/* Negate thickness sign to tag that strokes are in screen space.
@@ -137,12 +192,13 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f);
DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp);
- DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", true);
+ DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", is_stroke_order_3d);
DRW_shgroup_uniform_vec2_copy(grp, "sizeViewportInv", DRW_viewport_invert_size_get());
DRW_shgroup_uniform_vec2_copy(grp, "sizeViewport", DRW_viewport_size_get());
DRW_shgroup_uniform_float_copy(grp, "thicknessScale", object_scale);
DRW_shgroup_uniform_float_copy(grp, "thicknessOffset", (float)gpl->line_change);
DRW_shgroup_uniform_float_copy(grp, "thicknessWorldScale", thickness_scale);
+ DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane);
}
static void gp_stroke_cache_populate(bGPDlayer *UNUSED(gpl),
@@ -199,6 +255,10 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
.cfra = pd->cfra,
};
+ if (gpd->draw_mode == GP_DRAWMODE_2D) {
+ gpencil_depth_plane(ob, iter.plane);
+ }
+
BKE_gpencil_visible_stroke_iter(
ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
}
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 1d906a6fc38..db3611671c5 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -1041,7 +1041,8 @@ GPUShader *OVERLAY_shader_outline_prepass_gpencil(void)
datatoc_gpu_shader_common_obinfos_lib_glsl,
datatoc_outline_prepass_vert_glsl,
NULL},
- .frag = (const char *[]){datatoc_gpencil_common_lib_glsl,
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_gpencil_common_lib_glsl,
datatoc_outline_prepass_frag_glsl,
NULL},
.defs = (const char *[]){sh_cfg->def,
diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
index aadddd1e4da..9b11c02fd99 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_frag.glsl
@@ -1,15 +1,44 @@
+uniform vec4 gpDepthPlane;
+
flat in int objectId;
/* using uint because 16bit uint can contain more ids than int. */
out uint outId;
+vec3 ray_plane_intersection(vec3 ray_ori, vec3 ray_dir, vec4 plane)
+{
+ float d = dot(plane.xyz, ray_dir);
+ vec3 plane_co = plane.xyz * (-plane.w / dot(plane.xyz, plane.xyz));
+ vec3 h = ray_ori - plane_co;
+ float lambda = -dot(plane.xyz, h) / ((abs(d) < 1e-8) ? 1e-8 : d);
+ return ray_ori + ray_dir * lambda;
+}
+
void main()
{
#ifdef USE_GPENCIL
if (stroke_round_cap_mask(strokePt1, strokePt2, strokeThickness) < 0.001) {
discard;
}
+
+ if (depth != -1.0) {
+ /* Stroke order 2D. */
+ bool is_persp = ProjectionMatrix[3][3] == 0.0;
+ vec2 uvs = vec2(gl_FragCoord.xy) * sizeViewportInv;
+ vec3 pos_ndc = vec3(uvs, gl_FragCoord.z) * 2.0 - 1.0;
+ vec4 pos_world = ViewProjectionMatrixInverse * vec4(pos_ndc, 1.0);
+ vec3 pos = pos_world.xyz / pos_world.w;
+
+ vec3 ray_ori = pos;
+ vec3 ray_dir = (is_persp) ? (ViewMatrixInverse[3].xyz - pos) : ViewMatrixInverse[2].xyz;
+ vec3 isect = ray_plane_intersection(ray_ori, ray_dir, gpDepthPlane);
+ vec4 ndc = point_world_to_ndc(isect);
+ gl_FragDepth = (ndc.z / ndc.w) * 0.5 + 0.5;
+ }
+ else {
+ gl_FragDepth = gl_FragCoord.z;
+ }
#endif
outId = uint(objectId);
More information about the Bf-blender-cvs
mailing list