diff options
Diffstat (limited to 'source/blender/draw/intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl')
-rw-r--r-- | source/blender/draw/intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/source/blender/draw/intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl new file mode 100644 index 00000000000..ea73b9482d3 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_subdiv_vbo_edituv_strech_angle_comp.glsl @@ -0,0 +1,80 @@ + +/* To be compile with common_subdiv_lib.glsl */ + +layout(std430, binding = 0) readonly buffer inputVerts +{ + PosNorLoop pos_nor[]; +}; + +layout(std430, binding = 1) readonly buffer inputUVs +{ + vec2 uvs[]; +}; + +/* Mirror of #UVStretchAngle in the C++ code, but using floats until proper data compression + * is implemented for all subdivision data. */ +struct UVStretchAngle { + float angle; + float uv_angle0; + float uv_angle1; +}; + +layout(std430, binding = 2) writeonly buffer outputStretchAngles +{ + UVStretchAngle uv_stretches[]; +}; + +#define M_PI 3.1415926535897932 +#define M_1_PI 0.31830988618379067154 + +/* Adapted from BLI_math_vector.h */ +float angle_normalized_v3v3(vec3 v1, vec3 v2) +{ + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + bool q = (dot(v1, v2) >= 0.0); + vec3 v = (q) ? (v1 - v2) : (v1 + v2); + float a = 2.0 * asin(length(v) / 2.0); + return (q) ? a : M_PI - a; +} + +void main() +{ + /* We execute for each quad. */ + uint quad_index = get_global_invocation_index(); + if (quad_index >= total_dispatch_size) { + return; + } + + uint start_loop_index = quad_index * 4; + + for (uint i = 0; i < 4; i++) { + uint cur_loop_index = start_loop_index + i; + uint next_loop_index = start_loop_index + (i + 1) % 4; + uint prev_loop_index = start_loop_index + (i + 3) % 4; + + /* Compute 2d edge vectors from UVs. */ + vec2 cur_uv = uvs[src_offset + cur_loop_index]; + vec2 next_uv = uvs[src_offset + next_loop_index]; + vec2 prev_uv = uvs[src_offset + prev_loop_index]; + + vec2 norm_uv_edge0 = normalize(prev_uv - cur_uv); + vec2 norm_uv_edge1 = normalize(cur_uv - next_uv); + + /* Compute 3d edge vectors from positions. */ + vec3 cur_pos = get_vertex_pos(pos_nor[cur_loop_index]); + vec3 next_pos = get_vertex_pos(pos_nor[next_loop_index]); + vec3 prev_pos = get_vertex_pos(pos_nor[prev_loop_index]); + + vec3 norm_pos_edge0 = normalize(prev_pos - cur_pos); + vec3 norm_pos_edge1 = normalize(cur_pos - next_pos); + + /* Compute stretches, this logic is adapted from #edituv_get_edituv_stretch_angle. + * Keep in sync! */ + UVStretchAngle stretch; + stretch.uv_angle0 = atan(norm_uv_edge0.y, norm_uv_edge0.x) * M_1_PI; + stretch.uv_angle1 = atan(norm_uv_edge1.y, norm_uv_edge1.x) * M_1_PI; + stretch.angle = angle_normalized_v3v3(norm_pos_edge0, norm_pos_edge1) * M_1_PI; + + uv_stretches[cur_loop_index] = stretch; + } +} |