Wireframe: Add workaround for osx wide wires
This commit is contained in:
@@ -32,6 +32,9 @@
|
||||
#include "GPU_shader.h"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define USE_GEOM_SHADER_WORKAROUND
|
||||
#endif
|
||||
|
||||
/* Structures */
|
||||
typedef struct OVERLAY_StorageList {
|
||||
@@ -54,7 +57,6 @@ typedef struct OVERLAY_Data {
|
||||
typedef struct OVERLAY_PrivateData {
|
||||
DRWShadingGroup *face_orientation_shgrp;
|
||||
DRWShadingGroup *face_wires_shgrp;
|
||||
DRWShadingGroup *sculpt_wires_shgrp;
|
||||
View3DOverlay overlay;
|
||||
float wire_step_param;
|
||||
bool ghost_stencil_test;
|
||||
@@ -67,7 +69,6 @@ typedef struct OVERLAY_Shaders {
|
||||
/* Wireframe shader */
|
||||
struct GPUShader *select_wireframe;
|
||||
struct GPUShader *face_wireframe;
|
||||
struct GPUShader *face_wireframe_sculpt;
|
||||
} OVERLAY_Shaders;
|
||||
|
||||
/* *********** STATIC *********** */
|
||||
@@ -121,16 +122,21 @@ static void overlay_engine_init(void *vedata)
|
||||
.frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL},
|
||||
});
|
||||
#ifdef USE_GEOM_SHADER_WORKAROUND
|
||||
/* Apple drivers does not support wide wires. Use geometry shader as a workaround. */
|
||||
sh_data->face_wireframe = GPU_shader_create_from_arrays({
|
||||
.vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
|
||||
.geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL},
|
||||
.frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL},
|
||||
});
|
||||
#else
|
||||
sh_data->face_wireframe = GPU_shader_create_from_arrays({
|
||||
.vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
|
||||
.frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, NULL},
|
||||
});
|
||||
sh_data->face_wireframe_sculpt = GPU_shader_create_from_arrays({
|
||||
.vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
|
||||
.frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, NULL},
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +185,9 @@ static void overlay_cache_init(void *vedata)
|
||||
|
||||
{
|
||||
/* Wireframe */
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE;
|
||||
float wire_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
|
||||
DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE;
|
||||
float wire_size = U.pixelsize * 0.5f;
|
||||
|
||||
float winmat[4][4];
|
||||
float viewdist = rv3d->dist;
|
||||
@@ -192,28 +199,26 @@ static void overlay_cache_init(void *vedata)
|
||||
const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f);
|
||||
|
||||
const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
|
||||
GPUShader *sculpt_wire_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe_sculpt;
|
||||
GPUShader *face_wires_sh = use_select ? sh_data->select_wireframe : sh_data->face_wireframe;
|
||||
|
||||
psl->face_wireframe_pass = DRW_pass_create("Face Wires", state);
|
||||
|
||||
g_data->sculpt_wires_shgrp = DRW_shgroup_create(sculpt_wire_sh, psl->face_wireframe_pass);
|
||||
if (rv3d->rflag & RV3D_CLIPPING) {
|
||||
DRW_shgroup_world_clip_planes_from_rv3d(g_data->sculpt_wires_shgrp, rv3d);
|
||||
}
|
||||
|
||||
g_data->face_wires_shgrp = DRW_shgroup_create(face_wires_sh, psl->face_wireframe_pass);
|
||||
DRW_shgroup_uniform_float(g_data->face_wires_shgrp, "wireStepParam", &g_data->wire_step_param, 1);
|
||||
DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "ofs", depth_ofs);
|
||||
#ifdef USE_GEOM_SHADER_WORKAROUND
|
||||
DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size);
|
||||
DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
DRW_shgroup_uniform_vec2(g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
|
||||
#else
|
||||
if (!use_select) {
|
||||
DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size);
|
||||
}
|
||||
#endif
|
||||
if (rv3d->rflag & RV3D_CLIPPING) {
|
||||
DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d);
|
||||
}
|
||||
|
||||
if (!use_select) {
|
||||
DRW_shgroup_uniform_float_copy(g_data->sculpt_wires_shgrp, "wireSize", wire_size);
|
||||
DRW_shgroup_uniform_float_copy(g_data->face_wires_shgrp, "wireSize", wire_size);
|
||||
}
|
||||
|
||||
g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f;
|
||||
}
|
||||
}
|
||||
@@ -312,13 +317,13 @@ static void overlay_cache_populate(void *vedata, Object *ob)
|
||||
geom = DRW_cache_object_face_wireframe_get(ob);
|
||||
|
||||
if (geom || is_sculpt_mode) {
|
||||
shgrp = (is_sculpt_mode) ? pd->sculpt_wires_shgrp : pd->face_wires_shgrp;
|
||||
shgrp = DRW_shgroup_create_sub(shgrp);
|
||||
shgrp = DRW_shgroup_create_sub(pd->face_wires_shgrp);
|
||||
|
||||
static float all_wires_param = 10.0f;
|
||||
DRW_shgroup_uniform_vec2(
|
||||
shgrp, "wireStepParam", (all_wires) ?
|
||||
&all_wires_param : &pd->wire_step_param, 1);
|
||||
DRW_shgroup_uniform_float(
|
||||
shgrp, "wireStepParam",
|
||||
(all_wires || is_sculpt_mode) ? &all_wires_param : &pd->wire_step_param,
|
||||
1);
|
||||
|
||||
if (!(DRW_state_is_select() || DRW_state_is_depth())) {
|
||||
DRW_shgroup_stencil_mask(shgrp, stencil_mask);
|
||||
|
||||
@@ -1,85 +1,60 @@
|
||||
|
||||
/* This shader is only used for edge selection & sculpt mode wires (because of indexed drawing). */
|
||||
/* This shader is only used for edge selection and OSX workaround for large wires. */
|
||||
|
||||
layout(triangles) in;
|
||||
#ifdef SELECT_EDGES
|
||||
layout(line_strip, max_vertices = 6) out;
|
||||
#else
|
||||
layout(triangle_strip, max_vertices = 3) out;
|
||||
#endif
|
||||
uniform float wireSize;
|
||||
uniform vec2 viewportSize;
|
||||
uniform vec2 viewportSizeInv;
|
||||
|
||||
layout(lines) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
in float facing_g[];
|
||||
in float edgeSharpness_g[];
|
||||
|
||||
#ifndef SELECT_EDGES
|
||||
out float facing;
|
||||
out vec3 barycentric;
|
||||
flat out vec3 edgeSharpness;
|
||||
flat out float edgeSharpness;
|
||||
#endif
|
||||
|
||||
void vert_from_gl_in(int v)
|
||||
void do_vertex(const int i, float coord, vec2 offset)
|
||||
{
|
||||
gl_Position = gl_in[v].gl_Position;
|
||||
#ifndef SELECT_EDGES
|
||||
edgeSharpness = edgeSharpness_g[i];
|
||||
facing = facing_g[i];
|
||||
#endif
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
/* Multiply offset by 2 because gl_Position range is [-1..1]. */
|
||||
gl_Position.xy += offset * 2.0 * gl_Position.w;
|
||||
#ifdef USE_WORLD_CLIP_PLANES
|
||||
world_clip_planes_set_clip_distance(gl_in[v].gl_ClipDistance);
|
||||
world_clip_planes_set_clip_distance(gl_in[i].gl_ClipDistance);
|
||||
#endif
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
void main(void)
|
||||
void main()
|
||||
{
|
||||
#ifdef SELECT_EDGES
|
||||
const float edge_select_threshold = 0.3;
|
||||
if (edgeSharpness_g[0] > edge_select_threshold) {
|
||||
vert_from_gl_in(0);
|
||||
EmitVertex();
|
||||
vert_from_gl_in(1);
|
||||
EmitVertex();
|
||||
vec2 ss_pos[2];
|
||||
ss_pos[0] = gl_in[0].gl_Position.xy / gl_in[0].gl_Position.w;
|
||||
ss_pos[1] = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w;
|
||||
|
||||
EndPrimitive();
|
||||
vec2 line = ss_pos[0] - ss_pos[1];
|
||||
line = abs(line) * viewportSize;
|
||||
|
||||
float half_size = wireSize;
|
||||
|
||||
vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0);
|
||||
|
||||
bool horizontal = line.x > line.y;
|
||||
edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz;
|
||||
|
||||
if (edgeSharpness_g[0] < 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (edgeSharpness_g[1] > edge_select_threshold) {
|
||||
vert_from_gl_in(1);
|
||||
EmitVertex();
|
||||
vert_from_gl_in(2);
|
||||
EmitVertex();
|
||||
do_vertex(0, half_size, edge_ofs.xy);
|
||||
do_vertex(0, -half_size, -edge_ofs.xy);
|
||||
do_vertex(1, half_size, edge_ofs.xy);
|
||||
do_vertex(1, -half_size, -edge_ofs.xy);
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
if (edgeSharpness_g[2] > edge_select_threshold) {
|
||||
vert_from_gl_in(2);
|
||||
EmitVertex();
|
||||
vert_from_gl_in(0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
#else
|
||||
/* Originally was:
|
||||
* edgeSharpness = vec3(edgeSharpness_g[0], edgeSharpness_g[1], edgeSharpness_g[2]);
|
||||
*
|
||||
* But that strangely does not work for some AMD GPUs.
|
||||
* However since this code is currently only used for sculpt mode
|
||||
* and in this mode the `edgeSharpness_g` is not calculated,
|
||||
* let's simply set all to 1.0.
|
||||
*/
|
||||
edgeSharpness = vec3(1.0);
|
||||
|
||||
barycentric = vec3(1.0, 0.0, 0.0);
|
||||
vert_from_gl_in(0);
|
||||
facing = facing_g[0];
|
||||
EmitVertex();
|
||||
|
||||
barycentric = vec3(0.0, 1.0, 0.0);
|
||||
vert_from_gl_in(1);
|
||||
facing = facing_g[1];
|
||||
EmitVertex();
|
||||
|
||||
barycentric = vec3(0.0, 0.0, 1.0);
|
||||
vert_from_gl_in(2);
|
||||
facing = facing_g[2];
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
#endif /* SELECT_EDGES */
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@ uniform mat3 NormalMatrix;
|
||||
uniform float wireStepParam;
|
||||
uniform float ofs;
|
||||
|
||||
#ifndef USE_SCULPT
|
||||
float get_edge_sharpness(float wd)
|
||||
{
|
||||
return (wd == 1.0) ? 1.0 : ((wd == 0.0) ? -1.0 : (wd + wireStepParam));
|
||||
}
|
||||
#else
|
||||
float get_edge_sharpness(float wd) { return 1.0; }
|
||||
#endif
|
||||
|
||||
/* Geometry shader version */
|
||||
#if defined(SELECT_EDGES) || defined(USE_SCULPT)
|
||||
#if defined(SELECT_EDGES) || defined(USE_GEOM)
|
||||
|
||||
in vec3 pos;
|
||||
in vec3 nor;
|
||||
@@ -24,12 +28,7 @@ out float edgeSharpness_g;
|
||||
|
||||
void main()
|
||||
{
|
||||
# ifndef USE_SCULPT
|
||||
edgeSharpness_g = get_edge_sharpness(wd);
|
||||
# else
|
||||
/* TODO approximation using normals. */
|
||||
edgeSharpness_g = 1.0;
|
||||
# endif
|
||||
|
||||
mat4 projmat = ProjectionMatrix;
|
||||
projmat[3][2] -= ofs;
|
||||
@@ -43,7 +42,7 @@ void main()
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* SELECT_EDGES */
|
||||
#else /* USE_GEOM */
|
||||
|
||||
in vec3 pos;
|
||||
in vec3 nor;
|
||||
|
||||
Reference in New Issue
Block a user