GPv3: Outline prepass #118052
|
@ -828,6 +828,8 @@ set(GLSL_SRC
|
|||
engines/overlay/shaders/overlay_outline_prepass_geom.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_gpencil_frag.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_gpencil_vert.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_grease_pencil_frag.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_grease_pencil_vert.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_pointcloud_vert.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_vert.glsl
|
||||
engines/overlay/shaders/overlay_outline_prepass_vert_no_geom.glsl
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* \ingroup draw_engine
|
||||
*/
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
#include "DRW_render.hh"
|
||||
|
@ -273,6 +274,36 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
|
|||
pd->cfra);
|
||||
}
|
||||
|
||||
static void OVERLAY_outline_grease_pencil(OVERLAY_PrivateData *pd, const Scene *scene, Object *ob)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::draw;
|
||||
GPUBatch *geom = DRW_cache_grease_pencil_get(scene, ob);
|
||||
if (geom == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float object_scale = math::length(
|
||||
math::transform_point(float4x4(ob->object_to_world), float3(1.0f, 0.0f, 0.0f)));
|
||||
|
||||
DRWShadingGroup *shgroup = pd->outlines_gpencil_grp;
|
||||
DRWShadingGroup *grp = DRW_shgroup_create_sub(shgroup);
|
||||
|
||||
GPUVertBuf *position_tx = DRW_cache_grease_pencil_position_buffer_get(scene, ob);
|
||||
GPUVertBuf *color_tx = DRW_cache_grease_pencil_color_buffer_get(scene, ob);
|
||||
|
||||
DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", false);
|
||||
DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", object_scale);
|
||||
DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", 0.0f);
|
||||
DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", 1.0f);
|
||||
DRW_shgroup_uniform_vec4_copy(grp, "gpDepthPlane", float4(1.0f));
|
||||
|
||||
DRW_shgroup_buffer_texture(grp, "gp_pos_tx", position_tx);
|
||||
DRW_shgroup_buffer_texture(grp, "gp_col_tx", color_tx);
|
||||
|
||||
DRW_shgroup_call(grp, geom, ob);
|
||||
}
|
||||
|
||||
static void OVERLAY_outline_volume(OVERLAY_PrivateData *pd, Object *ob)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
|
@ -326,6 +357,11 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
|
|||
return;
|
||||
}
|
||||
|
||||
if (ob->type == OB_GREASE_PENCIL) {
|
||||
OVERLAY_outline_grease_pencil(pd, draw_ctx->scene, ob);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ob->type == OB_VOLUME) {
|
||||
OVERLAY_outline_volume(pd, ob);
|
||||
return;
|
||||
|
|
|
@ -720,9 +720,18 @@ GPUShader *OVERLAY_shader_outline_prepass_gpencil()
|
|||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
|
||||
if (!sh_data->outline_prepass_gpencil) {
|
||||
sh_data->outline_prepass_gpencil = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_outline_prepass_gpencil_clipped" :
|
||||
"overlay_outline_prepass_gpencil");
|
||||
if (U.experimental.use_grease_pencil_version3) {
|
||||
sh_data->outline_prepass_gpencil = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ?
|
||||
"overlay_outline_prepass_grease_pencil_clipped" :
|
||||
"overlay_outline_prepass_grease_pencil");
|
||||
}
|
||||
else {
|
||||
sh_data->outline_prepass_gpencil = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ?
|
||||
"overlay_outline_prepass_gpencil_clipped" :
|
||||
"overlay_outline_prepass_gpencil");
|
||||
}
|
||||
}
|
||||
return sh_data->outline_prepass_gpencil;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,33 @@ GPU_SHADER_CREATE_INFO(overlay_outline_prepass_gpencil_clipped)
|
|||
.do_static_compilation(true)
|
||||
.additional_info("overlay_outline_prepass_gpencil", "drw_clipped");
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_grease_pencil_flat_iface, "gp_interp_flat")
|
||||
.flat(Type::VEC2, "aspect")
|
||||
.flat(Type::VEC4, "sspos");
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_grease_pencil_noperspective_iface,
|
||||
"gp_interp_noperspective")
|
||||
.no_perspective(Type::VEC2, "thickness")
|
||||
.no_perspective(Type::FLOAT, "hardness");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_outline_prepass_grease_pencil)
|
||||
.do_static_compilation(true)
|
||||
.push_constant(Type::BOOL, "isTransform")
|
||||
.vertex_out(overlay_outline_prepass_iface)
|
||||
.vertex_out(overlay_outline_prepass_grease_pencil_flat_iface)
|
||||
.vertex_out(overlay_outline_prepass_grease_pencil_noperspective_iface)
|
||||
.vertex_source("overlay_outline_prepass_grease_pencil_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. */
|
||||
/* Using uint because 16bit uint can contain more ids than int. */
|
||||
.fragment_out(0, Type::UINT, "out_object_id")
|
||||
.fragment_source("overlay_outline_prepass_grease_pencil_frag.glsl")
|
||||
.depth_write(DepthWrite::ANY)
|
||||
.additional_info("draw_gpencil_new", "draw_resource_handle", "draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_outline_prepass_grease_pencil_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_outline_prepass_grease_pencil", "drw_clipped");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_outline_prepass_pointcloud)
|
||||
.do_static_compilation(true)
|
||||
.vertex_source("overlay_outline_prepass_pointcloud_vert.glsl")
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* SPDX-FileCopyrightText: 2018-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_grease_pencil_lib.glsl)
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (!gpStrokeOrder3d) {
|
||||
/* Stroke order 2D. Project to gpDepthPlane. */
|
||||
bool is_persp = drw_view.winmat[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 = drw_view.viewinv * (drw_view.wininv * vec4(pos_ndc, 1.0));
|
||||
vec3 pos = pos_world.xyz / pos_world.w;
|
||||
|
||||
vec3 ray_ori = pos;
|
||||
vec3 ray_dir = (is_persp) ? (drw_view.viewinv[3].xyz - pos) : drw_view.viewinv[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;
|
||||
}
|
||||
|
||||
out_object_id = interp.ob_id;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* SPDX-FileCopyrightText: 2022-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_grease_pencil_lib.glsl)
|
||||
|
||||
uint outline_colorid_get(void)
|
||||
{
|
||||
int flag = int(abs(ObjectInfo.w));
|
||||
bool is_active = (flag & DRW_BASE_ACTIVE) != 0;
|
||||
|
||||
if (isTransform) {
|
||||
return 0u; /* colorTransform */
|
||||
}
|
||||
else if (is_active) {
|
||||
return 3u; /* colorActive */
|
||||
}
|
||||
else {
|
||||
return 1u; /* colorSelect */
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
/* Replace top 2 bits (of the 16bit output) by outlineId.
|
||||
* This leaves 16K different IDs to create outlines between objects.
|
||||
* SHIFT = (32 - (16 - 2)) */
|
||||
#define SHIFT 18u
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 world_pos;
|
||||
vec3 unused_N;
|
||||
vec4 unused_color;
|
||||
float unused_strength;
|
||||
vec2 unused_uv;
|
||||
|
||||
gl_Position = gpencil_vertex(vec4(sizeViewport, sizeViewportInv),
|
||||
world_pos,
|
||||
unused_N,
|
||||
unused_color,
|
||||
unused_strength,
|
||||
unused_uv,
|
||||
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;
|
||||
|
||||
/* ID 0 is nothing (background) */
|
||||
interp.ob_id = uint(resource_handle + 1);
|
||||
|
||||
/* Should be 2 bits only [0..3]. */
|
||||
uint outline_id = outline_colorid_get();
|
||||
|
||||
/* Combine for 16bit uint target. */
|
||||
interp.ob_id = (outline_id << 14u) | ((interp.ob_id << SHIFT) >> SHIFT);
|
||||
|
||||
view_clipping_distances(world_pos);
|
||||
}
|
|
@ -385,7 +385,7 @@ vec4 gpencil_vertex(vec4 viewport_size,
|
|||
out float out_hardness)
|
||||
{
|
||||
return gpencil_vertex(viewport_size,
|
||||
0u,
|
||||
(GP_SHOW_STROKE | GP_SHOW_FILL),
|
||||
vec2(1.0, 0.0),
|
||||
out_P,
|
||||
out_N,
|
||||
|
|
Loading…
Reference in New Issue