chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -29,12 +29,23 @@ uint gpu_index_load(uint element_index)
|
||||
return element_index;
|
||||
}
|
||||
|
||||
#ifdef GPU_WEBGL
|
||||
uint raw_index = gpu_webgl_load_gpu_index_buf(gpu_index_16bit ? element_index >> 1u :
|
||||
element_index);
|
||||
#else
|
||||
uint raw_index = gpu_index_buf[gpu_index_16bit ? element_index >> 1u : element_index];
|
||||
#endif
|
||||
|
||||
if (gpu_index_16bit) {
|
||||
raw_index = ((element_index & 1u) == 0u) ? (raw_index & 0xFFFFu) : (raw_index >> 16u);
|
||||
}
|
||||
|
||||
#ifdef GPU_WEBGL
|
||||
/* Preserve fixed restart before adding the compressed buffer's base index. */
|
||||
if (raw_index == (gpu_index_16bit ? 0xFFFFu : 0xFFFFFFFFu)) {
|
||||
return 0xFFFFFFFFu;
|
||||
}
|
||||
#endif
|
||||
return raw_index + uint(gpu_index_base_index);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,14 +69,14 @@ uint rgb9e5_encode(float3 color)
|
||||
{
|
||||
rgb9e5_t result = rgb9e5_from_float3(color);
|
||||
result.exp_shared <<= RGB9E5_MANTISSA_BITS * 3;
|
||||
result.mantissa <<= RGB9E5_MANTISSA_BITS * uint3(0, 1, 2);
|
||||
result.mantissa <<= uint(RGB9E5_MANTISSA_BITS) * uint3(0, 1, 2);
|
||||
return result.mantissa.r | result.mantissa.g | result.mantissa.b | result.exp_shared;
|
||||
}
|
||||
|
||||
float3 rgb9e5_decode(uint data)
|
||||
{
|
||||
int exp_shared = int(data >> (RGB9E5_MANTISSA_BITS * 3));
|
||||
uint3 mantissa = (uint3(data) >> (RGB9E5_MANTISSA_BITS * uint3(0, 1, 2))) &
|
||||
uint3 mantissa = (uint3(data) >> (uint(RGB9E5_MANTISSA_BITS) * uint3(0, 1, 2))) &
|
||||
uint(MAX_RGB9E5_MANTISSA);
|
||||
return float3(mantissa) * rgb9e5_exponent_factor(exp_shared);
|
||||
}
|
||||
|
||||
@@ -6,15 +6,20 @@
|
||||
|
||||
#include "gpu_shader_compat.hh"
|
||||
|
||||
#ifdef GPU_WEBGL
|
||||
/* WebGL stores the single-mip tile map layers as rows. Integer fetches are unchanged. */
|
||||
bool tiled_image_lookup(float3 &co, sampler2DArray ima, sampler2D map)
|
||||
#else
|
||||
bool tiled_image_lookup(float3 &co, sampler2DArray ima, sampler1DArray map)
|
||||
#endif
|
||||
{
|
||||
float2 tile_pos = floor(co.xy);
|
||||
|
||||
if (tile_pos.x < 0 || tile_pos.y < 0 || tile_pos.x >= 10) {
|
||||
if (tile_pos.x < 0.0f || tile_pos.y < 0.0f || tile_pos.x >= 10.0f) {
|
||||
return false;
|
||||
}
|
||||
float tile = 10 * tile_pos.y + tile_pos.x;
|
||||
if (tile >= textureSize(map, 0).x) {
|
||||
float tile = 10.0f * tile_pos.y + tile_pos.x;
|
||||
if (tile >= float(textureSize(map, 0).x)) {
|
||||
return false;
|
||||
}
|
||||
/* Fetch tile information. */
|
||||
|
||||
@@ -105,9 +105,9 @@ void main()
|
||||
case SOCK_DISPLAY_SHAPE_VOLUME_GRID: {
|
||||
constexpr float rect_side_length = 0.25f;
|
||||
const float2 oversize = float2(0.0f, square_radius * 1.4) / 2.5f;
|
||||
const float2 rect_corner = max(float2(rect_side_length), extrusion / 2.0f + oversize) +
|
||||
float2 rect_corner = max(float2(rect_side_length), extrusion / 2.0f + oversize) +
|
||||
finalOutlineThickness / 4.0f;
|
||||
const float2 mirrored_uv = abs(abs(uv) - rect_corner);
|
||||
float2 mirrored_uv = abs(abs(uv) - rect_corner);
|
||||
distance_squared = square_sdf(mirrored_uv, rect_corner + finalOutlineThickness / 2.0f);
|
||||
alpha_threshold = corner_rounding;
|
||||
break;
|
||||
@@ -115,9 +115,9 @@ void main()
|
||||
case SOCK_DISPLAY_SHAPE_LIST: {
|
||||
constexpr float2 rect_side_length = float2(0.5f, 0.25f);
|
||||
const float2 oversize = float2(0.0f, square_radius * 1.4) / 2.5f;
|
||||
const float2 rect_corner = max(rect_side_length, extrusion / 2.0f + oversize) +
|
||||
float2 rect_corner = max(rect_side_length, extrusion / 2.0f + oversize) +
|
||||
finalOutlineThickness / 4.0f;
|
||||
const float2 mirrored_uv = float2(
|
||||
float2 mirrored_uv = float2(
|
||||
abs(uv.x), abs(abs(abs(uv.y) - rect_corner.y / 1.5f) - rect_corner.y / 1.5f));
|
||||
distance_squared = square_sdf(
|
||||
mirrored_uv, (rect_corner + finalOutlineThickness / 2.0f) / float2(1.0f, 1.5f));
|
||||
|
||||
@@ -284,15 +284,16 @@ struct Resources {
|
||||
InnerType v0, v1, v2, h0, h1, h2, out_pixel;
|
||||
|
||||
/* Reduce vertically up to 3 times (depending on kernel horizontal size) */
|
||||
switch (kernel_size.x) {
|
||||
case 3:
|
||||
/* Keep the same sample order without switch fall-through for WGSL translation. */
|
||||
{
|
||||
if (kernel_size.x == 3) {
|
||||
switch (kernel_size.y) {
|
||||
case 3:
|
||||
v2 = load_sample(src_coord + int2(2, 2), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v1 = load_sample(src_coord + int2(2, 1), load_from_shared); v0 = load_sample(src_coord + int2(2, 0), load_from_shared); break;
|
||||
case 2:
|
||||
v1 = load_sample(src_coord + int2(2, 1), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v0 = load_sample(src_coord + int2(2, 0), load_from_shared); break;
|
||||
case 1:
|
||||
v0 = load_sample(src_coord + int2(2, 0), load_from_shared);
|
||||
break;
|
||||
@@ -308,15 +309,14 @@ struct Resources {
|
||||
h2 = v0;
|
||||
break;
|
||||
}
|
||||
ATTR_FALLTHROUGH;
|
||||
case 2:
|
||||
} if (kernel_size.x == 2 || kernel_size.x == 3) {
|
||||
switch (kernel_size.y) {
|
||||
case 3:
|
||||
v2 = load_sample(src_coord + int2(1, 2), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v1 = load_sample(src_coord + int2(1, 1), load_from_shared); v0 = load_sample(src_coord + int2(1, 0), load_from_shared); break;
|
||||
case 2:
|
||||
v1 = load_sample(src_coord + int2(1, 1), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v0 = load_sample(src_coord + int2(1, 0), load_from_shared); break;
|
||||
case 1:
|
||||
v0 = load_sample(src_coord + int2(1, 0), load_from_shared);
|
||||
break;
|
||||
@@ -332,15 +332,14 @@ struct Resources {
|
||||
h1 = v0;
|
||||
break;
|
||||
}
|
||||
ATTR_FALLTHROUGH;
|
||||
case 1:
|
||||
} if (kernel_size.x >= 1 && kernel_size.x <= 3) {
|
||||
switch (kernel_size.y) {
|
||||
case 3:
|
||||
v2 = load_sample(src_coord + int2(0, 2), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v1 = load_sample(src_coord + int2(0, 1), load_from_shared); v0 = load_sample(src_coord + int2(0, 0), load_from_shared); break;
|
||||
case 2:
|
||||
v1 = load_sample(src_coord + int2(0, 1), load_from_shared);
|
||||
ATTR_FALLTHROUGH;
|
||||
v0 = load_sample(src_coord + int2(0, 0), load_from_shared); break;
|
||||
case 1:
|
||||
v0 = load_sample(src_coord + int2(0, 0), load_from_shared);
|
||||
break;
|
||||
@@ -356,6 +355,7 @@ struct Resources {
|
||||
h0 = v0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reduce up to 3 samples horizontally. */
|
||||
@@ -527,7 +527,10 @@ void update_mipmaps([[global_invocation_id]] const uint3 global_id,
|
||||
[[local_invocation_id]] const uint3 local_index,
|
||||
[[resource_table]] Resources<format, SharedStorage, InnerType> &srt)
|
||||
{
|
||||
if (srt.num_levels == 1u) {
|
||||
const bool two_levels = srt.num_levels != 1u;
|
||||
int2 tile_index = int2(0);
|
||||
bool use_bounds_check = false;
|
||||
if (!two_levels) {
|
||||
int2 kernel_size = kernel_size_from_input_size(srt.level_size(INPUT_LEVEL));
|
||||
int2 dst_image_size = srt.level_size(INPUT_LEVEL + 1);
|
||||
int2 dst_coord = int2(int(global_id.x) % dst_image_size.x,
|
||||
@@ -547,32 +550,32 @@ void update_mipmaps([[global_invocation_id]] const uint3 global_id,
|
||||
int2 tile_count;
|
||||
tile_count.x = int(uint(level2_size.x + 7) / 8u);
|
||||
tile_count.y = int(uint(level2_size.y + 7) / 8u);
|
||||
int2 tile_index = int2(group_id.x % uint(tile_count.x), group_id.x / uint(tile_count.x));
|
||||
tile_index = int2(group_id.x % uint(tile_count.x), group_id.x / uint(tile_count.x));
|
||||
|
||||
/* Determine if bounds checking is needed; this is only the case
|
||||
* for tiles at the right or bottom fringe that might be cut off
|
||||
* by the image border. Note that later, I use if statements rather
|
||||
* than passing use_bounds_check directly to convince the compiler
|
||||
* to inline everything. */
|
||||
bool use_bounds_check = tile_index.x >= tile_count.x - 1 || tile_index.y >= tile_count.y - 1;
|
||||
use_bounds_check = tile_index.x >= tile_count.x - 1 || tile_index.y >= tile_count.y - 1;
|
||||
|
||||
if (use_bounds_check) {
|
||||
/* Compute the tile in level inputLevel_ + 1 that's needed to
|
||||
* compute the above 8x8 tile. */
|
||||
srt.fill_intermediate_tile(local_index.x, tile_index * 2 * int2(8, 8), true);
|
||||
barrier();
|
||||
|
||||
/* Compute the inputLevel_ + 2 tile of size 8x8, loading
|
||||
* inputs from shared memory. */
|
||||
srt.fill_last_tile(local_index.x, tile_index * int2(8, 8), true);
|
||||
}
|
||||
else {
|
||||
/* Same but without bounds checking. */
|
||||
srt.fill_intermediate_tile(local_index.x, tile_index * 2 * int2(8, 8), false);
|
||||
barrier();
|
||||
srt.fill_last_tile(local_index.x, tile_index * int2(8, 8), false);
|
||||
}
|
||||
}
|
||||
/* Every lane reaches the barrier before consuming intermediate shared pixels. */
|
||||
barrier();
|
||||
if (two_levels) {
|
||||
if (use_bounds_check) { srt.fill_last_tile(local_index.x, tile_index * int2(8, 8), true); }
|
||||
else { srt.fill_last_tile(local_index.x, tile_index * int2(8, 8), false); }
|
||||
}
|
||||
}
|
||||
|
||||
template struct Shared<float>;
|
||||
|
||||
@@ -296,7 +296,9 @@ struct Resources {
|
||||
|
||||
bool is_tria = (vert_id > 3);
|
||||
float2 pos;
|
||||
VertOut vert_out = (is_tria) ? widget.do_tria(vert_id, pos) : widget.do_widget(vert_id, pos);
|
||||
VertOut vert_out;
|
||||
if (is_tria) { vert_out = widget.do_tria(vert_id, pos); }
|
||||
else { vert_out = widget.do_widget(vert_id, pos); }
|
||||
|
||||
/* WORKAROUND: Quirk of current BSL implementation.
|
||||
* Current implementation doesn't allow to assign the output struct at once. */
|
||||
|
||||
@@ -16,6 +16,26 @@ struct VertIn {
|
||||
float4 final_color;
|
||||
};
|
||||
|
||||
float polyline_position_load(uint address)
|
||||
{
|
||||
#ifdef GPU_WEBGL
|
||||
return uintBitsToFloat(gpu_webgl_load_pos(address));
|
||||
#else
|
||||
return pos[address];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef UNIFORM
|
||||
float polyline_color_load(uint address)
|
||||
{
|
||||
# ifdef GPU_WEBGL
|
||||
return uintBitsToFloat(gpu_webgl_load_color(address));
|
||||
# else
|
||||
return color[address];
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
VertIn input_assembly(uint in_vertex_id)
|
||||
{
|
||||
uint v_i = gpu_index_load(in_vertex_id);
|
||||
@@ -24,12 +44,12 @@ VertIn input_assembly(uint in_vertex_id)
|
||||
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];
|
||||
vert_in.ls_P.x = polyline_position_load(gpu_attr_load_index(v_i, gpu_attr_0) + 0u + ofs);
|
||||
if (gpu_attr_0_len >= 2) {
|
||||
vert_in.ls_P.y = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 1 + ofs];
|
||||
vert_in.ls_P.y = polyline_position_load(gpu_attr_load_index(v_i, gpu_attr_0) + 1u + ofs);
|
||||
}
|
||||
if (gpu_attr_0_len >= 3) {
|
||||
vert_in.ls_P.z = pos[gpu_attr_load_index(v_i, gpu_attr_0) + 2 + ofs];
|
||||
vert_in.ls_P.z = polyline_position_load(gpu_attr_load_index(v_i, gpu_attr_0) + 2u + ofs);
|
||||
}
|
||||
|
||||
if (gpu_attr_0_fetch_int) {
|
||||
@@ -38,19 +58,26 @@ VertIn input_assembly(uint in_vertex_id)
|
||||
#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) {
|
||||
# ifdef GPU_WEBGL
|
||||
/* Decode packed bytes before float conversion, including bit patterns that encode NaNs. */
|
||||
uint packed_color = gpu_webgl_load_color(gpu_attr_load_index(v_i, gpu_attr_1) + ofs);
|
||||
vert_in.final_color = float4(gpu_attr_decode_uchar4_to_uint4(packed_color)) / 255.0f;
|
||||
# else
|
||||
vert_in.final_color.x = color[gpu_attr_load_index(v_i, gpu_attr_1) + ofs];
|
||||
vert_in.final_color = unpackUnorm4x8(floatBitsToUint(vert_in.final_color.x));
|
||||
# endif
|
||||
}
|
||||
else {
|
||||
vert_in.final_color.x = polyline_color_load(gpu_attr_load_index(v_i, gpu_attr_1) + ofs);
|
||||
if (gpu_attr_1_len >= 2) {
|
||||
vert_in.final_color.y = color[gpu_attr_load_index(v_i, gpu_attr_1) + 1 + ofs];
|
||||
vert_in.final_color.y = polyline_color_load(gpu_attr_load_index(v_i, gpu_attr_1) + 1u + ofs);
|
||||
}
|
||||
if (gpu_attr_1_len >= 3) {
|
||||
vert_in.final_color.z = color[gpu_attr_load_index(v_i, gpu_attr_1) + 2 + ofs];
|
||||
vert_in.final_color.z = polyline_color_load(gpu_attr_load_index(v_i, gpu_attr_1) + 2u + ofs);
|
||||
}
|
||||
if (gpu_attr_1_len >= 4) {
|
||||
vert_in.final_color.w = color[gpu_attr_load_index(v_i, gpu_attr_1) + 3 + ofs];
|
||||
vert_in.final_color.w = polyline_color_load(gpu_attr_load_index(v_i, gpu_attr_1) + 3u + ofs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -134,8 +161,15 @@ void do_vertex(const uint i,
|
||||
geom_out.final_color = color;
|
||||
|
||||
#elif defined(FLAT)
|
||||
# ifdef GPU_WEBGL
|
||||
/* Triangle provoking-vertex rotation cannot choose the input line's color:
|
||||
* all six expanded vertices carry the same flat value. Keep endpoint order
|
||||
* (and thus clipping/winding) intact and select the native source explicitly. */
|
||||
geom_out.final_color = geom_in[gpu_webgl_polyline_first_vertex ? 0 : 1].final_color;
|
||||
# else
|
||||
/* WATCH: Assuming last provoking vertex. */
|
||||
geom_out.final_color = geom_in[1].final_color;
|
||||
# endif
|
||||
|
||||
#elif defined(SMOOTH)
|
||||
geom_out.final_color = geom_in[i].final_color;
|
||||
@@ -201,10 +235,26 @@ void main()
|
||||
output_invocation_count;
|
||||
/* Used to wrap around for the line loop case. */
|
||||
uint input_total_vertex_count = uint(gpu_vert_stride_count_offset.y);
|
||||
uint index_start = uint(gpu_polyline_index_start);
|
||||
uint first_vertex = index_start + in_primitive_first_vertex;
|
||||
uint second_vertex = index_start + (in_primitive_first_vertex + 1u) % input_total_vertex_count;
|
||||
|
||||
#ifdef GPU_WEBGL
|
||||
/* Expanded draws must discard restart segments before fetching their vertex attributes. */
|
||||
if (gpu_index_load(first_vertex) == 0xFFFFFFFFu ||
|
||||
gpu_index_load(second_vertex) == 0xFFFFFFFFu)
|
||||
{
|
||||
gl_Position = float4(2.0f, 2.0f, 2.0f, 1.0f);
|
||||
final_color = float4(0.0f);
|
||||
smoothline = 0.0f;
|
||||
clip = 0.0f;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
vert_in[0] = input_assembly(first_vertex);
|
||||
vert_in[1] = input_assembly(second_vertex);
|
||||
|
||||
VertOut vert_out[2];
|
||||
vert_out[0] = vertex_main(vert_in[0]);
|
||||
|
||||
@@ -10,7 +10,7 @@ void main()
|
||||
{
|
||||
float phase = mod((gl_FragCoord.x + gl_FragCoord.y), float(size1 + size2));
|
||||
|
||||
if (phase < size1) {
|
||||
if (phase < float(size1)) {
|
||||
fragColor = color1;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -46,13 +46,13 @@ void main()
|
||||
outline_dist = max(outline_dist, absPos.x - radii[2]);
|
||||
}
|
||||
|
||||
float alpha = 1 - smoothstep(thresholds[0], thresholds[1], abs(outline_dist));
|
||||
float alpha = 1.0f - smoothstep(thresholds[0], thresholds[1], abs(outline_dist));
|
||||
|
||||
/* Inside the outline. */
|
||||
if (outline_dist < 0) {
|
||||
if (outline_dist < 0.0f) {
|
||||
/* Middle dot */
|
||||
if (test(GPU_KEYFRAME_SHAPE_INNER_DOT)) {
|
||||
alpha = max(alpha, 1 - smoothstep(thresholds[2], thresholds[3], length(absPos)));
|
||||
alpha = max(alpha, 1.0f - smoothstep(thresholds[2], thresholds[3], length(absPos)));
|
||||
}
|
||||
|
||||
/* Up and down arrow-like shading. */
|
||||
|
||||
@@ -26,11 +26,11 @@ void main()
|
||||
gl_Position = ModelViewProjectionMatrix * float4(pos, 0.0f, 1.0f);
|
||||
|
||||
/* Align to pixel grid if the viewport size is known. */
|
||||
if (ViewportSize.x > 0) {
|
||||
if (ViewportSize.x > 0.0f) {
|
||||
float2 scale = ViewportSize * 0.5f;
|
||||
float2 px_pos = (gl_Position.xy + 1) * scale;
|
||||
float2 px_pos = (gl_Position.xy + 1.0f) * scale;
|
||||
float2 adj_pos = round(px_pos - 0.5f) + 0.5f;
|
||||
gl_Position.xy = adj_pos / scale - 1;
|
||||
gl_Position.xy = adj_pos / scale - 1.0f;
|
||||
}
|
||||
|
||||
/* Pass through parameters. */
|
||||
@@ -45,7 +45,7 @@ void main()
|
||||
}
|
||||
|
||||
/* Size-dependent line thickness. */
|
||||
float half_width = (0.06f + (size - 10) * 0.04f);
|
||||
float half_width = (0.06f + (size - 10.0f) * 0.04f);
|
||||
float line_width = half_width + line_falloff;
|
||||
|
||||
/* Outline thresholds. */
|
||||
@@ -57,7 +57,7 @@ void main()
|
||||
/* Extend the primitive size by half line width on either side; odd for symmetry. */
|
||||
float ext_radius = round(0.5f * size) + thresholds.x;
|
||||
|
||||
gl_PointSize = ceil(ext_radius + thresholds.y) * 2 + 1;
|
||||
gl_PointSize = ceil(ext_radius + thresholds.y) * 2.0f + 1.0f;
|
||||
|
||||
/* Diamond radius. */
|
||||
radii[0] = ext_radius * diagonal_scale;
|
||||
|
||||
@@ -83,7 +83,7 @@ void main()
|
||||
uint shadow_type = glyph_flags & 0xFu;
|
||||
|
||||
/* Colored glyphs: do not do filtering or blurring. */
|
||||
if (num_channels == 4) {
|
||||
if (num_channels == 4u) {
|
||||
fragColor.rgba = sample_glyph_rgba(uv_base).rgba;
|
||||
fragColor.a *= color_flat.a;
|
||||
return;
|
||||
@@ -93,7 +93,7 @@ void main()
|
||||
|
||||
fragColor.rgb = color_flat.rgb;
|
||||
|
||||
if (shadow_type == 0) {
|
||||
if (shadow_type == 0u) {
|
||||
/* No blurring: just a bilinear sample. */
|
||||
fragColor.a = sample_glyph_bilinear(bilin_f, uv_base);
|
||||
}
|
||||
@@ -106,7 +106,7 @@ void main()
|
||||
int2 texel = int2(floor(uv_base)) - 1;
|
||||
int frag_offset = glyph_offset + texel.y * glyph_dim.x + texel.x;
|
||||
|
||||
if (shadow_type == 6) {
|
||||
if (shadow_type == 6u) {
|
||||
/* 3x3 outline by dilation */
|
||||
|
||||
float maxval = 0.0f;
|
||||
@@ -131,7 +131,7 @@ void main()
|
||||
}
|
||||
fragColor.a = maxval;
|
||||
}
|
||||
else if (shadow_type <= 4) {
|
||||
else if (shadow_type <= 4u) {
|
||||
/* 3x3 blur */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
@@ -17,7 +17,7 @@ void main()
|
||||
|
||||
/* Depending on shadow outline / blur level, we might need to expand the quad. */
|
||||
uint shadow_type = glyph_flags & 0xFu;
|
||||
int interp_size = shadow_type > 4 ? 2 : (shadow_type > 0 ? 1 : 0);
|
||||
int interp_size = shadow_type > 4u ? 2 : (shadow_type > 0u ? 1 : 0);
|
||||
|
||||
/* Quad expansion using instanced rendering. */
|
||||
float x = float(gl_VertexID % 2);
|
||||
|
||||
@@ -37,6 +37,7 @@ PUSH_CONSTANT(bool, lineSmooth)
|
||||
STORAGE_BUF_FREQ(GPU_SSBO_POLYLINE_POS_BUF_SLOT, read, float, pos[], GEOMETRY)
|
||||
PUSH_CONSTANT(int2, gpu_attr_0)
|
||||
PUSH_CONSTANT(int3, gpu_vert_stride_count_offset)
|
||||
PUSH_CONSTANT(int, gpu_polyline_index_start)
|
||||
PUSH_CONSTANT(int, gpu_attr_0_len)
|
||||
PUSH_CONSTANT(bool, gpu_attr_0_fetch_int)
|
||||
PUSH_CONSTANT(bool, gpu_attr_1_fetch_unorm8)
|
||||
|
||||
Reference in New Issue
Block a user