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:
authorClément Foucault <foucault.clem@gmail.com>2022-10-21 14:09:07 +0300
committerClément Foucault <foucault.clem@gmail.com>2022-10-24 12:21:17 +0300
commit0ee9282b5c51066dfcf5a6c7a5ebcd3dd5290673 (patch)
tree4e02590a5b3148e626e9187e8ba88313d581789c
parentb27c831e0cdcbd5e9792a8311e53ca31654a1d9f (diff)
GPencil: Use indexed rendering instead of instances
This allows using instancing in other ways, like resources indexing.
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_sync.cc4
-rw-r--r--source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl36
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c31
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_shared.h3
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl595
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl21
-rw-r--r--source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh8
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.cc22
-rw-r--r--source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl15
-rw-r--r--source/blender/draw/intern/draw_cache.h11
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.cc189
-rw-r--r--source/blender/draw/intern/draw_manager_data.cc6
-rw-r--r--source/blender/draw/intern/shaders/common_gpencil_lib.glsl88
-rw-r--r--source/blender/draw/intern/shaders/draw_view_info.hh17
-rw-r--r--source/blender/gpu/intern/gpu_texture_private.hh2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.cc8
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h10
17 files changed, 228 insertions, 838 deletions
diff --git a/source/blender/draw/engines/eevee_next/eevee_sync.cc b/source/blender/draw/engines/eevee_next/eevee_sync.cc
index 08cda6f47cf..0915dace1e5 100644
--- a/source/blender/draw/engines/eevee_next/eevee_sync.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_sync.cc
@@ -248,15 +248,15 @@ static void gpencil_stroke_sync(bGPDlayer * /*gpl*/,
return;
}
+ GPUBatch *geom = DRW_cache_gpencil_get(iter.ob, iter.cfra);
+
if (show_fill) {
- GPUBatch *geom = DRW_cache_gpencil_fills_get(iter.ob, iter.cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
gpencil_drawcall_add(iter, geom, material, vfirst, vcount, false);
}
if (show_stroke) {
- GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter.ob, iter.cfra);
/* Start one vert before to have gl_InstanceID > 0 (see shader). */
int vfirst = gps->runtime.stroke_start - 1;
/* Include "potential" cyclic vertex and start adj vertex (see shader). */
diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
index 38debf14eda..87a5bf71c45 100644
--- a/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
+++ b/source/blender/draw/engines/eevee_next/shaders/eevee_geom_gpencil_vert.glsl
@@ -16,30 +16,18 @@ void main()
float hardness;
vec2 thickness;
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- /* TODO */
- vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0),
- interp.P,
- interp.N,
- g_color,
- strength,
- g_uvs,
- sspos,
- aspect,
- thickness,
- hardness);
+ gl_Position = gpencil_vertex(
+ /* TODO */
+ vec4(1024.0, 1024.0, 1.0 / 1024.0, 1.0 / 1024.0),
+ interp.P,
+ interp.N,
+ g_color,
+ strength,
+ g_uvs,
+ sspos,
+ aspect,
+ thickness,
+ hardness);
#ifdef MAT_VELOCITY
/* GPencil do not support deformation motion blur. */
vec3 lP_curr = transform_point(ModelMatrixInverse, interp.P);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index b24e4c605e4..956830e6b4c 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -346,7 +346,7 @@ typedef struct gpIterPopulateData {
int vfirst, vcount;
} gpIterPopulateData;
-#define DISABLE_BATCHING 0
+#define DISABLE_BATCHING 1
static void gpencil_drawcall_flush(gpIterPopulateData *iter)
{
@@ -377,6 +377,7 @@ static void gpencil_drawcall_add(
else {
DRW_shgroup_call_range(iter->grp, iter->ob, geom, v_first, v_count);
}
+ return;
#endif
int last = iter->vfirst + iter->vcount;
@@ -516,22 +517,32 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl,
bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW);
+ GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_get(iter->ob) :
+ DRW_cache_gpencil_get(iter->ob, iter->pd->cfra);
+ if (geom != iter->geom) {
+ gpencil_drawcall_flush(iter);
+
+ GPUVertBuf *position_tx = do_sbuffer ?
+ DRW_cache_gpencil_sbuffer_position_buffer_get(iter->ob) :
+ DRW_cache_gpencil_position_buffer_get(iter->ob, iter->pd->cfra);
+ GPUVertBuf *color_tx = do_sbuffer ?
+ DRW_cache_gpencil_sbuffer_color_buffer_get(iter->ob) :
+ DRW_cache_gpencil_color_buffer_get(iter->ob, iter->pd->cfra);
+ DRW_shgroup_buffer_texture(iter->grp, "gp_pos_tx", position_tx);
+ DRW_shgroup_buffer_texture(iter->grp, "gp_col_tx", color_tx);
+ }
+
if (show_fill) {
- GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_fill_get(iter->ob) :
- DRW_cache_gpencil_fills_get(iter->ob, iter->pd->cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
gpencil_drawcall_add(iter, geom, false, vfirst, vcount);
}
if (show_stroke) {
- GPUBatch *geom = do_sbuffer ? DRW_cache_gpencil_sbuffer_stroke_get(iter->ob) :
- DRW_cache_gpencil_strokes_get(iter->ob, iter->pd->cfra);
- /* Start one vert before to have gl_InstanceID > 0 (see shader). */
- int vfirst = gps->runtime.stroke_start - 1;
- /* Include "potential" cyclic vertex and start adj vertex (see shader). */
- int vcount = gps->totpoints + 1 + 1;
- gpencil_drawcall_add(iter, geom, true, vfirst, vcount);
+ int vfirst = gps->runtime.stroke_start * 3;
+ /* Include "potential" cyclic vertex (see shader). */
+ int vcount = (gps->totpoints + 1) * 2 * 3;
+ gpencil_drawcall_add(iter, geom, false, vfirst, vcount);
}
iter->stroke_index_last = gps->runtime.stroke_start + gps->totpoints + 1;
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
index 4c621e955b9..3f0f73e7c13 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_shared.h
@@ -41,6 +41,9 @@ enum gpLightType {
GP_LIGHT_TYPE_AMBIENT = 3u,
};
+#define GP_IS_STROKE_VERTEX_BIT (1 << 30)
+#define GP_VERTEX_ID_SHIFT 2
+
/* Avoid compiler funkiness with enum types not being strongly typed in C. */
#ifndef GPU_SHADER
# define gpMaterialFlag uint
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 7ddfdc5f65c..642939136c8 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -1,92 +1,4 @@
-/* Must match C declaration. */
-struct gpMaterial {
- vec4 stroke_color;
- vec4 fill_color;
- vec4 fill_mix_color;
- vec4 fill_uv_rot_scale;
- vec4 fill_uv_offset;
- /* Put float/int at the end to avoid padding error */
- /* Some drivers are completely messing the alignment or the fetches here.
- * We are forced to pack these into vec4 otherwise we only get 0.0 as value. */
- vec4 gp_mat_packed_1;
- // float stroke_texture_mix;
- // float stroke_u_scale;
- // float fill_texture_mix;
- // int gp_flag;
- /* Please ensure 16 byte alignment (multiple of vec4). */
-};
-
-#define MATERIAL(m) materials[m + gpMaterialOffset]
-
-#define stroke_texture_mix gp_mat_packed_1.x
-#define stroke_u_scale gp_mat_packed_1.y
-#define fill_texture_mix gp_mat_packed_1.z
-#define GP_FLAG(m) floatBitsToInt(MATERIAL(m).gp_mat_packed_1.w)
-
-/* flag */
-#define GP_STROKE_ALIGNMENT_STROKE 1
-#define GP_STROKE_ALIGNMENT_OBJECT 2
-#define GP_STROKE_ALIGNMENT_FIXED 3
-#define GP_STROKE_ALIGNMENT 0x3
-#define GP_STROKE_OVERLAP (1 << 2)
-#define GP_STROKE_TEXTURE_USE (1 << 3)
-#define GP_STROKE_TEXTURE_STENCIL (1 << 4)
-#define GP_STROKE_TEXTURE_PREMUL (1 << 5)
-#define GP_STROKE_DOTS (1 << 6)
-#define GP_STROKE_HOLDOUT (1 << 7)
-#define GP_FILL_HOLDOUT (1 << 8)
-#define GP_FILL_TEXTURE_USE (1 << 10)
-#define GP_FILL_TEXTURE_PREMUL (1 << 11)
-#define GP_FILL_TEXTURE_CLIP (1 << 12)
-#define GP_FILL_GRADIENT_USE (1 << 13)
-#define GP_FILL_GRADIENT_RADIAL (1 << 14)
-/* High bits are used to pass material ID to fragment shader. */
-#define GP_MATID_SHIFT 16
-
-/* Multiline defines can crash blender with certain GPU drivers. */
-/* clang-format off */
-#define GP_FILL_FLAGS (GP_FILL_TEXTURE_USE | GP_FILL_TEXTURE_PREMUL | GP_FILL_TEXTURE_CLIP | GP_FILL_GRADIENT_USE | GP_FILL_GRADIENT_RADIAL | GP_FILL_HOLDOUT)
-/* clang-format on */
-
-#define GP_FLAG_TEST(flag, val) (((flag) & (val)) != 0)
-
-/* Must match C declaration. */
-struct gpLight {
- vec4 color_type;
- vec4 right;
- vec4 up;
- vec4 forward;
- vec4 position;
- /* Please ensure 16 byte alignment (multiple of vec4). */
-};
-
-#define spot_size right.w
-#define spot_blend up.w
-
-#define GP_LIGHT_TYPE_POINT 0.0
-#define GP_LIGHT_TYPE_SPOT 1.0
-#define GP_LIGHT_TYPE_SUN 2.0
-#define GP_LIGHT_TYPE_AMBIENT 3.0
-
-#ifdef GP_MATERIAL_BUFFER_LEN
-
-layout(std140) uniform gpMaterialBlock
-{
- gpMaterial materials[GP_MATERIAL_BUFFER_LEN];
-};
-
-#endif
-
-#ifdef GPENCIL_LIGHT_BUFFER_LEN
-
-layout(std140) uniform gpLightBlock
-{
- gpLight lights[GPENCIL_LIGHT_BUFFER_LEN];
-};
-
-#endif
-
/* Must match eGPLayerBlendModes */
#define MODE_REGULAR 0
#define MODE_HARDLIGHT 1
@@ -149,510 +61,3 @@ void blend_mode_output(
break;
}
}
-
-#ifndef USE_GPU_SHADER_CREATE_INFO
-
-IN_OUT ShaderStageInterface
-{
- vec4 finalColorMul;
- vec4 finalColorAdd;
- vec3 finalPos;
- vec2 finalUvs;
- noperspective float strokeThickness;
- noperspective float unclampedThickness;
- noperspective float strokeHardeness;
- flat vec2 strokeAspect;
- flat vec2 strokePt1;
- flat vec2 strokePt2;
- flat int matFlag;
- flat float depth;
-};
-
-#endif
-
-#ifdef GPU_FRAGMENT_SHADER
-
-# define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
-
-float stroke_round_cap_mask(vec2 p1, vec2 p2, vec2 aspect, float thickness, float hardfac)
-{
- /* We create our own uv space to avoid issues with triangulation and linear
- * interpolation artifacts. */
- vec2 line = p2.xy - p1.xy;
- vec2 pos = gl_FragCoord.xy - p1.xy;
- float line_len = length(line);
- float half_line_len = line_len * 0.5;
- /* Normalize */
- line = (line_len > 0.0) ? (line / line_len) : vec2(1.0, 0.0);
- /* Create a uv space that englobe the whole segment into a capsule. */
- vec2 uv_end;
- uv_end.x = max(abs(dot(line, pos) - half_line_len) - half_line_len, 0.0);
- uv_end.y = dot(vec2(-line.y, line.x), pos);
- /* Divide by stroke radius. */
- uv_end /= thickness;
- uv_end *= aspect;
-
- float dist = clamp(1.0 - length(uv_end) * 2.0, 0.0, 1.0);
- if (hardfac > 0.999) {
- return step(1e-8, dist);
- }
- else {
- /* Modulate the falloff profile */
- float hardness = 1.0 - hardfac;
- dist = pow(dist, mix(0.01, 10.0, hardness));
- return smoothstep(0.0, 1.0, dist);
- }
-}
-
-#endif
-
-uniform vec2 sizeViewport;
-uniform vec2 sizeViewportInv;
-
-/* Per Object */
-uniform bool strokeOrder3d;
-uniform int gpMaterialOffset;
-uniform float thicknessScale;
-uniform float thicknessWorldScale;
-#define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
-
-#ifdef GPU_VERTEX_SHADER
-
-/* Per Layer */
-uniform float thicknessOffset;
-uniform float vertexColorOpacity;
-uniform vec4 layerTint;
-uniform float layerOpacity; /* Used for onion skin. */
-uniform float strokeIndexOffset = 0.0;
-
-/* All of these attributes are quad loaded the same way
- * as GL_LINES_ADJACENCY would feed a geometry shader:
- * - ma reference the previous adjacency point.
- * - ma1 reference the current line first point.
- * - ma2 reference the current line second point.
- * - ma3 reference the next adjacency point.
- * Note that we are rendering quad instances and not using any index buffer (except for fills).
- */
-/* x is material index, y is stroke_id, z is point_id, w is aspect & rotation & hardness packed. */
-in ivec4 ma;
-in ivec4 ma1;
-in ivec4 ma2;
-in ivec4 ma3;
-/* Position contains thickness in 4th component. */
-in vec4 pos; /* Prev adj vert */
-in vec4 pos1; /* Current edge */
-in vec4 pos2; /* Current edge */
-in vec4 pos3; /* Next adj vert */
-/* xy is UV for fills, z is U of stroke, w is strength. */
-in vec4 uv1;
-in vec4 uv2;
-in vec4 col1;
-in vec4 col2;
-in vec4 fcol1;
-/* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation
- * considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536) */
-# define stroke_id1 ma1.y
-# define point_id1 ma1.z
-# define thickness1 pos1.w
-# define thickness2 pos2.w
-# define strength1 uv1.w
-# define strength2 uv2.w
-/* Packed! need to be decoded. */
-# define hardness1 ma1.w
-# define hardness2 ma2.w
-# define uvrot1 ma1.w
-# define aspect1 ma1.w
-
-vec2 decode_aspect(int packed_data)
-{
- float asp = float(uint(packed_data) & 0x1FFu) * (1.0 / 255.0);
- return (asp > 1.0) ? vec2(1.0, (asp - 1.0)) : vec2(asp, 1.0);
-}
-
-float decode_uvrot(int packed_data)
-{
- uint udata = uint(packed_data);
- float uvrot = 1e-8 + float((udata & 0x1FE00u) >> 9u) * (1.0 / 255.0);
- return ((udata & 0x20000u) != 0u) ? -uvrot : uvrot;
-}
-
-float decode_hardness(int packed_data)
-{
- return float((uint(packed_data) & 0x3FC0000u) >> 18u) * (1.0 / 255.0);
-}
-
-void discard_vert()
-{
- /* We set the vertex at the camera origin to generate 0 fragments. */
- gl_Position = vec4(0.0, 0.0, -3e36, 0.0);
-}
-
-vec2 project_to_screenspace(vec4 v)
-{
- return ((v.xy / v.w) * 0.5 + 0.5) * sizeViewport;
-}
-
-vec2 rotate_90deg(vec2 v)
-{
- /* Counter Clock-Wise. */
- return vec2(-v.y, v.x);
-}
-
-mat4 model_matrix_get()
-{
- return ModelMatrix;
-}
-
-vec3 transform_point(mat4 m, vec3 v)
-{
- return (m * vec4(v, 1.0)).xyz;
-}
-
-vec2 safe_normalize(vec2 v)
-{
- float len_sqr = dot(v, v);
- if (len_sqr > 0.0) {
- return v / sqrt(len_sqr);
- }
- else {
- return vec2(1.0, 0.0);
- }
-}
-
-vec2 safe_normalize_len(vec2 v, out float len)
-{
- len = sqrt(dot(v, v));
- if (len > 0.0) {
- return v / len;
- }
- else {
- return vec2(1.0, 0.0);
- }
-}
-
-float stroke_thickness_modulate(float thickness)
-{
- /* Modify stroke thickness by object and layer factors. */
- thickness *= thicknessScale;
- thickness += thicknessOffset;
- thickness = max(1.0, thickness);
-
- if (thicknessIsScreenSpace) {
- /* Multiply offset by view Z so that offset is constant in screenspace.
- * (e.i: does not change with the distance to camera) */
- thickness *= gl_Position.w;
- }
- else {
- /* World space point size. */
- thickness *= thicknessWorldScale * drw_view.winmat[1][1] * sizeViewport.y;
- }
- return thickness;
-}
-
-float clamp_small_stroke_thickness(float thickness)
-{
- /* To avoid aliasing artifacts, we clamp the line thickness and
- * reduce its opacity in the fragment shader. */
- float min_thickness = gl_Position.w * 1.3;
- thickness = max(min_thickness, thickness);
-
- return thickness;
-}
-
-# ifdef GP_MATERIAL_BUFFER_LEN
-void color_output(vec4 stroke_col, vec4 vert_col, float vert_strength, float mix_tex)
-{
- /* Mix stroke with other colors. */
- vec4 mixed_col = stroke_col;
- mixed_col.rgb = mix(mixed_col.rgb, vert_col.rgb, vert_col.a * vertexColorOpacity);
- mixed_col.rgb = mix(mixed_col.rgb, layerTint.rgb, layerTint.a);
- mixed_col.a *= vert_strength * layerOpacity;
- /**
- * This is what the fragment shader looks like.
- * out = col * finalColorMul + col.a * finalColorAdd.
- * finalColorMul is how much of the texture color to keep.
- * finalColorAdd is how much of the mixed color to add.
- * Note that we never add alpha. This is to keep the texture act as a stencil.
- * We do however, modulate the alpha (reduce it).
- */
- /* We add the mixed color. This is 100% mix (no texture visible). */
- finalColorMul = vec4(mixed_col.aaa, mixed_col.a);
- finalColorAdd = vec4(mixed_col.rgb * mixed_col.a, 0.0);
- /* Then we blend according to the texture mix factor.
- * Note that we keep the alpha modulation. */
- finalColorMul.rgb *= mix_tex;
- finalColorAdd.rgb *= 1.0 - mix_tex;
-}
-# endif
-
-void stroke_vertex()
-{
- int m = ma1.x;
- bool is_dot = false;
- bool is_squares = false;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (m != -1) {
- is_dot = GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_ALIGNMENT);
- is_squares = !GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_DOTS);
- }
-# endif
-
- /* Special Case. Stroke with single vert are rendered as dots. Do not discard them. */
- if (!is_dot && ma.x == -1 && ma2.x == -1) {
- is_dot = true;
- is_squares = false;
- }
-
- /* Endpoints, we discard the vertices. */
- if (ma1.x == -1 || (!is_dot && ma2.x == -1)) {
- discard_vert();
- return;
- }
-
- mat4 model_mat = model_matrix_get();
-
- /* Avoid using a vertex attribute for quad positioning. */
- float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
- float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
-
- bool use_curr = is_dot || (x == -1.0);
-
- vec3 wpos_adj = transform_point(model_mat, (use_curr) ? pos.xyz : pos3.xyz);
- vec3 wpos1 = transform_point(model_mat, pos1.xyz);
- vec3 wpos2 = transform_point(model_mat, pos2.xyz);
-
- vec4 ndc_adj = point_world_to_ndc(wpos_adj);
- vec4 ndc1 = point_world_to_ndc(wpos1);
- vec4 ndc2 = point_world_to_ndc(wpos2);
-
- gl_Position = (use_curr) ? ndc1 : ndc2;
- finalPos = (use_curr) ? wpos1 : wpos2;
-
- vec2 ss_adj = project_to_screenspace(ndc_adj);
- vec2 ss1 = project_to_screenspace(ndc1);
- vec2 ss2 = project_to_screenspace(ndc2);
- /* Screenspace Lines tangents. */
- float line_len;
- vec2 line = safe_normalize_len(ss2 - ss1, line_len);
- vec2 line_adj = safe_normalize((use_curr) ? (ss1 - ss_adj) : (ss_adj - ss2));
-
- float thickness = abs((use_curr) ? thickness1 : thickness2);
- thickness = stroke_thickness_modulate(thickness);
- float clampedThickness = clamp_small_stroke_thickness(thickness);
-
- finalUvs = vec2(x, y) * 0.5 + 0.5;
- strokeHardeness = decode_hardness(use_curr ? hardness1 : hardness2);
-
- if (is_dot) {
-# ifdef GP_MATERIAL_BUFFER_LEN
- int alignement = GP_FLAG(m) & GP_STROKE_ALIGNMENT;
- /* For one point strokes use object alignment. */
- if (ma.x == -1 && ma2.x == -1 && alignement == GP_STROKE_ALIGNMENT_STROKE) {
- alignement = GP_STROKE_ALIGNMENT_OBJECT;
- }
-# endif
-
- vec2 x_axis;
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (alignement == GP_STROKE_ALIGNMENT_STROKE) {
- x_axis = (ma2.x == -1) ? line_adj : line;
- }
- else if (alignement == GP_STROKE_ALIGNMENT_FIXED) {
- /* Default for no-material drawing. */
- x_axis = vec2(1.0, 0.0);
- }
- else
-# endif
- { /* GP_STROKE_ALIGNMENT_OBJECT */
- vec4 ndc_x = point_world_to_ndc(wpos1 + model_mat[0].xyz);
- vec2 ss_x = project_to_screenspace(ndc_x);
- x_axis = safe_normalize(ss_x - ss1);
- }
-
- /* Rotation: Encoded as Cos + Sin sign. */
- float uv_rot = decode_uvrot(uvrot1);
- float rot_sin = sqrt(max(0.0, 1.0 - uv_rot * uv_rot)) * sign(uv_rot);
- float rot_cos = abs(uv_rot);
- x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- if (is_dot) {
- float alignment_cos = MATERIAL(m).fill_uv_offset.z;
- float alignment_sin = MATERIAL(m).fill_uv_offset.w;
- x_axis = mat2(alignment_cos, -alignment_sin, alignment_sin, alignment_cos) * x_axis;
- }
-# endif
-
- vec2 y_axis = rotate_90deg(x_axis);
-
- strokeAspect = decode_aspect(aspect1);
-
- x *= strokeAspect.x;
- y *= strokeAspect.y;
-
- /* Invert for vertex shader. */
- strokeAspect = 1.0 / strokeAspect;
-
- gl_Position.xy += (x * x_axis + y * y_axis) * sizeViewportInv.xy * clampedThickness;
-
- strokePt1 = ss1;
- strokePt2 = ss1 + x_axis * 0.5;
- strokeThickness = (is_squares) ? 1e18 : (clampedThickness / gl_Position.w);
- unclampedThickness = (is_squares) ? 1e18 : (thickness / gl_Position.w);
- }
- else {
- bool is_stroke_start = (ma.x == -1 && x == -1);
- bool is_stroke_end = (ma3.x == -1 && x == 1);
-
- /* Mitter tangent vector. */
- vec2 miter_tan = safe_normalize(line_adj + line);
- float miter_dot = dot(miter_tan, line_adj);
- /* Break corners after a certain angle to avoid really thick corners. */
- const float miter_limit = 0.5; /* cos(60°) */
- bool miter_break = (miter_dot < miter_limit);
- miter_tan = (miter_break || is_stroke_start || is_stroke_end) ? line : (miter_tan / miter_dot);
-
- vec2 miter = rotate_90deg(miter_tan);
-
- strokePt1.xy = ss1;
- strokePt2.xy = ss2;
- strokeThickness = clampedThickness / gl_Position.w;
- unclampedThickness = thickness / gl_Position.w;
- strokeAspect = vec2(1.0);
-
- vec2 screen_ofs = miter * y;
-
- /* Reminder: we packed the cap flag into the sign of strength and thickness sign. */
- if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) ||
- (miter_break && !is_stroke_start && !is_stroke_end)) {
- screen_ofs += line * x;
- }
-
- gl_Position.xy += screen_ofs * sizeViewportInv.xy * clampedThickness;
-
- finalUvs.x = (use_curr) ? uv1.z : uv2.z;
-# ifdef GP_MATERIAL_BUFFER_LEN
- finalUvs.x *= MATERIAL(m).stroke_u_scale;
-# endif
- }
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- vec4 vert_col = (use_curr) ? col1 : col2;
- float vert_strength = abs((use_curr) ? strength1 : strength2);
- vec4 stroke_col = MATERIAL(m).stroke_color;
- float mix_tex = MATERIAL(m).stroke_texture_mix;
-
- /* Special case: We don't use vertex color if material Holdout. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_HOLDOUT)) {
- vert_col = vec4(0.0);
- }
-
- color_output(stroke_col, vert_col, vert_strength, mix_tex);
-
- matFlag = GP_FLAG(m) & ~GP_FILL_FLAGS;
-# endif
-
- if (strokeOrder3d) {
- /* Use the fragment depth (see fragment shader). */
- depth = -1.0;
- }
-# ifdef GP_MATERIAL_BUFFER_LEN
- else if (GP_FLAG_TEST(GP_FLAG(m), GP_STROKE_OVERLAP)) {
- /* Use the index of the point as depth.
- * This means the stroke can overlap itself. */
- depth = (point_id1 + strokeIndexOffset + 1.0) * 0.0000002;
- }
-# endif
- else {
- /* Use the index of first point of the stroke as depth.
- * We render using a greater depth test this means the stroke
- * cannot overlap itself.
- * We offset by one so that the fill can be overlapped by its stroke.
- * The offset is ok since we pad the strokes data because of adjacency infos. */
- depth = (stroke_id1 + strokeIndexOffset + 1.0) * 0.0000002;
- }
-}
-
-void fill_vertex()
-{
- mat4 model_mat = model_matrix_get();
-
- vec3 wpos = transform_point(model_mat, pos1.xyz);
- gl_Position = point_world_to_ndc(wpos);
- finalPos = wpos;
-
-# ifdef GP_MATERIAL_BUFFER_LEN
- int m = ma1.x;
-
- vec4 fill_col = MATERIAL(m).fill_color;
- float mix_tex = MATERIAL(m).fill_texture_mix;
-
- /* Special case: We don't modulate alpha in gradient mode. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_GRADIENT_USE)) {
- fill_col.a = 1.0;
- }
-
- /* Decode fill opacity. */
- vec4 fcol_decode = vec4(fcol1.rgb, floor(fcol1.a / 10.0));
- float fill_opacity = fcol1.a - (fcol_decode.a * 10);
- fcol_decode.a /= 10000.0;
-
- /* Special case: We don't use vertex color if material Holdout. */
- if (GP_FLAG_TEST(GP_FLAG(m), GP_FILL_HOLDOUT)) {
- fcol_decode = vec4(0.0);
- }
-
- /* Apply opacity. */
- fill_col.a *= fill_opacity;
- /* If factor is > 1 force opacity. */
- if (fill_opacity > 1.0) {
- fill_col.a += fill_opacity - 1.0;
- }
-
- fill_col.a = clamp(fill_col.a, 0.0, 1.0);
-
- color_output(fill_col, fcol_decode, 1.0, mix_tex);
-
- matFlag = GP_FLAG(m) & GP_FILL_FLAGS;
- matFlag |= m << GP_MATID_SHIFT;
-
- vec2 loc = MATERIAL(m).fill_uv_offset.xy;
- mat2x2 rot_scale = mat2x2(MATERIAL(m).fill_uv_rot_scale.xy, MATERIAL(m).fill_uv_rot_scale.zw);
- finalUvs = rot_scale * uv1.xy + loc;
-# endif
-
- strokeHardeness = 1.0;
- strokeThickness = 1e18;
- unclampedThickness = 1e20;
- strokeAspect = vec2(1.0);
- strokePt1 = strokePt2 = vec2(0.0);
-
- if (strokeOrder3d) {
- /* Use the fragment depth (see fragment shader). */
- depth = -1.0;
- /* We still offset the fills a little to avoid overlaps */
- gl_Position.z += 0.000002;
- }
- else {
- /* Use the index of first point of the stroke as depth. */
- depth = (stroke_id1 + strokeIndexOffset) * 0.0000002;
- }
-}
-
-void gpencil_vertex()
-{
- /* Trick to detect if a drawcall is stroke or fill.
- * This does mean that we need to draw an empty stroke segment before starting
- * to draw the real stroke segments. */
- bool is_fill = (gl_InstanceID == 0);
-
- if (!is_fill) {
- stroke_vertex();
- }
- else {
- fill_vertex();
- }
-}
-
-#endif
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
index 8ed03b23809..9b1db09ab3c 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vert.glsl
@@ -31,23 +31,11 @@ void main()
vec4 vert_color;
vec3 vert_N;
+ ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, gpencil_stroke_point_id() * 3 + 1));
gpMaterial gp_mat = materials[ma1.x + gpMaterialOffset];
gpMaterialFlag gp_flag = floatBitsToUint(gp_mat._flag);
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- vec4(viewportSize, 1.0 / viewportSize),
+ gl_Position = gpencil_vertex(vec4(viewportSize, 1.0 / viewportSize),
gp_flag,
gp_mat._alignment_rot,
gp_interp.pos,
@@ -60,7 +48,7 @@ void main()
gp_interp.thickness,
gp_interp.hardness);
- if (GPENCIL_IS_STROKE_VERTEX) {
+ if (gpencil_is_stroke_vertex()) {
if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) {
gp_interp.uv.x *= gp_mat._stroke_u_scale;
}
@@ -96,6 +84,9 @@ void main()
}
}
else {
+ int stroke_point_id = gpencil_stroke_point_id();
+ vec4 uv1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 2);
+ vec4 fcol1 = texelFetch(gp_col_tx, stroke_point_id * 2 + 1);
vec4 fill_col = gp_mat.fill_color;
/* Special case: We don't modulate alpha in gradient mode. */
diff --git a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
index edd51e71242..da2776254e6 100644
--- a/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
+++ b/source/blender/draw/engines/gpencil/shaders/infos/gpencil_info.hh
@@ -22,10 +22,10 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry)
.do_static_compilation(true)
.define("GP_LIGHT")
.typedef_source("gpencil_defines.h")
- .sampler(0, ImageType::FLOAT_2D, "gpFillTexture")
- .sampler(1, ImageType::FLOAT_2D, "gpStrokeTexture")
- .sampler(2, ImageType::DEPTH_2D, "gpSceneDepthTexture")
- .sampler(3, ImageType::FLOAT_2D, "gpMaskTexture")
+ .sampler(2, ImageType::FLOAT_2D, "gpFillTexture")
+ .sampler(3, ImageType::FLOAT_2D, "gpStrokeTexture")
+ .sampler(4, ImageType::DEPTH_2D, "gpSceneDepthTexture")
+ .sampler(5, ImageType::FLOAT_2D, "gpMaskTexture")
.uniform_buf(4, "gpMaterial", "materials[GPENCIL_MATERIAL_BUFFER_LEN]", Frequency::BATCH)
.uniform_buf(3, "gpLight", "lights[GPENCIL_LIGHT_BUFFER_LEN]", Frequency::BATCH)
.push_constant(Type::VEC2, "viewportSize")
diff --git a/source/blender/draw/engines/overlay/overlay_outline.cc b/source/blender/draw/engines/overlay/overlay_outline.cc
index 5ea02376b67..50d42effe00 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.cc
+++ b/source/blender/draw/engines/overlay/overlay_outline.cc
@@ -172,7 +172,6 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
typedef struct iterData {
Object *ob;
DRWShadingGroup *stroke_grp;
- DRWShadingGroup *fill_grp;
int cfra;
float plane[4];
} iterData;
@@ -193,12 +192,17 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
* Convert to world units (by default, 1 meter = 2000 pixels). */
float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / 2000.0f);
+ GPUVertBuf *position_tx = DRW_cache_gpencil_position_buffer_get(iter->ob, iter->cfra);
+ GPUVertBuf *color_tx = DRW_cache_gpencil_color_buffer_get(iter->ob, iter->cfra);
+
DRWShadingGroup *grp = iter->stroke_grp = DRW_shgroup_create_sub(iter->stroke_grp);
DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", is_stroke_order_3d);
DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", object_scale);
DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", float(gpl->line_change));
DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale);
DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", iter->plane);
+ DRW_shgroup_buffer_texture(grp, "gp_pos_tx", position_tx);
+ DRW_shgroup_buffer_texture(grp, "gp_col_tx", color_tx);
}
static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/,
@@ -219,20 +223,19 @@ static void gpencil_stroke_cache_populate(bGPDlayer * /*gpl*/,
return;
}
+ struct GPUBatch *geom = DRW_cache_gpencil_get(iter->ob, iter->cfra);
+
if (show_fill) {
- struct GPUBatch *geom = DRW_cache_gpencil_fills_get(iter->ob, iter->cfra);
int vfirst = gps->runtime.fill_start * 3;
int vcount = gps->tot_triangles * 3;
- DRW_shgroup_call_range(iter->fill_grp, iter->ob, geom, vfirst, vcount);
+ DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
}
if (show_stroke) {
- struct GPUBatch *geom = DRW_cache_gpencil_strokes_get(iter->ob, iter->cfra);
- /* Start one vert before to have gl_InstanceID > 0 (see shader). */
- int vfirst = gps->runtime.stroke_start - 1;
- /* Include "potential" cyclic vertex and start adj vertex (see shader). */
- int vcount = gps->totpoints + 1 + 1;
- DRW_shgroup_call_instance_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
+ int vfirst = gps->runtime.stroke_start * 3;
+ /* Include "potential" cyclic vertex (see shader). */
+ int vcount = (gps->totpoints + 1) * 2 * 3;
+ DRW_shgroup_call_range(iter->stroke_grp, iter->ob, geom, vfirst, vcount);
}
}
@@ -247,7 +250,6 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
iterData iter{};
iter.ob = ob;
iter.stroke_grp = pd->outlines_gpencil_grp;
- iter.fill_grp = DRW_shgroup_create_sub(pd->outlines_gpencil_grp);
iter.cfra = pd->cfra;
if (gpd->draw_mode == GP_DRAWMODE_2D) {
diff --git a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
index 7d8fb0c2cb8..851e0884354 100644
--- a/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
@@ -34,20 +34,7 @@ void main()
float unused_strength;
vec2 unused_uv;
- gl_Position = gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- vec4(sizeViewport, sizeViewportInv),
+ gl_Position = gpencil_vertex(vec4(sizeViewport, sizeViewportInv),
world_pos,
unused_N,
unused_color,
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 058f28f094d..44abf3c7064 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -13,6 +13,7 @@ extern "C" {
struct GPUBatch;
struct GPUMaterial;
+struct GPUVertBuf;
struct ModifierData;
struct Object;
struct PTCacheEdit;
@@ -257,14 +258,16 @@ struct GPUBatch *DRW_cache_volume_selection_surface_get(struct Object *ob);
/* GPencil */
-struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
+struct GPUBatch *DRW_cache_gpencil_get(struct Object *ob, int cfra);
+struct GPUVertBuf *DRW_cache_gpencil_position_buffer_get(struct Object *ob, int cfra);
+struct GPUVertBuf *DRW_cache_gpencil_color_buffer_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_lines_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_points_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_handles_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_edit_curve_points_get(struct Object *ob, int cfra);
-struct GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(struct Object *ob);
-struct GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(struct Object *ob);
+struct GPUBatch *DRW_cache_gpencil_sbuffer_get(struct Object *ob);
+struct GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(struct Object *ob);
+struct GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(struct Object *ob);
int DRW_gpencil_material_count_get(struct bGPdata *gpd);
struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.cc b/source/blender/draw/intern/draw_cache_impl_gpencil.cc
index 94925bfae71..eadb7772f4c 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.cc
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.cc
@@ -23,12 +23,14 @@
#include "DEG_depsgraph_query.h"
#include "BLI_hash.h"
+#include "BLI_math_vec_types.hh"
#include "BLI_polyfill_2d.h"
#include "draw_cache.h"
#include "draw_cache_impl.h"
#include "../engines/gpencil/gpencil_defines.h"
+#include "../engines/gpencil/gpencil_shader_shared.h"
#define BEZIER_HANDLE (1 << 3)
#define COLOR_SHIFT 5
@@ -41,11 +43,13 @@ typedef struct GpencilBatchCache {
/** Instancing Data */
GPUVertBuf *vbo;
GPUVertBuf *vbo_col;
- /** Fill Topology */
+ /** Indices in material order, then stroke order with fill first.
+ * Strokes can be individually rendered using `gps->runtime.stroke_start` and
+ * `gps->runtime.stroke_start`. */
GPUIndexBuf *ibo;
- /** Instancing Batches */
- GPUBatch *stroke_batch;
- GPUBatch *fill_batch;
+ /** Batches */
+ GPUBatch *geom_batch;
+ /** Stroke lines only */
GPUBatch *lines_batch;
/** Edit Mode */
@@ -117,8 +121,7 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
}
GPU_BATCH_DISCARD_SAFE(cache->lines_batch);
- GPU_BATCH_DISCARD_SAFE(cache->fill_batch);
- GPU_BATCH_DISCARD_SAFE(cache->stroke_batch);
+ GPU_BATCH_DISCARD_SAFE(cache->geom_batch);
GPU_VERTBUF_DISCARD_SAFE(cache->vbo);
GPU_VERTBUF_DISCARD_SAFE(cache->vbo_col);
GPU_INDEXBUF_DISCARD_SAFE(cache->ibo);
@@ -173,9 +176,10 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd)
/* MUST match the format below. */
typedef struct gpStrokeVert {
- int32_t mat, stroke_id, point_id, packed_asp_hard_rot;
/** Position and thickness packed in the same attribute. */
float pos[3], thickness;
+ /** Material Index, Stroke Index, Point Index, Packed aspect + hardness + rotation. */
+ int32_t mat, stroke_id, point_id, packed_asp_hard_rot;
/** UV and strength packed in the same attribute. */
float uv_fill[2], u_stroke, strength;
} gpStrokeVert;
@@ -184,12 +188,9 @@ static GPUVertFormat *gpencil_stroke_format(void)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT);
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "ma", GPU_COMP_I32, 4, GPU_FETCH_INT);
GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- /* IMPORTANT: This means having only 4 attributes
- * to fit into GPU module limit of 16 attributes. */
- GPU_vertformat_multiload_enable(&format, 4);
}
return &format;
}
@@ -239,9 +240,6 @@ static GPUVertFormat *gpencil_color_format(void)
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "col", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "fcol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- /* IMPORTANT: This means having only 4 attributes
- * to fit into GPU module limit of 16 attributes. */
- GPU_vertformat_multiload_enable(&format, 4);
}
return &format;
}
@@ -296,7 +294,8 @@ BLI_INLINE int32_t pack_rotation_aspect_hardness(float rot, float asp, float har
return packed;
}
-static void gpencil_buffer_add_point(gpStrokeVert *verts,
+static void gpencil_buffer_add_point(GPUIndexBufBuilder *ibo,
+ gpStrokeVert *verts,
gpColorVert *cols,
const bGPDstroke *gps,
const bGPDspoint *pt,
@@ -330,27 +329,36 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts,
vert->packed_asp_hard_rot = pack_rotation_aspect_hardness(
pt->uv_rot, aspect_ratio, gps->hardeness);
+
+ if (!is_endpoint) {
+ /* Issue a Quad per point. */
+ /* The attribute loading uses a different shader and will undo this bit packing. */
+ int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT;
+ GPU_indexbuf_add_tri_verts(ibo, v_mat + 0, v_mat + 1, v_mat + 2);
+ GPU_indexbuf_add_tri_verts(ibo, v_mat + 2, v_mat + 1, v_mat + 3);
+ }
}
-static void gpencil_buffer_add_stroke(gpStrokeVert *verts,
+static void gpencil_buffer_add_stroke(GPUIndexBufBuilder *ibo,
+ gpStrokeVert *verts,
gpColorVert *cols,
const bGPDstroke *gps)
{
const bGPDspoint *pts = gps->points;
int pts_len = gps->totpoints;
bool is_cyclic = gpencil_stroke_is_cyclic(gps);
- int v = gps->runtime.stroke_start;
+ int v = gps->runtime.vertex_start;
/* First point for adjacency (not drawn). */
int adj_idx = (is_cyclic) ? (pts_len - 1) : min_ii(pts_len - 1, 1);
- gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true);
for (int i = 0; i < pts_len; i++) {
- gpencil_buffer_add_point(verts, cols, gps, &pts[i], v++, false);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[i], v++, false);
}
/* Draw line to first point to complete the loop for cyclic strokes. */
if (is_cyclic) {
- gpencil_buffer_add_point(verts, cols, gps, &pts[0], v, false);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[0], v, false);
/* UV factor needs to be adjusted for the last point to not be equal to the UV factor of the
* first point. It should be the factor of the last point plus the distance from the last point
* to the first.
@@ -361,16 +369,20 @@ static void gpencil_buffer_add_stroke(gpStrokeVert *verts,
}
/* Last adjacency point (not drawn). */
adj_idx = (is_cyclic) ? 1 : max_ii(0, pts_len - 2);
- gpencil_buffer_add_point(verts, cols, gps, &pts[adj_idx], v++, true);
+ gpencil_buffer_add_point(ibo, verts, cols, gps, &pts[adj_idx], v++, true);
}
static void gpencil_buffer_add_fill(GPUIndexBufBuilder *ibo, const bGPDstroke *gps)
{
int tri_len = gps->tot_triangles;
- int v = gps->runtime.stroke_start;
+ int v = gps->runtime.vertex_start + 1;
for (int i = 0; i < tri_len; i++) {
uint *tri = gps->triangles[i].verts;
- GPU_indexbuf_add_tri_verts(ibo, v + tri[0], v + tri[1], v + tri[2]);
+ /* The attribute loading uses a different shader and will undo this bit packing. */
+ GPU_indexbuf_add_tri_verts(ibo,
+ (v + tri[0]) << GP_VERTEX_ID_SHIFT,
+ (v + tri[1]) << GP_VERTEX_ID_SHIFT,
+ (v + tri[2]) << GP_VERTEX_ID_SHIFT);
}
}
@@ -380,10 +392,10 @@ static void gpencil_stroke_iter_cb(bGPDlayer *UNUSED(gpl),
void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
- gpencil_buffer_add_stroke(iter->verts, iter->cols, gps);
if (gps->tot_triangles > 0) {
gpencil_buffer_add_fill(&iter->ibo, gps);
}
+ gpencil_buffer_add_stroke(&iter->ibo, iter->verts, iter->cols, gps);
}
static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
@@ -392,12 +404,15 @@ static void gpencil_object_verts_count_cb(bGPDlayer *UNUSED(gpl),
void *thunk)
{
gpIterData *iter = (gpIterData *)thunk;
-
- /* Store first index offset */
- gps->runtime.stroke_start = iter->vert_len;
+ int stroke_vert_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
+ gps->runtime.vertex_start = iter->vert_len;
+ /* Add additional padding at the start and end. */
+ iter->vert_len += 1 + stroke_vert_len + 1;
+ /* Store first index offset. */
gps->runtime.fill_start = iter->tri_len;
- iter->vert_len += gps->totpoints + 2 + gpencil_stroke_is_cyclic(gps);
iter->tri_len += gps->tot_triangles;
+ gps->runtime.stroke_start = iter->tri_len;
+ iter->tri_len += stroke_vert_len * 2;
}
static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfra)
@@ -407,7 +422,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
if (cache->vbo == NULL) {
/* Should be discarded together. */
BLI_assert(cache->vbo == NULL && cache->ibo == NULL);
- BLI_assert(cache->fill_batch == NULL && cache->stroke_batch == NULL);
+ BLI_assert(cache->geom_batch == NULL);
/* TODO/PERF: Could be changed to only do it if needed.
* For now it's simpler to assume we always need it
* since multiple viewport could or could not need it.
@@ -420,25 +435,26 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.gpd = gpd,
.verts = NULL,
.ibo = {0},
- .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
+ .vert_len = 0,
.tri_len = 0,
.curve_len = 0,
};
BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, NULL, gpencil_object_verts_count_cb, &iter, do_onion, cfra);
+ GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
GPUVertFormat *format_col = gpencil_color_format();
- cache->vbo = GPU_vertbuf_create_with_format(format);
- cache->vbo_col = GPU_vertbuf_create_with_format(format_col);
+ cache->vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag);
+ cache->vbo_col = GPU_vertbuf_create_with_format_ex(format_col, vbo_flag);
/* Add extra space at the end of the buffer because of quad load. */
GPU_vertbuf_data_alloc(cache->vbo, iter.vert_len + 2);
GPU_vertbuf_data_alloc(cache->vbo_col, iter.vert_len + 2);
iter.verts = (gpStrokeVert *)GPU_vertbuf_get_data(cache->vbo);
iter.cols = (gpColorVert *)GPU_vertbuf_get_data(cache->vbo_col);
/* Create IBO. */
- GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
+ GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, 0xFFFFFFFFu);
/* Fill buffers with data. */
BKE_gpencil_visible_stroke_advanced_iter(
@@ -453,33 +469,39 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
/* Finish the IBO. */
cache->ibo = GPU_indexbuf_build(&iter.ibo);
-
/* Create the batches */
- cache->fill_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
- GPU_batch_vertbuf_add(cache->fill_batch, cache->vbo_col);
- cache->stroke_batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
- GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo, 0);
- GPU_batch_instbuf_add_ex(cache->stroke_batch, cache->vbo_col, 0);
+ cache->geom_batch = GPU_batch_create(GPU_PRIM_TRIS, cache->vbo, cache->ibo);
+ /* Allow creation of buffer texture. */
+ GPU_vertbuf_use(cache->vbo);
+ GPU_vertbuf_use(cache->vbo_col);
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
cache->is_dirty = false;
}
}
-GPUBatch *DRW_cache_gpencil_strokes_get(Object *ob, int cfra)
+GPUBatch *DRW_cache_gpencil_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
- return cache->stroke_batch;
+ return cache->geom_batch;
}
-GPUBatch *DRW_cache_gpencil_fills_get(Object *ob, int cfra)
+GPUVertBuf *DRW_cache_gpencil_position_buffer_get(Object *ob, int cfra)
{
GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
gpencil_batches_ensure(ob, cache, cfra);
- return cache->fill_batch;
+ return cache->vbo;
+}
+
+GPUVertBuf *DRW_cache_gpencil_color_buffer_get(Object *ob, int cfra)
+{
+ GpencilBatchCache *cache = gpencil_batch_cache_get(ob, cfra);
+ gpencil_batches_ensure(ob, cache, cfra);
+
+ return cache->vbo_col;
}
static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl),
@@ -490,7 +512,7 @@ static void gpencil_lines_indices_cb(bGPDlayer *UNUSED(gpl),
gpIterData *iter = (gpIterData *)thunk;
int pts_len = gps->totpoints + gpencil_stroke_is_cyclic(gps);
- int start = gps->runtime.stroke_start + 1;
+ int start = gps->runtime.vertex_start + 1;
int end = start + pts_len;
for (int i = start; i < end; i++) {
GPU_indexbuf_add_generic_vert(&iter->ibo, i);
@@ -573,7 +595,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_
/* DRW_cache_gpencil_sbuffer_stroke_data_get need to have been called previously. */
BLI_assert(gps != NULL);
- if (do_stroke && (gpd->runtime.sbuffer_stroke_batch == NULL)) {
+ if (do_stroke && (gpd->runtime.sbuffer_batch == NULL)) {
gps->points = (bGPDspoint *)MEM_mallocN(vert_len * sizeof(*gps->points), __func__);
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -597,35 +619,24 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_
/* Calc uv data along the stroke. */
BKE_gpencil_stroke_uv_update(gps);
+ int vert_len = gps->tot_triangles + (gps->totpoints + gpencil_stroke_is_cyclic(gps)) * 2;
+ /* Create IBO. */
+ GPUIndexBufBuilder ibo_builder;
+ GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, vert_len, 0xFFFFFFFFu);
/* Create VBO. */
+ GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
GPUVertFormat *format = gpencil_stroke_format();
GPUVertFormat *format_color = gpencil_color_format();
- GPUVertBuf *vbo = GPU_vertbuf_create_with_format(format);
- GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format(format_color);
- /* Add extra space at the end (and start) of the buffer because of quad load and cyclic. */
- GPU_vertbuf_data_alloc(vbo, 1 + vert_len + 1 + 2);
- GPU_vertbuf_data_alloc(vbo_col, 1 + vert_len + 1 + 2);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format_ex(format, vbo_flag);
+ GPUVertBuf *vbo_col = GPU_vertbuf_create_with_format_ex(format_color, vbo_flag);
+ /* Add extra space at the end the buffer because of quad load and cyclic. */
+ GPU_vertbuf_data_alloc(vbo, vert_len + 2);
+ GPU_vertbuf_data_alloc(vbo_col, vert_len + 2);
gpStrokeVert *verts = (gpStrokeVert *)GPU_vertbuf_get_data(vbo);
gpColorVert *cols = (gpColorVert *)GPU_vertbuf_get_data(vbo_col);
- /* Fill buffers with data. */
- gpencil_buffer_add_stroke(verts, cols, gps);
-
- GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_STRIP, gpencil_dummy_buffer_get(), NULL);
- GPU_batch_instbuf_add_ex(batch, vbo, true);
- GPU_batch_instbuf_add_ex(batch, vbo_col, true);
-
- gpd->runtime.sbuffer_stroke_batch = batch;
-
- MEM_freeN(gps->points);
- }
-
- if (do_fill && (gpd->runtime.sbuffer_fill_batch == NULL)) {
- /* Create IBO. */
- GPUIndexBufBuilder ibo_builder;
- GPU_indexbuf_init(&ibo_builder, GPU_PRIM_TRIS, gps->tot_triangles, vert_len);
-
- if (gps->tot_triangles > 0) {
+ /* Create fill indices. */
+ if (do_fill && gps->tot_triangles > 0) {
float(*tpoints2d)[2] = (float(*)[2])MEM_mallocN(sizeof(*tpoints2d) * vert_len, __func__);
/* Triangulate in 2D. */
for (int i = 0; i < vert_len; i++) {
@@ -645,40 +656,56 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_
MEM_freeN(tpoints2d);
}
- GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder);
- GPUVertBuf *vbo = gpd->runtime.sbuffer_stroke_batch->inst[0];
- GPUVertBuf *vbo_col = gpd->runtime.sbuffer_stroke_batch->inst[1];
+ /* Fill buffers with data. */
+ gpencil_buffer_add_stroke(&ibo_builder, verts, cols, gps);
+
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS,
+ gpencil_dummy_buffer_get(),
+ GPU_indexbuf_build(&ibo_builder),
+ GPU_BATCH_OWNS_INDEX);
- GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, ibo, GPU_BATCH_OWNS_INDEX);
- GPU_batch_vertbuf_add(batch, vbo_col);
+ gpd->runtime.sbuffer_position_buf = vbo;
+ gpd->runtime.sbuffer_color_buf = vbo_col;
+ gpd->runtime.sbuffer_batch = batch;
- gpd->runtime.sbuffer_fill_batch = batch;
+ MEM_freeN(gps->points);
}
}
-GPUBatch *DRW_cache_gpencil_sbuffer_stroke_get(Object *ob)
+GPUBatch *DRW_cache_gpencil_sbuffer_get(Object *ob)
+{
+ bGPdata *gpd = (bGPdata *)ob->data;
+ /* Fill batch also need stroke batch to be created (vbo is shared). */
+ gpencil_sbuffer_stroke_ensure(gpd, true, true);
+
+ return gpd->runtime.sbuffer_batch;
+}
+
+GPUVertBuf *DRW_cache_gpencil_sbuffer_position_buffer_get(Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
- gpencil_sbuffer_stroke_ensure(gpd, true, false);
+ /* Fill batch also need stroke batch to be created (vbo is shared). */
+ gpencil_sbuffer_stroke_ensure(gpd, true, true);
- return gpd->runtime.sbuffer_stroke_batch;
+ return gpd->runtime.sbuffer_position_buf;
}
-GPUBatch *DRW_cache_gpencil_sbuffer_fill_get(Object *ob)
+GPUVertBuf *DRW_cache_gpencil_sbuffer_color_buffer_get(Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
/* Fill batch also need stroke batch to be created (vbo is shared). */
gpencil_sbuffer_stroke_ensure(gpd, true, true);
- return gpd->runtime.sbuffer_fill_batch;
+ return gpd->runtime.sbuffer_color_buf;
}
void DRW_cache_gpencil_sbuffer_clear(Object *ob)
{
bGPdata *gpd = (bGPdata *)ob->data;
MEM_SAFE_FREE(gpd->runtime.sbuffer_gps);
- GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_fill_batch);
- GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_stroke_batch);
+ GPU_BATCH_DISCARD_SAFE(gpd->runtime.sbuffer_batch);
+ GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_position_buf);
+ GPU_VERTBUF_DISCARD_SAFE(gpd->runtime.sbuffer_color_buf);
}
/** \} */
diff --git a/source/blender/draw/intern/draw_manager_data.cc b/source/blender/draw/intern/draw_manager_data.cc
index 981206e56fe..b9e0db71122 100644
--- a/source/blender/draw/intern/draw_manager_data.cc
+++ b/source/blender/draw/intern/draw_manager_data.cc
@@ -589,7 +589,7 @@ void DRW_shgroup_buffer_texture(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf *vertex_buffer)
{
- int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ int location = GPU_shader_get_texture_binding(shgroup->shader, name);
if (location == -1) {
return;
}
@@ -606,7 +606,7 @@ void DRW_shgroup_buffer_texture_ref(DRWShadingGroup *shgroup,
const char *name,
GPUVertBuf **vertex_buffer)
{
- int location = GPU_shader_get_ssbo(shgroup->shader, name);
+ int location = GPU_shader_get_texture_binding(shgroup->shader, name);
if (location == -1) {
return;
}
@@ -695,7 +695,7 @@ static void drw_call_obinfos_init(DRWObjectInfos *ob_infos, Object *ob)
drw_call_calc_orco(ob, ob_infos->orcotexfac);
/* Random float value. */
uint random = (DST.dupli_source) ?
- DST.dupli_source->random_id :
+ DST.dupli_source->random_id :
/* TODO(fclem): this is rather costly to do at runtime. Maybe we can
* put it in ob->runtime and make depsgraph ensure it is up to date. */
BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
diff --git a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
index 123c493b572..def841b07aa 100644
--- a/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_gpencil_lib.glsl
@@ -90,10 +90,15 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
#ifdef GPU_VERTEX_SHADER
-/* Trick to detect if a drawcall is stroke or fill.
- * This does mean that we need to draw an empty stroke segment before starting
- * to draw the real stroke segments. */
-# define GPENCIL_IS_STROKE_VERTEX (gl_InstanceID != 0)
+int gpencil_stroke_point_id()
+{
+ return (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT;
+}
+
+bool gpencil_is_stroke_vertex()
+{
+ return flag_test(gl_VertexID, GP_IS_STROKE_VERTEX_BIT);
+}
/**
* Returns value of gl_Position.
@@ -120,20 +125,7 @@ float gpencil_clamp_small_stroke_thickness(float thickness, vec4 ndc_pos)
* WARNING: Max attribute count is actually 14 because OSX OpenGL implementation
* considers gl_VertexID and gl_InstanceID as vertex attribute. (see T74536)
*/
-vec4 gpencil_vertex(ivec4 ma,
- ivec4 ma1,
- ivec4 ma2,
- ivec4 ma3,
- vec4 pos,
- vec4 pos1,
- vec4 pos2,
- vec4 pos3,
- vec4 uv1,
- vec4 uv2,
- vec4 col1,
- vec4 col2,
- vec4 fcol1,
- vec4 viewport_size,
+vec4 gpencil_vertex(vec4 viewport_size,
gpMaterialFlag material_flags,
vec2 alignment_rot,
/* World Position. */
@@ -155,6 +147,24 @@ vec4 gpencil_vertex(ivec4 ma,
/* Stroke hardness. */
out float out_hardness)
{
+ int stroke_point_id = (gl_VertexID & ~GP_IS_STROKE_VERTEX_BIT) >> GP_VERTEX_ID_SHIFT;
+
+ /* Attribute Loading. */
+ vec4 pos = texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 0);
+ vec4 pos1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 0);
+ vec4 pos2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 0);
+ vec4 pos3 = texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 0);
+ ivec4 ma = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id - 1) * 3 + 1));
+ ivec4 ma1 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 1));
+ ivec4 ma2 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 1));
+ ivec4 ma3 = floatBitsToInt(texelFetch(gp_pos_tx, (stroke_point_id + 2) * 3 + 1));
+ vec4 uv1 = texelFetch(gp_pos_tx, (stroke_point_id + 0) * 3 + 2);
+ vec4 uv2 = texelFetch(gp_pos_tx, (stroke_point_id + 1) * 3 + 2);
+
+ vec4 col1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 0);
+ vec4 col2 = texelFetch(gp_col_tx, (stroke_point_id + 1) * 2 + 0);
+ vec4 fcol1 = texelFetch(gp_col_tx, (stroke_point_id + 0) * 2 + 1);
+
# define thickness1 pos1.w
# define thickness2 pos2.w
# define strength1 uv1.w
@@ -167,7 +177,7 @@ vec4 gpencil_vertex(ivec4 ma,
vec4 out_ndc;
- if (GPENCIL_IS_STROKE_VERTEX) {
+ if (gpencil_is_stroke_vertex()) {
bool is_dot = flag_test(material_flags, GP_STROKE_ALIGNMENT);
bool is_squares = !flag_test(material_flags, GP_STROKE_DOTS);
@@ -177,13 +187,6 @@ vec4 gpencil_vertex(ivec4 ma,
is_squares = false;
}
- /* Endpoints, we discard the vertices. */
- if (ma1.x == -1 || (!is_dot && ma2.x == -1)) {
- /* We set the vertex at the camera origin to generate 0 fragments. */
- out_ndc = vec4(0.0, 0.0, -3e36, 0.0);
- return out_ndc;
- }
-
/* Avoid using a vertex attribute for quad positioning. */
float x = float(gl_VertexID & 1) * 2.0 - 1.0; /* [-1..1] */
float y = float(gl_VertexID & 2) - 1.0; /* [-1..1] */
@@ -336,8 +339,7 @@ vec4 gpencil_vertex(ivec4 ma,
out_N = safe_normalize(N);
/* Decode fill opacity. */
- out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0));
- out_color.a /= 10000.0;
+ out_color = vec4(fcol1.rgb, floor(fcol1.a / 10.0) / 10000.0);
/* We still offset the fills a little to avoid overlaps */
out_ndc.z += 0.000002;
@@ -355,20 +357,7 @@ vec4 gpencil_vertex(ivec4 ma,
return out_ndc;
}
-vec4 gpencil_vertex(ivec4 ma,
- ivec4 ma1,
- ivec4 ma2,
- ivec4 ma3,
- vec4 pos,
- vec4 pos1,
- vec4 pos2,
- vec4 pos3,
- vec4 uv1,
- vec4 uv2,
- vec4 col1,
- vec4 col2,
- vec4 fcol1,
- vec4 viewport_size,
+vec4 gpencil_vertex(vec4 viewport_size,
out vec3 out_P,
out vec3 out_N,
out vec4 out_color,
@@ -379,20 +368,7 @@ vec4 gpencil_vertex(ivec4 ma,
out vec2 out_thickness,
out float out_hardness)
{
- return gpencil_vertex(ma,
- ma1,
- ma2,
- ma3,
- pos,
- pos1,
- pos2,
- pos3,
- uv1,
- uv2,
- col1,
- col2,
- fcol1,
- viewport_size,
+ return gpencil_vertex(viewport_size,
0u,
vec2(1.0, 0.0),
out_P,
diff --git a/source/blender/draw/intern/shaders/draw_view_info.hh b/source/blender/draw/intern/shaders/draw_view_info.hh
index 7b500f66a68..114dbab799f 100644
--- a/source/blender/draw/intern/shaders/draw_view_info.hh
+++ b/source/blender/draw/intern/shaders/draw_view_info.hh
@@ -122,26 +122,15 @@ GPU_SHADER_CREATE_INFO(draw_volume).additional_info("draw_modelmat", "draw_resou
GPU_SHADER_CREATE_INFO(draw_gpencil)
.typedef_source("gpencil_shader_shared.h")
.define("DRW_GPENCIL_INFO")
- .vertex_in(0, Type::IVEC4, "ma")
- .vertex_in(1, Type::IVEC4, "ma1")
- .vertex_in(2, Type::IVEC4, "ma2")
- .vertex_in(3, Type::IVEC4, "ma3")
- .vertex_in(4, Type::VEC4, "pos")
- .vertex_in(5, Type::VEC4, "pos1")
- .vertex_in(6, Type::VEC4, "pos2")
- .vertex_in(7, Type::VEC4, "pos3")
- .vertex_in(8, Type::VEC4, "uv1")
- .vertex_in(9, Type::VEC4, "uv2")
- .vertex_in(10, Type::VEC4, "col1")
- .vertex_in(11, Type::VEC4, "col2")
- .vertex_in(12, Type::VEC4, "fcol1")
+ .sampler(0, ImageType::FLOAT_BUFFER, "gp_pos_tx")
+ .sampler(1, ImageType::FLOAT_BUFFER, "gp_col_tx")
/* Per Object */
.push_constant(Type::FLOAT, "gpThicknessScale") /* TODO(fclem): Replace with object info. */
.push_constant(Type::FLOAT, "gpThicknessWorldScale") /* TODO(fclem): Same as above. */
.define("gpThicknessIsScreenSpace", "(gpThicknessWorldScale < 0.0)")
/* Per Layer */
.push_constant(Type::FLOAT, "gpThicknessOffset")
- .additional_info("draw_modelmat", "draw_resource_id_uniform", "draw_object_infos");
+ .additional_info("draw_modelmat", "draw_object_infos");
/** \} */
diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh
index 2ad31183206..124b1751b96 100644
--- a/source/blender/gpu/intern/gpu_texture_private.hh
+++ b/source/blender/gpu/intern/gpu_texture_private.hh
@@ -588,7 +588,7 @@ inline eGPUFrameBufferBits to_framebuffer_bits(eGPUTextureFormat tex_format)
static inline eGPUTextureFormat to_texture_format(const GPUVertFormat *format)
{
- if (format->attr_len > 1 || format->attr_len == 0) {
+ if (format->attr_len == 0) {
BLI_assert_msg(0, "Incorrect vertex format for buffer texture");
return GPU_DEPTH_COMPONENT24;
}
diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc
index b30e3c358c8..76d95ac1b55 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.cc
+++ b/source/blender/gpu/intern/gpu_vertex_format.cc
@@ -361,8 +361,12 @@ void VertexFormat_texture_buffer_pack(GPUVertFormat *format)
* minimum per-vertex stride, which mandates 4-byte alignment in Metal.
* This additional alignment padding caused smaller data types, e.g. U16,
* to mis-align. */
- BLI_assert_msg(format->attr_len == 1,
- "Texture buffer mode should only use a single vertex attribute.");
+ for (int i = 0; i < format->attr_len; i++) {
+ /* The buffer texture setup uses the first attribute for type and size.
+ * Make sure all attributes use the same size. */
+ BLI_assert_msg(format->attrs[i].size == format->attrs[0].size,
+ "Texture buffer mode should only use a attributes with the same size.");
+ }
/* Pack vertex format without minimum stride, as this is not required by texture buffers. */
VertexFormat_pack_impl(format, 1);
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 26dbb544f52..8b3f4956cfe 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -243,12 +243,15 @@ typedef struct bGPDstroke_Runtime {
/** Runtime falloff factor (only for transform). */
float multi_frame_falloff;
- /** Vertex offset in the VBO where this stroke starts. */
+ /** Triangle offset in the IBO where this stroke starts. */
int stroke_start;
/** Triangle offset in the IBO where this fill starts. */
int fill_start;
+ /** Vertex offset in the VBO where this stroke starts. */
+ int vertex_start;
/** Curve Handles offset in the IBO where this handle starts. */
int curve_start;
+ int _pad0;
/** Original stroke (used to dereference evaluated data) */
struct bGPDstroke *gps_orig;
@@ -613,8 +616,9 @@ typedef struct bGPdata_Runtime {
/** Stroke buffer. */
void *sbuffer;
/** Temp batches cleared after drawing. */
- struct GPUBatch *sbuffer_stroke_batch;
- struct GPUBatch *sbuffer_fill_batch;
+ struct GPUVertBuf *sbuffer_position_buf;
+ struct GPUVertBuf *sbuffer_color_buf;
+ struct GPUBatch *sbuffer_batch;
/** Temp stroke used for drawing. */
struct bGPDstroke *sbuffer_gps;