This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/intern/shaders/common_subdiv_lib.glsl
Brecht Van Lommel 549cc568b0 Fix various issues with modifiers and edge display in edit mode
Consistently use edge draw flag instead of original index to determine if an
edge should be drawn or not.

In GPU subdivision the edge original index was used for both edge optimal
display and selection mapping to coarse edges, but they are not the same.
Now match the CPU subdivision logic and use a separate edge draw flag VBO.

For cage display, match Blender 3.3 behavior more in showing/hiding of edges
in wireframe mode. That is edges without a mapping to an original edge are
always hidden when there is no distinct cage, and drawn otherwise. This is
not ideal for e.g. the bevel modifier where it will always show some edges on
corners despite all edges being hidden by the user. But we currently have
no good information to decide if these should be hidden or not, so err on
the side of showing too much as it did before.

Fie #103706: bevel modifier edges not drawn correctly
Fix #103700: optimal display can't be turned of with GPU subdivision
Fix wrong edge display with GPU subdivision preceded by other modifiers

Pull Request #105384
2023-03-03 16:38:27 +01:00

200 lines
4.8 KiB
GLSL

layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
/* Uniform block for #DRWSubivUboStorage. */
layout(std140) uniform shader_data
{
/* Offsets in the buffers data where the source and destination data start. */
int src_offset;
int dst_offset;
/* Parameters for the DRWPatchMap. */
int min_patch_face;
int max_patch_face;
int max_depth;
int patches_are_triangular;
/* Coarse topology information. */
int coarse_poly_count;
uint edge_loose_offset;
/* Subdiv topology information. */
uint num_subdiv_loops;
/* Sculpt data. */
bool has_sculpt_mask;
/* Masks for the extra coarse face data. */
uint coarse_face_select_mask;
uint coarse_face_smooth_mask;
uint coarse_face_active_mask;
uint coarse_face_hidden_mask;
uint coarse_face_loopstart_mask;
/* Total number of elements to process. */
uint total_dispatch_size;
bool is_edit_mode;
bool use_hide;
};
uint get_global_invocation_index()
{
uint invocations_per_row = gl_WorkGroupSize.x * gl_NumWorkGroups.x;
return gl_GlobalInvocationID.x + gl_GlobalInvocationID.y * invocations_per_row;
}
/* Structure for #CompressedPatchCoord. */
struct BlenderPatchCoord {
int patch_index;
uint encoded_uv;
};
vec2 decode_uv(uint encoded_uv)
{
float u = float((encoded_uv >> 16) & 0xFFFFu) / 65535.0;
float v = float(encoded_uv & 0xFFFFu) / 65535.0;
return vec2(u, v);
}
/* This structure is a carbon copy of OpenSubDiv's PatchTable::PatchHandle. */
struct PatchHandle {
int array_index;
int patch_index;
int vertex_index;
};
/* This structure is a carbon copy of OpenSubDiv's PatchCoord. */
struct PatchCoord {
int array_index;
int patch_index;
int vertex_index;
float u;
float v;
};
/* This structure is a carbon copy of OpenSubDiv's PatchCoord.QuadNode.
* Each child is a bitfield. */
struct QuadNode {
uvec4 child;
};
bool is_set(uint i)
{
/* QuadNode.Child.isSet is the first bit of the bitfield. */
return (i & 0x1u) != 0;
}
bool is_leaf(uint i)
{
/* QuadNode.Child.isLeaf is the second bit of the bitfield. */
return (i & 0x2u) != 0;
}
uint get_index(uint i)
{
/* QuadNode.Child.index is made of the remaining bits. */
return (i >> 2) & 0x3FFFFFFFu;
}
/* Duplicate of #PosNorLoop from the mesh extract CPU code.
* We do not use a vec3 for the position as it will be padded to a vec4 which is incompatible with
* the format. */
struct PosNorLoop {
float x, y, z;
/* TODO(@kevindietrich): figure how to compress properly as GLSL does not have char/short types,
* bit operations get tricky. */
float nx, ny, nz;
float flag;
};
struct LoopNormal {
float nx, ny, nz, flag;
};
vec3 get_vertex_pos(PosNorLoop vertex_data)
{
return vec3(vertex_data.x, vertex_data.y, vertex_data.z);
}
vec3 get_vertex_nor(PosNorLoop vertex_data)
{
return vec3(vertex_data.nx, vertex_data.ny, vertex_data.nz);
}
LoopNormal get_normal_and_flag(PosNorLoop vertex_data)
{
LoopNormal loop_nor;
loop_nor.nx = vertex_data.nx;
loop_nor.ny = vertex_data.ny;
loop_nor.nz = vertex_data.nz;
loop_nor.flag = vertex_data.flag;
return loop_nor;
}
void set_vertex_pos(inout PosNorLoop vertex_data, vec3 pos)
{
vertex_data.x = pos.x;
vertex_data.y = pos.y;
vertex_data.z = pos.z;
}
/* Set the vertex normal but preserve the existing flag. This is for when we compute manually the
* vertex normals when we cannot use the limit surface, in which case the flag and the normal are
* set by two separate compute pass. */
void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor)
{
vertex_data.nx = nor.x;
vertex_data.ny = nor.y;
vertex_data.nz = nor.z;
}
void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor, float flag)
{
set_vertex_nor(vertex_data, nor);
vertex_data.flag = flag;
}
void add_newell_cross_v3_v3v3(inout vec3 n, vec3 v_prev, vec3 v_curr)
{
n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]);
n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]);
n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
}
#define ORIGINDEX_NONE -1
#ifdef SUBDIV_POLYGON_OFFSET
layout(std430, binding = 0) readonly buffer inputSubdivPolygonOffset
{
uint subdiv_polygon_offset[];
};
/* Given the index of the subdivision quad, return the index of the corresponding coarse polygon.
* This uses subdiv_polygon_offset and since it is a growing list of offsets, we can use binary
* search to locate the right index. */
uint coarse_polygon_index_from_subdiv_quad_index(uint subdiv_quad_index, uint coarse_poly_count)
{
uint first = 0;
uint last = coarse_poly_count;
while (first != last) {
uint middle = (first + last) / 2;
if (subdiv_polygon_offset[middle] < subdiv_quad_index) {
first = middle + 1;
}
else {
last = middle;
}
}
if (subdiv_polygon_offset[first] == subdiv_quad_index) {
return first;
}
return first - 1;
}
#endif