Vulkan: Convert Grease Pencil Shaders

Converting grease pencil stage interfaces to be compatible with vulkan.

Pull Request: https://projects.blender.org/blender/blender/pulls/111222
This commit is contained in:
Jeroen Bakker 2023-08-17 15:25:36 +02:00
parent b6c014c731
commit 101c9383d7
7 changed files with 65 additions and 56 deletions

@ -54,20 +54,20 @@ vec3 gpencil_lighting(void)
void main()
{
vec4 col;
if (flag_test(gp_interp.mat_flag, GP_STROKE_TEXTURE_USE)) {
bool premul = flag_test(gp_interp.mat_flag, GP_STROKE_TEXTURE_PREMUL);
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_USE)) {
bool premul = flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpStrokeTexture, premul, gp_interp.uv);
}
else if (flag_test(gp_interp.mat_flag, GP_FILL_TEXTURE_USE)) {
bool use_clip = flag_test(gp_interp.mat_flag, GP_FILL_TEXTURE_CLIP);
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_USE)) {
bool use_clip = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_CLIP);
vec2 uvs = (use_clip) ? clamp(gp_interp.uv, 0.0, 1.0) : gp_interp.uv;
bool premul = flag_test(gp_interp.mat_flag, GP_FILL_TEXTURE_PREMUL);
bool premul = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_PREMUL);
col = texture_read_as_linearrgb(gpFillTexture, premul, uvs);
}
else if (flag_test(gp_interp.mat_flag, GP_FILL_GRADIENT_USE)) {
bool radial = flag_test(gp_interp.mat_flag, GP_FILL_GRADIENT_RADIAL);
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_USE)) {
bool radial = flag_test(gp_interp_flat.mat_flag, GP_FILL_GRADIENT_RADIAL);
float fac = clamp(radial ? length(gp_interp.uv * 2.0 - 1.0) : gp_interp.uv.x, 0.0, 1.0);
uint matid = gp_interp.mat_flag >> GPENCIl_MATID_SHIFT;
uint matid = gp_interp_flat.mat_flag >> GPENCIl_MATID_SHIFT;
col = mix(gp_materials[matid].fill_color, gp_materials[matid].fill_mix_color, fac);
}
else /* SOLID */ {
@ -81,17 +81,17 @@ void main()
fragColor.rgb *= gpencil_lighting();
fragColor *= gpencil_stroke_round_cap_mask(gp_interp.sspos.xy,
gp_interp.sspos.zw,
gp_interp.aspect,
gp_interp.thickness.x,
gp_interp.hardness);
fragColor *= gpencil_stroke_round_cap_mask(gp_interp_flat.sspos.xy,
gp_interp_flat.sspos.zw,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness.x,
gp_interp_noperspective.hardness);
/* To avoid aliasing artifacts, we reduce the opacity of small strokes. */
fragColor *= smoothstep(0.0, 1.0, gp_interp.thickness.y);
fragColor *= smoothstep(0.0, 1.0, gp_interp_noperspective.thickness.y);
/* Holdout materials. */
if (flag_test(gp_interp.mat_flag, GP_STROKE_HOLDOUT | GP_FILL_HOLDOUT)) {
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_HOLDOUT | GP_FILL_HOLDOUT)) {
revealColor = fragColor.aaaa;
}
else {
@ -130,8 +130,8 @@ void main()
* This has a cost as the depth test cannot happen early.
* We could do this in the vertex shader but then perspective interpolation of uvs and
* fragment clipping gets really complicated. */
if (gp_interp.depth >= 0.0) {
gl_FragDepth = gp_interp.depth;
if (gp_interp_flat.depth >= 0.0) {
gl_FragDepth = gp_interp_flat.depth;
}
else {
gl_FragDepth = gl_FragCoord.z;

@ -43,10 +43,10 @@ void main()
vert_color,
vert_strength,
gp_interp.uv,
gp_interp.sspos,
gp_interp.aspect,
gp_interp.thickness,
gp_interp.hardness);
gp_interp_flat.sspos,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness,
gp_interp_noperspective.hardness);
if (gpencil_is_stroke_vertex()) {
if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) {
@ -61,17 +61,17 @@ void main()
gpencil_color_output(
gp_mat.stroke_color, vert_color, vert_strength, gp_mat._stroke_texture_mix);
gp_interp.mat_flag = gp_flag & ~GP_FILL_FLAGS;
gp_interp_flat.mat_flag = gp_flag & ~GP_FILL_FLAGS;
if (gpStrokeOrder3d) {
/* Use the fragment depth (see fragment shader). */
gp_interp.depth = -1.0;
gp_interp_flat.depth = -1.0;
}
else if (flag_test(gp_flag, GP_STROKE_OVERLAP)) {
/* Use the index of the point as depth.
* This means the stroke can overlap itself. */
float point_index = float(ma1.z);
gp_interp.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
gp_interp_flat.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
else {
/* Use the index of first point of the stroke as depth.
@ -80,7 +80,7 @@ void main()
* 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. */
float stroke_index = float(ma1.y);
gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
gp_interp_flat.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
}
else {
@ -115,20 +115,20 @@ void main()
gpencil_color_output(fill_col, fcol_decode, 1.0, gp_mat._fill_texture_mix);
gp_interp.mat_flag = gp_flag & GP_FILL_FLAGS;
gp_interp.mat_flag |= uint(ma1.x + gpMaterialOffset) << GPENCIl_MATID_SHIFT;
gp_interp_flat.mat_flag = gp_flag & GP_FILL_FLAGS;
gp_interp_flat.mat_flag |= uint(ma1.x + gpMaterialOffset) << GPENCIl_MATID_SHIFT;
gp_interp.uv = mat2(gp_mat.fill_uv_rot_scale.xy, gp_mat.fill_uv_rot_scale.zw) * uv1.xy +
gp_mat._fill_uv_offset;
if (gpStrokeOrder3d) {
/* Use the fragment depth (see fragment shader). */
gp_interp.depth = -1.0;
gp_interp_flat.depth = -1.0;
}
else {
/* Use the index of first point of the stroke as depth. */
float stroke_index = float(ma1.y);
gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
gp_interp_flat.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
}
}
}

@ -45,10 +45,10 @@ void main()
vert_color,
vert_strength,
gp_interp.uv,
gp_interp.sspos,
gp_interp.aspect,
gp_interp.thickness,
gp_interp.hardness);
gp_interp_flat.sspos,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness,
gp_interp_noperspective.hardness);
if (gpencil_is_stroke_vertex()) {
if (!flag_test(gp_flag, GP_STROKE_ALIGNMENT)) {
@ -63,17 +63,17 @@ void main()
gpencil_color_output(
gp_mat.stroke_color, vert_color, vert_strength, gp_mat._stroke_texture_mix);
gp_interp.mat_flag = gp_flag & ~GP_FILL_FLAGS;
gp_interp_flat.mat_flag = gp_flag & ~GP_FILL_FLAGS;
if (gpStrokeOrder3d) {
/* Use the fragment depth (see fragment shader). */
gp_interp.depth = -1.0;
gp_interp_flat.depth = -1.0;
}
else if (flag_test(gp_flag, GP_STROKE_OVERLAP)) {
/* Use the index of the point as depth.
* This means the stroke can overlap itself. */
float point_index = float(ma1.z);
gp_interp.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
gp_interp_flat.depth = (point_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
else {
/* Use the index of first point of the stroke as depth.
@ -82,7 +82,7 @@ void main()
* 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. */
float stroke_index = float(ma1.y);
gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
gp_interp_flat.depth = (stroke_index + gpStrokeIndexOffset + 2.0) * 0.0000002;
}
}
else {
@ -117,20 +117,20 @@ void main()
gpencil_color_output(fill_col, fcol_decode, 1.0, gp_mat._fill_texture_mix);
gp_interp.mat_flag = gp_flag & GP_FILL_FLAGS;
gp_interp.mat_flag |= uint(ma1.x + gpMaterialOffset) << GPENCIl_MATID_SHIFT;
gp_interp_flat.mat_flag = gp_flag & GP_FILL_FLAGS;
gp_interp_flat.mat_flag |= uint(ma1.x + gpMaterialOffset) << GPENCIl_MATID_SHIFT;
gp_interp.uv = mat2(gp_mat.fill_uv_rot_scale.xy, gp_mat.fill_uv_rot_scale.zw) * uv1.xy +
gp_mat._fill_uv_offset;
if (gpStrokeOrder3d) {
/* Use the fragment depth (see fragment shader). */
gp_interp.depth = -1.0;
gp_interp_flat.depth = -1.0;
}
else {
/* Use the index of first point of the stroke as depth. */
float stroke_index = float(ma1.y);
gp_interp.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
gp_interp_flat.depth = (stroke_index + gpStrokeIndexOffset + 1.0) * 0.0000002;
}
}
}

@ -14,13 +14,15 @@ GPU_SHADER_INTERFACE_INFO(gpencil_geometry_iface, "gp_interp")
.smooth(Type::VEC4, "color_mul")
.smooth(Type::VEC4, "color_add")
.smooth(Type::VEC3, "pos")
.smooth(Type::VEC2, "uv")
.no_perspective(Type::VEC2, "thickness")
.no_perspective(Type::FLOAT, "hardness")
.smooth(Type::VEC2, "uv");
GPU_SHADER_INTERFACE_INFO(gpencil_geometry_flat_iface, "gp_interp_flat")
.flat(Type::VEC2, "aspect")
.flat(Type::VEC4, "sspos")
.flat(Type::UINT, "mat_flag")
.flat(Type::FLOAT, "depth");
GPU_SHADER_INTERFACE_INFO(gpencil_geometry_noperspective_iface, "gp_interp_noperspective")
.no_perspective(Type::VEC2, "thickness")
.no_perspective(Type::FLOAT, "hardness");
GPU_SHADER_CREATE_INFO(gpencil_geometry)
.do_static_compilation(true)
@ -45,6 +47,8 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry)
.fragment_out(0, Type::VEC4, "fragColor")
.fragment_out(1, Type::VEC4, "revealColor")
.vertex_out(gpencil_geometry_iface)
.vertex_out(gpencil_geometry_flat_iface)
.vertex_out(gpencil_geometry_noperspective_iface)
.vertex_source("gpencil_vert.glsl")
.fragment_source("gpencil_frag.glsl")
.depth_write(DepthWrite::ANY)
@ -78,6 +82,8 @@ GPU_SHADER_CREATE_INFO(gpencil_geometry_next)
.fragment_out(0, Type::VEC4, "fragColor")
.fragment_out(1, Type::VEC4, "revealColor")
.vertex_out(gpencil_geometry_iface)
.vertex_out(gpencil_geometry_flat_iface)
.vertex_out(gpencil_geometry_noperspective_iface)
.vertex_source("grease_pencil_vert.glsl")
.fragment_source("gpencil_frag.glsl")
.additional_info("draw_gpencil_new")

@ -66,9 +66,11 @@ GPU_SHADER_CREATE_INFO(overlay_outline_prepass_wire_clipped)
.do_static_compilation(true)
.additional_info("overlay_outline_prepass_wire", "drw_clipped");
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_gpencil_iface, "gp_interp")
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_gpencil_noperspective_iface,
"gp_interp_noperspective")
.no_perspective(Type::VEC2, "thickness")
.no_perspective(Type::FLOAT, "hardness")
.no_perspective(Type::FLOAT, "hardness");
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_gpencil_flat_iface, "gp_interp_flat")
.flat(Type::VEC2, "aspect")
.flat(Type::VEC4, "sspos");
@ -76,7 +78,8 @@ GPU_SHADER_CREATE_INFO(overlay_outline_prepass_gpencil)
.do_static_compilation(true)
.push_constant(Type::BOOL, "isTransform")
.vertex_out(overlay_outline_prepass_iface)
.vertex_out(overlay_outline_prepass_gpencil_iface)
.vertex_out(overlay_outline_prepass_gpencil_flat_iface)
.vertex_out(overlay_outline_prepass_gpencil_noperspective_iface)
.vertex_source("overlay_outline_prepass_gpencil_vert.glsl")
.push_constant(Type::BOOL, "gpStrokeOrder3d") /* TODO(fclem): Move to a GPencil object UBO. */
.push_constant(Type::VEC4, "gpDepthPlane") /* TODO(fclem): Move to a GPencil object UBO. */

@ -12,11 +12,11 @@ vec3 ray_plane_intersection(vec3 ray_ori, vec3 ray_dir, vec4 plane)
void main()
{
if (gpencil_stroke_round_cap_mask(gp_interp.sspos.xy,
gp_interp.sspos.zw,
gp_interp.aspect,
gp_interp.thickness.x,
gp_interp.hardness) < 0.001)
if (gpencil_stroke_round_cap_mask(gp_interp_flat.sspos.xy,
gp_interp_flat.sspos.zw,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness.x,
gp_interp_noperspective.hardness) < 0.001)
{
discard;
return;

@ -40,10 +40,10 @@ void main()
unused_color,
unused_strength,
unused_uv,
gp_interp.sspos,
gp_interp.aspect,
gp_interp.thickness,
gp_interp.hardness);
gp_interp_flat.sspos,
gp_interp_flat.aspect,
gp_interp_noperspective.thickness,
gp_interp_noperspective.hardness);
/* Small bias to always be on top of the geom. */
gl_Position.z -= 1e-3;