This changes `ouput` to `output`. Pull Request: https://projects.blender.org/blender/blender/pulls/139711
217 lines
6.9 KiB
GLSL
217 lines
6.9 KiB
GLSL
/* SPDX-FileCopyrightText: 2020-2022 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "infos/gpu_shader_3D_polyline_info.hh"
|
|
|
|
#include "gpu_shader_attribute_load_lib.glsl"
|
|
#include "gpu_shader_index_load_lib.glsl"
|
|
#include "gpu_shader_math_base_lib.glsl"
|
|
#include "gpu_shader_utildefines_lib.glsl"
|
|
|
|
VERTEX_SHADER_CREATE_INFO(gpu_shader_3D_polyline_flat_color)
|
|
|
|
struct VertIn {
|
|
float3 ls_P;
|
|
float4 final_color;
|
|
};
|
|
|
|
VertIn input_assembly(uint in_vertex_id)
|
|
{
|
|
uint v_i = gpu_index_load(in_vertex_id);
|
|
uint ofs = uint(gpu_vert_stride_count_offset.z);
|
|
|
|
VertIn vert_in;
|
|
vert_in.ls_P = float3(0.0f, 0.0f, 0.0f);
|
|
/* Need to support 1, 2 and 3 dimensional input (sigh). */
|
|
vert_in.ls_P.x = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 0 + ofs];
|
|
if (gpu_attr_0_len >= 2) {
|
|
vert_in.ls_P.y = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 1 + ofs];
|
|
}
|
|
if (gpu_attr_0_len >= 3) {
|
|
vert_in.ls_P.z = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 2 + ofs];
|
|
}
|
|
|
|
if (gpu_attr_0_fetch_int) {
|
|
vert_in.ls_P = float3(floatBitsToInt(vert_in.ls_P));
|
|
}
|
|
#ifndef UNIFORM
|
|
vert_in.final_color = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
/* Need to support 1, 2, 3 and 4 dimensional input (sigh). */
|
|
vert_in.final_color.x = color[gpu_attr_load_index(v_i, gpu_attr_1) + 0 + ofs];
|
|
if (gpu_attr_1_fetch_unorm8) {
|
|
vert_in.final_color = unpackUnorm4x8(floatBitsToUint(vert_in.final_color.x));
|
|
}
|
|
else {
|
|
if (gpu_attr_1_len >= 2) {
|
|
vert_in.final_color.y = color[gpu_attr_load_index(v_i, gpu_attr_1) + 1 + ofs];
|
|
}
|
|
if (gpu_attr_1_len >= 3) {
|
|
vert_in.final_color.z = color[gpu_attr_load_index(v_i, gpu_attr_1) + 2 + ofs];
|
|
}
|
|
if (gpu_attr_1_len >= 4) {
|
|
vert_in.final_color.w = color[gpu_attr_load_index(v_i, gpu_attr_1) + 3 + ofs];
|
|
}
|
|
}
|
|
#endif
|
|
return vert_in;
|
|
}
|
|
|
|
struct VertOut {
|
|
float4 gpu_position;
|
|
float4 final_color;
|
|
float clip;
|
|
};
|
|
|
|
VertOut vertex_main(VertIn vert_in)
|
|
{
|
|
VertOut vert_out;
|
|
vert_out.gpu_position = ModelViewProjectionMatrix * float4(vert_in.ls_P, 1.0f);
|
|
#ifndef UNIFORM
|
|
vert_out.final_color = vert_in.final_color;
|
|
#endif
|
|
#ifdef CLIP
|
|
vert_out.clip = dot(ModelMatrix * float4(vert_in.ls_P, 1.0f), ClipPlane);
|
|
#endif
|
|
return vert_out;
|
|
}
|
|
|
|
/* Clips point to near clip plane before perspective divide. */
|
|
float4 clip_line_point_homogeneous_space(float4 p, float4 q)
|
|
{
|
|
if (p.z < -p.w) {
|
|
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0f. */
|
|
float denom = q.z - p.z + q.w - p.w;
|
|
if (denom == 0.0f) {
|
|
/* No solution. */
|
|
return p;
|
|
}
|
|
float A = (-p.z - p.w) / denom;
|
|
p = p + (q - p) * A;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
struct GeomOut {
|
|
float4 gpu_position;
|
|
float4 final_color;
|
|
float clip;
|
|
float smoothline;
|
|
};
|
|
|
|
void export_vertex(GeomOut geom_out)
|
|
{
|
|
gl_Position = geom_out.gpu_position;
|
|
final_color = geom_out.final_color;
|
|
smoothline = geom_out.smoothline;
|
|
clip = geom_out.clip;
|
|
}
|
|
|
|
void strip_EmitVertex(const uint strip_index,
|
|
uint out_vertex_id,
|
|
uint out_primitive_id,
|
|
GeomOut geom_out)
|
|
{
|
|
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
|
/* Maps triangle list primitives to triangle strip indices. */
|
|
uint out_strip_index = (is_odd_primitive ? (2u - out_vertex_id) : out_vertex_id) +
|
|
out_primitive_id;
|
|
|
|
if (out_strip_index == strip_index) {
|
|
export_vertex(geom_out);
|
|
}
|
|
}
|
|
|
|
void do_vertex(const uint i,
|
|
uint out_vertex_id,
|
|
uint out_primitive_id,
|
|
VertOut geom_in[2],
|
|
float4 position,
|
|
float2 ofs)
|
|
{
|
|
GeomOut geom_out;
|
|
#if defined(UNIFORM)
|
|
geom_out.final_color = color;
|
|
|
|
#elif defined(FLAT)
|
|
/* WATCH: Assuming last provoking vertex. */
|
|
geom_out.final_color = geom_in[1].final_color;
|
|
|
|
#elif defined(SMOOTH)
|
|
geom_out.final_color = geom_in[i].final_color;
|
|
#endif
|
|
|
|
#ifdef CLIP
|
|
geom_out.clip = geom_in[i].clip;
|
|
#endif
|
|
|
|
geom_out.smoothline = (lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5f;
|
|
geom_out.gpu_position = position;
|
|
geom_out.gpu_position.xy += ofs * position.w;
|
|
strip_EmitVertex(i * 2u + 0u, out_vertex_id, out_primitive_id, geom_out);
|
|
|
|
geom_out.smoothline = -(lineWidth + SMOOTH_WIDTH * float(lineSmooth)) * 0.5f;
|
|
geom_out.gpu_position = position;
|
|
geom_out.gpu_position.xy -= ofs * position.w;
|
|
strip_EmitVertex(i * 2u + 1u, out_vertex_id, out_primitive_id, geom_out);
|
|
}
|
|
|
|
void geometry_main(VertOut geom_in[2],
|
|
uint out_vertex_id,
|
|
uint out_primitive_id,
|
|
uint out_invocation_id)
|
|
{
|
|
float4 p0 = clip_line_point_homogeneous_space(geom_in[0].gpu_position, geom_in[1].gpu_position);
|
|
float4 p1 = clip_line_point_homogeneous_space(geom_in[1].gpu_position, geom_in[0].gpu_position);
|
|
float2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * viewportSize.xy);
|
|
|
|
#if 0 /* Hard turn when line direction changes quadrant. */
|
|
e = abs(e);
|
|
float2 ofs = (e.x > e.y) ? float2(0.0f, 1.0f / e.x) : float2(1.0f / e.y, 0.0f);
|
|
#else /* Use perpendicular direction. */
|
|
float2 ofs = float2(-e.y, e.x);
|
|
#endif
|
|
ofs /= viewportSize.xy;
|
|
ofs *= lineWidth + SMOOTH_WIDTH * float(lineSmooth);
|
|
|
|
do_vertex(0u, out_vertex_id, out_primitive_id, geom_in, p0, ofs);
|
|
do_vertex(1u, out_vertex_id, out_primitive_id, geom_in, p1, ofs);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
/* Line list primitive. */
|
|
uint input_primitive_vertex_count = uint(gpu_vert_stride_count_offset.x);
|
|
/* Triangle list primitive (emulating triangle strip). */
|
|
constexpr uint output_primitive_vertex_count = 3u;
|
|
constexpr uint output_primitive_count = 2u;
|
|
constexpr uint output_invocation_count = 1u;
|
|
constexpr uint output_vertex_count_per_invocation = output_primitive_count *
|
|
output_primitive_vertex_count;
|
|
constexpr uint output_vertex_count_per_input_primitive = output_vertex_count_per_invocation *
|
|
output_invocation_count;
|
|
|
|
uint in_primitive_id = uint(gl_VertexID) / output_vertex_count_per_input_primitive;
|
|
uint in_primitive_first_vertex = in_primitive_id * input_primitive_vertex_count;
|
|
|
|
uint out_vertex_id = uint(gl_VertexID) % output_primitive_vertex_count;
|
|
uint out_primitive_id = (uint(gl_VertexID) / output_primitive_vertex_count) %
|
|
output_primitive_count;
|
|
uint out_invocation_id = (uint(gl_VertexID) / output_vertex_count_per_invocation) %
|
|
output_invocation_count;
|
|
/* Used to wrap around for the line loop case. */
|
|
uint input_total_vertex_count = uint(gpu_vert_stride_count_offset.y);
|
|
|
|
VertIn vert_in[2];
|
|
vert_in[0] = input_assembly(in_primitive_first_vertex + 0u);
|
|
vert_in[1] = input_assembly((in_primitive_first_vertex + 1u) % input_total_vertex_count);
|
|
|
|
VertOut vert_out[2];
|
|
vert_out[0] = vertex_main(vert_in[0]);
|
|
vert_out[1] = vertex_main(vert_in[1]);
|
|
|
|
/* Discard by default. */
|
|
gl_Position = float4(NAN_FLT);
|
|
geometry_main(vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
|
|
}
|