#70267 Retopology Overlay #104599
|
@ -204,50 +204,10 @@ class MutableBitSpan {
|
|||
}
|
||||
|
||||
/** Sets all referenced bits to 1. */
|
||||
void set_all()
|
||||
{
|
||||
const AlignedIndexRanges ranges = split_index_range_by_alignment(bit_range_, BitsPerInt);
|
||||
{
|
||||
BitInt &first_int = *int_containing_bit(data_, bit_range_.start());
|
||||
const BitInt first_int_mask = mask_range_bits(ranges.prefix.start() & BitIndexMask,
|
||||
ranges.prefix.size());
|
||||
first_int |= first_int_mask;
|
||||
}
|
||||
{
|
||||
BitInt *start = int_containing_bit(data_, ranges.aligned.start());
|
||||
const int64_t ints_to_fill = ranges.aligned.size() / BitsPerInt;
|
||||
constexpr BitInt fill_value = BitInt(-1);
|
||||
initialized_fill_n(start, ints_to_fill, fill_value);
|
||||
}
|
||||
{
|
||||
BitInt &last_int = *int_containing_bit(data_, bit_range_.one_after_last() - 1);
|
||||
const BitInt last_int_mask = mask_first_n_bits(ranges.suffix.size());
|
||||
last_int |= last_int_mask;
|
||||
}
|
||||
}
|
||||
void set_all();
|
||||
|
||||
/** Sets all referenced bits to 0. */
|
||||
void reset_all()
|
||||
{
|
||||
const AlignedIndexRanges ranges = split_index_range_by_alignment(bit_range_, BitsPerInt);
|
||||
{
|
||||
BitInt &first_int = *int_containing_bit(data_, bit_range_.start());
|
||||
const BitInt first_int_mask = mask_range_bits(ranges.prefix.start() & BitIndexMask,
|
||||
ranges.prefix.size());
|
||||
first_int &= ~first_int_mask;
|
||||
}
|
||||
{
|
||||
BitInt *start = int_containing_bit(data_, ranges.aligned.start());
|
||||
const int64_t ints_to_fill = ranges.aligned.size() / BitsPerInt;
|
||||
constexpr BitInt fill_value = 0;
|
||||
initialized_fill_n(start, ints_to_fill, fill_value);
|
||||
}
|
||||
{
|
||||
BitInt &last_int = *int_containing_bit(data_, bit_range_.one_after_last() - 1);
|
||||
const BitInt last_int_mask = mask_first_n_bits(ranges.suffix.size());
|
||||
last_int &= ~last_int_mask;
|
||||
}
|
||||
}
|
||||
void reset_all();
|
||||
|
||||
/** Sets all referenced bits to either 0 or 1. */
|
||||
void set_all(const bool value)
|
||||
|
@ -267,20 +227,8 @@ class MutableBitSpan {
|
|||
}
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const BitSpan &span)
|
||||
{
|
||||
stream << "(Size: " << span.size() << ", ";
|
||||
for (const BitRef bit : span) {
|
||||
stream << bit;
|
||||
}
|
||||
stream << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &stream, const MutableBitSpan &span)
|
||||
{
|
||||
return stream << BitSpan(span);
|
||||
}
|
||||
std::ostream &operator<<(std::ostream &stream, const BitSpan &span);
|
||||
std::ostream &operator<<(std::ostream &stream, const MutableBitSpan &span);
|
||||
|
||||
} // namespace blender::bits
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ set(SRC
|
|||
intern/array_utils.cc
|
||||
intern/astar.c
|
||||
intern/atomic_disjoint_set.cc
|
||||
intern/bit_span.cc
|
||||
intern/bitmap.c
|
||||
intern/bitmap_draw_2d.c
|
||||
intern/boxpack_2d.c
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BLI_bit_span.hh"
|
||||
|
||||
namespace blender::bits {
|
||||
|
||||
void MutableBitSpan::set_all()
|
||||
{
|
||||
if (bit_range_.is_empty()) {
|
||||
return;
|
||||
}
|
||||
const AlignedIndexRanges ranges = split_index_range_by_alignment(bit_range_, BitsPerInt);
|
||||
{
|
||||
BitInt &first_int = *int_containing_bit(data_, bit_range_.start());
|
||||
const BitInt first_int_mask = mask_range_bits(ranges.prefix.start() & BitIndexMask,
|
||||
ranges.prefix.size());
|
||||
first_int |= first_int_mask;
|
||||
}
|
||||
{
|
||||
BitInt *start = int_containing_bit(data_, ranges.aligned.start());
|
||||
const int64_t ints_to_fill = ranges.aligned.size() / BitsPerInt;
|
||||
constexpr BitInt fill_value = BitInt(-1);
|
||||
initialized_fill_n(start, ints_to_fill, fill_value);
|
||||
}
|
||||
{
|
||||
BitInt &last_int = *int_containing_bit(data_, bit_range_.one_after_last() - 1);
|
||||
const BitInt last_int_mask = mask_first_n_bits(ranges.suffix.size());
|
||||
last_int |= last_int_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void MutableBitSpan::reset_all()
|
||||
{
|
||||
if (bit_range_.is_empty()) {
|
||||
return;
|
||||
}
|
||||
const AlignedIndexRanges ranges = split_index_range_by_alignment(bit_range_, BitsPerInt);
|
||||
{
|
||||
BitInt &first_int = *int_containing_bit(data_, bit_range_.start());
|
||||
const BitInt first_int_mask = mask_range_bits(ranges.prefix.start() & BitIndexMask,
|
||||
ranges.prefix.size());
|
||||
first_int &= ~first_int_mask;
|
||||
}
|
||||
{
|
||||
BitInt *start = int_containing_bit(data_, ranges.aligned.start());
|
||||
const int64_t ints_to_fill = ranges.aligned.size() / BitsPerInt;
|
||||
constexpr BitInt fill_value = 0;
|
||||
initialized_fill_n(start, ints_to_fill, fill_value);
|
||||
}
|
||||
{
|
||||
BitInt &last_int = *int_containing_bit(data_, bit_range_.one_after_last() - 1);
|
||||
const BitInt last_int_mask = mask_first_n_bits(ranges.suffix.size());
|
||||
last_int &= ~last_int_mask;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const BitSpan &span)
|
||||
{
|
||||
stream << "(Size: " << span.size() << ", ";
|
||||
for (const BitRef bit : span) {
|
||||
stream << bit;
|
||||
}
|
||||
stream << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const MutableBitSpan &span)
|
||||
{
|
||||
return stream << BitSpan(span);
|
||||
}
|
||||
|
||||
} // namespace blender::bits
|
|
@ -118,6 +118,12 @@ TEST(bit_span, Set)
|
|||
0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'1111'0000);
|
||||
}
|
||||
|
||||
TEST(bit_span, SetEmpty)
|
||||
{
|
||||
MutableBitSpan().set_all(true);
|
||||
MutableBitSpan().set_all(false);
|
||||
}
|
||||
|
||||
TEST(bit_span, SetSliced)
|
||||
{
|
||||
std::array<uint64_t, 10> data;
|
||||
|
|
|
@ -1617,12 +1617,12 @@ static void icon_draw_cache_texture_flush_ex(GPUTexture *texture,
|
|||
return;
|
||||
}
|
||||
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
|
||||
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_ICON_MULTI);
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
const int data_binding = GPU_shader_get_ubo_binding(shader, "multi_rect_data");
|
||||
const int data_binding = GPU_shader_get_ubo_binding(shader, "multi_icon_data");
|
||||
GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(
|
||||
sizeof(MultiRectCallData), texture_draw_calls->drawcall_cache, __func__);
|
||||
sizeof(MultiIconCallData), texture_draw_calls->drawcall_cache, __func__);
|
||||
GPU_uniformbuf_bind(ubo, data_binding);
|
||||
|
||||
const int img_binding = GPU_shader_get_sampler_binding(shader, "image");
|
||||
|
@ -1798,7 +1798,7 @@ static void icon_draw_texture(float x,
|
|||
GPU_shader_bind(shader);
|
||||
|
||||
const int img_binding = GPU_shader_get_sampler_binding(shader, "image");
|
||||
const int color_loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR);
|
||||
const int color_loc = GPU_shader_get_uniform(shader, "finalColor");
|
||||
const int rect_tex_loc = GPU_shader_get_uniform(shader, "rect_icon");
|
||||
const int rect_geom_loc = GPU_shader_get_uniform(shader, "rect_geom");
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ set(GLSL_SRC
|
|||
shaders/gpu_shader_2D_line_dashed_frag.glsl
|
||||
shaders/gpu_shader_2D_image_vert.glsl
|
||||
shaders/gpu_shader_2D_image_rect_vert.glsl
|
||||
shaders/gpu_shader_2D_image_multi_rect_vert.glsl
|
||||
shaders/gpu_shader_icon_multi_vert.glsl
|
||||
shaders/gpu_shader_icon_frag.glsl
|
||||
shaders/gpu_shader_icon_vert.glsl
|
||||
shaders/gpu_shader_image_frag.glsl
|
||||
|
@ -373,7 +373,6 @@ set(GLSL_SRC
|
|||
shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl
|
||||
shaders/gpu_shader_image_shuffle_color_frag.glsl
|
||||
shaders/gpu_shader_image_color_frag.glsl
|
||||
shaders/gpu_shader_image_varying_color_frag.glsl
|
||||
shaders/gpu_shader_3D_image_vert.glsl
|
||||
shaders/gpu_shader_3D_vert.glsl
|
||||
shaders/gpu_shader_3D_normal_vert.glsl
|
||||
|
@ -511,6 +510,7 @@ set(GLSL_SRC
|
|||
shaders/material/gpu_shader_material_world_normals.glsl
|
||||
|
||||
shaders/gpu_shader_gpencil_stroke_vert.glsl
|
||||
shaders/gpu_shader_gpencil_stroke_vert_no_geom.glsl
|
||||
shaders/gpu_shader_gpencil_stroke_frag.glsl
|
||||
shaders/gpu_shader_gpencil_stroke_geom.glsl
|
||||
|
||||
|
@ -656,7 +656,6 @@ set(SRC_SHADER_CREATE_INFOS
|
|||
shaders/infos/gpu_shader_2D_diag_stripes_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_desaturate_color_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_multi_rect_color_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_overlays_merge_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_overlays_stereo_merge_info.hh
|
||||
shaders/infos/gpu_shader_2D_image_rect_color_info.hh
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef enum eGPUBuiltinShader {
|
|||
/** Draw a texture with a desaturation factor. */
|
||||
GPU_SHADER_2D_IMAGE_DESATURATE_COLOR,
|
||||
/** Draw a group of texture rectangle with an associated color multiplied. */
|
||||
GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR,
|
||||
GPU_SHADER_ICON_MULTI,
|
||||
/** Draw a two color checker based on screen position (not UV coordinates). */
|
||||
GPU_SHADER_2D_CHECKER,
|
||||
/** Draw diagonal stripes with two alternating colors. */
|
||||
|
|
|
@ -82,39 +82,39 @@ BLI_STATIC_ASSERT_ALIGN(struct SimpleLightingData, 16)
|
|||
|
||||
#define MAX_CALLS 16
|
||||
|
||||
struct MultiRectCallData {
|
||||
struct MultiIconCallData {
|
||||
float4 calls_data[MAX_CALLS * 3];
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(struct MultiRectCallData, 16)
|
||||
BLI_STATIC_ASSERT_ALIGN(struct MultiIconCallData, 16)
|
||||
|
||||
enum TestStatus {
|
||||
TEST_STATUS_NONE = 0,
|
||||
TEST_STATUS_PASSED = 1,
|
||||
TEST_STATUS_FAILED = 2,
|
||||
TEST_STATUS_NONE = 0u,
|
||||
TEST_STATUS_PASSED = 1u,
|
||||
TEST_STATUS_FAILED = 2u,
|
||||
};
|
||||
enum TestType {
|
||||
TEST_TYPE_BOOL = 0,
|
||||
TEST_TYPE_UINT = 1,
|
||||
TEST_TYPE_INT = 2,
|
||||
TEST_TYPE_FLOAT = 3,
|
||||
TEST_TYPE_IVEC2 = 4,
|
||||
TEST_TYPE_IVEC3 = 5,
|
||||
TEST_TYPE_IVEC4 = 6,
|
||||
TEST_TYPE_UVEC2 = 7,
|
||||
TEST_TYPE_UVEC3 = 8,
|
||||
TEST_TYPE_UVEC4 = 9,
|
||||
TEST_TYPE_VEC2 = 10,
|
||||
TEST_TYPE_VEC3 = 11,
|
||||
TEST_TYPE_VEC4 = 12,
|
||||
TEST_TYPE_MAT2X2 = 13,
|
||||
TEST_TYPE_MAT2X3 = 14,
|
||||
TEST_TYPE_MAT2X4 = 15,
|
||||
TEST_TYPE_MAT3X2 = 16,
|
||||
TEST_TYPE_MAT3X3 = 17,
|
||||
TEST_TYPE_MAT3X4 = 18,
|
||||
TEST_TYPE_MAT4X2 = 19,
|
||||
TEST_TYPE_MAT4X3 = 20,
|
||||
TEST_TYPE_MAT4X4 = 21,
|
||||
TEST_TYPE_BOOL = 0u,
|
||||
TEST_TYPE_UINT = 1u,
|
||||
TEST_TYPE_INT = 2u,
|
||||
TEST_TYPE_FLOAT = 3u,
|
||||
TEST_TYPE_IVEC2 = 4u,
|
||||
TEST_TYPE_IVEC3 = 5u,
|
||||
TEST_TYPE_IVEC4 = 6u,
|
||||
TEST_TYPE_UVEC2 = 7u,
|
||||
TEST_TYPE_UVEC3 = 8u,
|
||||
TEST_TYPE_UVEC4 = 9u,
|
||||
TEST_TYPE_VEC2 = 10u,
|
||||
TEST_TYPE_VEC3 = 11u,
|
||||
TEST_TYPE_VEC4 = 12u,
|
||||
TEST_TYPE_MAT2X2 = 13u,
|
||||
TEST_TYPE_MAT2X3 = 14u,
|
||||
TEST_TYPE_MAT2X4 = 15u,
|
||||
TEST_TYPE_MAT3X2 = 16u,
|
||||
TEST_TYPE_MAT3X3 = 17u,
|
||||
TEST_TYPE_MAT3X4 = 18u,
|
||||
TEST_TYPE_MAT4X2 = 19u,
|
||||
TEST_TYPE_MAT4X3 = 20u,
|
||||
TEST_TYPE_MAT4X4 = 21u,
|
||||
};
|
||||
|
||||
/** \note Contains arrays of scalar. To be use only with SSBOs to avoid padding issues. */
|
||||
|
|
|
@ -42,8 +42,8 @@ static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader)
|
|||
return "gpu_shader_2D_image_shuffle_color";
|
||||
case GPU_SHADER_2D_IMAGE_RECT_COLOR:
|
||||
return "gpu_shader_2D_image_rect_color";
|
||||
case GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR:
|
||||
return "gpu_shader_2D_image_multi_rect_color";
|
||||
case GPU_SHADER_ICON_MULTI:
|
||||
return "gpu_shader_icon_multi";
|
||||
case GPU_SHADER_3D_UNIFORM_COLOR:
|
||||
return "gpu_shader_3D_uniform_color";
|
||||
case GPU_SHADER_3D_FLAT_COLOR:
|
||||
|
@ -85,8 +85,7 @@ static const char *builtin_shader_create_info_name(eGPUBuiltinShader shader)
|
|||
case GPU_SHADER_2D_NODELINK_INST:
|
||||
return "gpu_shader_2D_nodelink_inst";
|
||||
case GPU_SHADER_GPENCIL_STROKE:
|
||||
return GPU_geometry_shader_support() ? "gpu_shader_gpencil_stroke_geom" :
|
||||
"gpu_shader_gpencil_stroke_nogeom";
|
||||
return "gpu_shader_gpencil_stroke";
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
return "";
|
||||
|
|
|
@ -379,6 +379,9 @@ void gpu_shader_create_info_init()
|
|||
|
||||
/* EEVEE Volumetric Material */
|
||||
eevee_legacy_material_volumetric_vert = eevee_legacy_material_volumetric_vert_no_geom;
|
||||
|
||||
/* GPencil stroke. */
|
||||
gpu_shader_gpencil_stroke = gpu_shader_gpencil_stroke_no_geom;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -768,6 +768,7 @@ class MTLContext : public Context {
|
|||
void texture_unbind_all();
|
||||
id<MTLSamplerState> get_sampler_from_state(MTLSamplerState state);
|
||||
id<MTLSamplerState> generate_sampler_from_state(MTLSamplerState state);
|
||||
id<MTLSamplerState> generate_icon_sampler();
|
||||
id<MTLSamplerState> get_default_sampler_state();
|
||||
|
||||
/* Metal Context pipeline state. */
|
||||
|
|
|
@ -223,11 +223,13 @@ MTLContext::MTLContext(void *ghost_window, void *ghost_context)
|
|||
}
|
||||
|
||||
/* Initialize samplers. */
|
||||
for (uint i = 0; i < GPU_SAMPLER_MAX; i++) {
|
||||
for (uint i = 0; i < GPU_SAMPLER_ICON; i++) {
|
||||
MTLSamplerState state;
|
||||
state.state = static_cast<eGPUSamplerState>(i);
|
||||
sampler_state_cache_[i] = this->generate_sampler_from_state(state);
|
||||
}
|
||||
/* Special sampler for icons. */
|
||||
sampler_state_cache_[GPU_SAMPLER_ICON] = this->generate_icon_sampler();
|
||||
}
|
||||
|
||||
MTLContext::~MTLContext()
|
||||
|
@ -2025,7 +2027,6 @@ id<MTLSamplerState> MTLContext::get_sampler_from_state(MTLSamplerState sampler_s
|
|||
|
||||
id<MTLSamplerState> MTLContext::generate_sampler_from_state(MTLSamplerState sampler_state)
|
||||
{
|
||||
/* Check if sampler already exists for given state. */
|
||||
MTLSamplerDescriptor *descriptor = [[MTLSamplerDescriptor alloc] init];
|
||||
descriptor.normalizedCoordinates = true;
|
||||
|
||||
|
@ -2068,6 +2069,21 @@ id<MTLSamplerState> MTLContext::generate_sampler_from_state(MTLSamplerState samp
|
|||
return state;
|
||||
}
|
||||
|
||||
id<MTLSamplerState> MTLContext::generate_icon_sampler()
|
||||
{
|
||||
MTLSamplerDescriptor *descriptor = [[MTLSamplerDescriptor alloc] init];
|
||||
descriptor.minFilter = MTLSamplerMinMagFilterLinear;
|
||||
descriptor.magFilter = MTLSamplerMinMagFilterLinear;
|
||||
descriptor.mipFilter = MTLSamplerMipFilterNearest;
|
||||
descriptor.lodMinClamp = 0;
|
||||
descriptor.lodMaxClamp = 1;
|
||||
|
||||
id<MTLSamplerState> icon_state = [this->device newSamplerStateWithDescriptor:descriptor];
|
||||
BLI_assert(icon_state != nil);
|
||||
[descriptor autorelease];
|
||||
return icon_state;
|
||||
}
|
||||
|
||||
id<MTLSamplerState> MTLContext::get_default_sampler_state()
|
||||
{
|
||||
if (default_sampler_state_ == nil) {
|
||||
|
|
|
@ -239,6 +239,17 @@ void MTLImmediate::end()
|
|||
desc.vertex_descriptor.buffer_layouts[0].stride = this->vertex_format.stride;
|
||||
BLI_assert(this->vertex_format.stride > 0);
|
||||
|
||||
/* Emulate LineLoop using LineStrip. */
|
||||
if (this->prim_type == GPU_PRIM_LINE_LOOP) {
|
||||
/* Patch final vertex of line loop to close. Rendered using LineStrip.
|
||||
* NOTE: vertex_len represents original length, however, allocated Metal
|
||||
* buffer contains space for one extra vertex when LineLoop is used. */
|
||||
uchar *buffer_data = reinterpret_cast<uchar *>(current_allocation_.data);
|
||||
memcpy(buffer_data + (vertex_len)*vertex_format.stride, buffer_data, vertex_format.stride);
|
||||
this->vertex_idx++;
|
||||
this->prim_type = GPU_PRIM_LINE_STRIP;
|
||||
}
|
||||
|
||||
/* SSBO Vertex Fetch -- Verify Attributes. */
|
||||
if (active_mtl_shader->get_uses_ssbo_vertex_fetch()) {
|
||||
active_mtl_shader->ssbo_vertex_fetch_bind_attributes_end(rec);
|
||||
|
@ -337,16 +348,6 @@ void MTLImmediate::end()
|
|||
}
|
||||
rendered = true;
|
||||
} break;
|
||||
case GPU_PRIM_LINE_LOOP: {
|
||||
/* Patch final vertex of line loop to close. Rendered using LineStrip.
|
||||
* NOTE: vertex_len represents original length, however, allocated Metal
|
||||
* buffer contains space for one extra vertex when LineLoop is used. */
|
||||
uchar *buffer_data = reinterpret_cast<uchar *>(current_allocation_.data);
|
||||
memcpy(buffer_data + (vertex_len)*vertex_format.stride,
|
||||
buffer_data,
|
||||
vertex_format.stride);
|
||||
this->vertex_idx++;
|
||||
} break;
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
} break;
|
||||
|
|
|
@ -594,11 +594,11 @@ void GLTexture::samplers_init()
|
|||
}
|
||||
samplers_update();
|
||||
|
||||
/* Custom sampler for icons. */
|
||||
/* Custom sampler for icons.
|
||||
* NOTE: The icon texture is sampled within the shader using a -0.5f lod bias. */
|
||||
GLuint icon_sampler = samplers_[GPU_SAMPLER_ICON];
|
||||
glSamplerParameteri(icon_sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
glSamplerParameteri(icon_sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameterf(icon_sampler, GL_TEXTURE_LOD_BIAS, -0.5f);
|
||||
|
||||
debug::object_label(GL_SAMPLER, icon_sampler, "icons");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
|
||||
#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 27)
|
||||
|
||||
#define GP_XRAY_FRONT 0
|
||||
#define GP_XRAY_3DSPACE 1
|
||||
#define GP_XRAY_BACK 2
|
||||
|
||||
#define GPENCIL_FLATCAP 1
|
||||
|
||||
#define DISCARD_VERTEX \
|
||||
gl_Position = vec4(0.0); \
|
||||
return;
|
||||
|
||||
/* project 3d point to 2d on screen space */
|
||||
vec2 toScreenSpace(vec4 in_vertex)
|
||||
{
|
||||
return vec2(in_vertex.xy / in_vertex.w) * gpencil_stroke_data.viewport;
|
||||
}
|
||||
|
||||
/* get zdepth value */
|
||||
float getZdepth(vec4 point)
|
||||
{
|
||||
if (gpencil_stroke_data.xraymode == GP_XRAY_FRONT) {
|
||||
return 0.0;
|
||||
}
|
||||
if (gpencil_stroke_data.xraymode == GP_XRAY_3DSPACE) {
|
||||
return (point.z / point.w);
|
||||
}
|
||||
if (gpencil_stroke_data.xraymode == GP_XRAY_BACK) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/* in front by default */
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* check equality but with a small tolerance */
|
||||
bool is_equal(vec4 p1, vec4 p2)
|
||||
{
|
||||
float limit = 0.0001;
|
||||
float x = abs(p1.x - p2.x);
|
||||
float y = abs(p1.y - p2.y);
|
||||
float z = abs(p1.z - p2.z);
|
||||
|
||||
if ((x < limit) && (y < limit) && (z < limit)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Vertex emission. */
|
||||
|
||||
#define EMIT_VERTEX(vertex_selector, _v0, _v1, _v2) \
|
||||
{ \
|
||||
switch (vertex_selector) { \
|
||||
case 0: { \
|
||||
_v0 \
|
||||
} break; \
|
||||
case 1: { \
|
||||
_v1 \
|
||||
} break; \
|
||||
case 2: { \
|
||||
_v2 \
|
||||
} break; \
|
||||
} \
|
||||
} \
|
||||
return;
|
||||
|
||||
#define EMIT_VERTEX_COND(vertex_selector, condition, _v0, _v1, _v2) \
|
||||
{ \
|
||||
if (condition) { \
|
||||
switch (vertex_selector) { \
|
||||
case 0: { \
|
||||
_v0 \
|
||||
} break; \
|
||||
case 1: { \
|
||||
_v1 \
|
||||
} break; \
|
||||
case 2: { \
|
||||
_v2 \
|
||||
} break; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
DISCARD_VERTEX; \
|
||||
} \
|
||||
} \
|
||||
return;
|
||||
|
||||
/** All output vertex combinations. */
|
||||
/* Excessively long mitre gap. */
|
||||
#define V0_a \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 + finalThickness[2] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
#define V1_a \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 + finalThickness[2] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
#define V2_a \
|
||||
geometry_out.mTexCoord = vec2(0, 0.5); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4(sp1 / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
#define V0_b \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 - finalThickness[2] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
#define V1_b \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 - finalThickness[2] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
#define V2_b \
|
||||
geometry_out.mTexCoord = vec2(0, 0.5); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4(sp1 / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* -- start end cap. -- */
|
||||
#define V3 \
|
||||
geometry_out.mTexCoord = vec2(1, 0.5); \
|
||||
geometry_out.mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); \
|
||||
vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0 * extend; \
|
||||
gl_Position = vec4((sp1 + svn1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* V4. */
|
||||
#define V4 \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); \
|
||||
gl_Position = vec4( \
|
||||
(sp1 - (length_a * 2.0) * miter_a) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* V5. */
|
||||
#define V5 \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); \
|
||||
gl_Position = vec4( \
|
||||
(sp1 + (length_a * 2.0) * miter_a) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* -- Main triangle strip --*/
|
||||
#define V6 \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 + length_a * miter_a) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* V7. */
|
||||
#define V7 \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = finalColor[1]; \
|
||||
gl_Position = vec4( \
|
||||
(sp1 - length_a * miter_a) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0);
|
||||
|
||||
/* V8. */
|
||||
#define V8 \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = finalColor[2]; \
|
||||
gl_Position = vec4( \
|
||||
(sp2 + length_b * miter_b) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0);
|
||||
|
||||
/* V9. */
|
||||
#define V9 \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = finalColor[2]; \
|
||||
gl_Position = vec4( \
|
||||
(sp2 - length_b * miter_b) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0);
|
||||
|
||||
/* End end-cap. */
|
||||
/* V10. */
|
||||
#define V10 \
|
||||
geometry_out.mTexCoord = vec2(0, 1); \
|
||||
geometry_out.mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); \
|
||||
gl_Position = vec4( \
|
||||
(sp2 + (length_b * 2.0) * miter_b) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0);
|
||||
|
||||
/* V11. */
|
||||
#define V11 \
|
||||
geometry_out.mTexCoord = vec2(0, 0); \
|
||||
geometry_out.mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); \
|
||||
gl_Position = vec4( \
|
||||
(sp2 - (length_b * 2.0) * miter_b) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0);
|
||||
|
||||
/* V12. */
|
||||
#define V12 \
|
||||
geometry_out.mTexCoord = vec2(1, 0.5); \
|
||||
geometry_out.mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); \
|
||||
vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0 * extend; \
|
||||
gl_Position = vec4((sp2 + svn2) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
/* Determine output geometry IDs. */
|
||||
uint input_prim_id = gl_VertexID / 27;
|
||||
uint output_vertex_id = gl_VertexID % 27;
|
||||
uint output_prim_triangle_id = output_vertex_id / 3;
|
||||
uint vertex_in_triangle = output_vertex_id % 3;
|
||||
|
||||
/** Run Vertex shader for all input vertices (Lines adjacency). */
|
||||
vec4 finalPos[4];
|
||||
vec4 finalColor[4];
|
||||
float finalThickness[4];
|
||||
|
||||
float defaultpixsize = gpencil_stroke_data.pixsize * (1000.0 / gpencil_stroke_data.pixfactor);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
finalPos[i] = ModelViewProjectionMatrix *
|
||||
vec4(vertex_fetch_attribute(input_prim_id + i, pos, vec3).xyz, 1.0);
|
||||
finalColor[i] = vertex_fetch_attribute(input_prim_id + i, color, vec4);
|
||||
float in_thickness = vertex_fetch_attribute(input_prim_id + i, thickness, float);
|
||||
|
||||
if (gpencil_stroke_data.keep_size) {
|
||||
finalThickness[i] = in_thickness;
|
||||
}
|
||||
else {
|
||||
float size = (ProjectionMatrix[3][3] == 0.0) ?
|
||||
(in_thickness / (gl_Position.z * defaultpixsize)) :
|
||||
(in_thickness / defaultpixsize);
|
||||
finalThickness[i] = max(size * gpencil_stroke_data.objscale, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Perform Geometry shader alternative. */
|
||||
float MiterLimit = 0.75;
|
||||
|
||||
/* receive 4 points */
|
||||
vec4 P0 = finalPos[0];
|
||||
vec4 P1 = finalPos[1];
|
||||
vec4 P2 = finalPos[2];
|
||||
vec4 P3 = finalPos[3];
|
||||
|
||||
/* get the four vertices passed to the shader */
|
||||
vec2 sp0 = toScreenSpace(P0); /* start of previous segment */
|
||||
vec2 sp1 = toScreenSpace(P1); /* end of previous segment, start of current segment */
|
||||
vec2 sp2 = toScreenSpace(P2); /* end of current segment, start of next segment */
|
||||
vec2 sp3 = toScreenSpace(P3); /* end of next segment */
|
||||
|
||||
/* culling outside viewport */
|
||||
vec2 area = gpencil_stroke_data.viewport * 4.0;
|
||||
if (sp1.x < -area.x || sp1.x > area.x) {
|
||||
DISCARD_VERTEX;
|
||||
}
|
||||
if (sp1.y < -area.y || sp1.y > area.y) {
|
||||
DISCARD_VERTEX;
|
||||
}
|
||||
if (sp2.x < -area.x || sp2.x > area.x) {
|
||||
DISCARD_VERTEX;
|
||||
}
|
||||
if (sp2.y < -area.y || sp2.y > area.y) {
|
||||
DISCARD_VERTEX;
|
||||
}
|
||||
|
||||
/* determine the direction of each of the 3 segments (previous,
|
||||
* current, next) */
|
||||
vec2 v0 = normalize(sp1 - sp0);
|
||||
vec2 v1 = normalize(sp2 - sp1);
|
||||
vec2 v2 = normalize(sp3 - sp2);
|
||||
|
||||
/* determine the normal of each of the 3 segments (previous,
|
||||
* current, next) */
|
||||
vec2 n0 = vec2(-v0.y, v0.x);
|
||||
vec2 n1 = vec2(-v1.y, v1.x);
|
||||
vec2 n2 = vec2(-v2.y, v2.x);
|
||||
|
||||
/* determine miter lines by averaging the normals of the 2
|
||||
* segments */
|
||||
vec2 miter_a = normalize(n0 + n1); /* miter at start of current segment */
|
||||
vec2 miter_b = normalize(n1 + n2); /* miter at end of current segment */
|
||||
|
||||
/* determine the length of the miter by projecting it onto normal
|
||||
* and then inverse it */
|
||||
float an1 = dot(miter_a, n1);
|
||||
float bn1 = dot(miter_b, n2);
|
||||
if (an1 == 0) {
|
||||
an1 = 1;
|
||||
}
|
||||
if (bn1 == 0) {
|
||||
bn1 = 1;
|
||||
}
|
||||
float length_a = finalThickness[1] / an1;
|
||||
float length_b = finalThickness[2] / bn1;
|
||||
if (length_a <= 0.0) {
|
||||
length_a = 0.01;
|
||||
}
|
||||
if (length_b <= 0.0) {
|
||||
length_b = 0.01;
|
||||
}
|
||||
|
||||
/** Geometry output. */
|
||||
/* First triangle (T0). prevent excessively long miters at sharp
|
||||
* corners */
|
||||
if (output_prim_triangle_id == 0) {
|
||||
if (dot(v0, v1) < -MiterLimit) {
|
||||
if (dot(v0, n1) > 0) {
|
||||
EMIT_VERTEX(vertex_in_triangle, V0_a, V1_a, V2_a)
|
||||
}
|
||||
else {
|
||||
EMIT_VERTEX(vertex_in_triangle, V0_b, V1_b, V2_b)
|
||||
}
|
||||
}
|
||||
else {
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
}
|
||||
|
||||
if (dot(v1, v2) < -MiterLimit) {
|
||||
miter_b = n1;
|
||||
length_b = finalThickness[2];
|
||||
}
|
||||
|
||||
float extend = gpencil_stroke_data.fill_stroke ? 2 : 1;
|
||||
bool start_endcap = ((gpencil_stroke_data.caps_start != GPENCIL_FLATCAP) && is_equal(P0, P2));
|
||||
bool end_endcap = (gpencil_stroke_data.caps_end != GPENCIL_FLATCAP) && is_equal(P1, P3);
|
||||
|
||||
switch (output_prim_triangle_id) {
|
||||
/* -- Start end cap. -*/
|
||||
case 1:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, start_endcap, V3, V4, V5)
|
||||
case 2:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, start_endcap, V4, V5, V6)
|
||||
case 3:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, start_endcap, V5, V6, V7)
|
||||
/* -- Standard triangle strip. -- */
|
||||
case 4:
|
||||
EMIT_VERTEX(vertex_in_triangle, V6, V7, V8)
|
||||
case 5:
|
||||
EMIT_VERTEX(vertex_in_triangle, V7, V8, V9)
|
||||
/* -- End end cap. -- */
|
||||
case 6:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, end_endcap, V8, V9, V10)
|
||||
case 7:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, end_endcap, V9, V10, V11)
|
||||
case 8:
|
||||
EMIT_VERTEX_COND(vertex_in_triangle, end_endcap, V10, V11, V12)
|
||||
default:
|
||||
DISCARD_VERTEX
|
||||
}
|
||||
}
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
/* Sample texture with LOD BIAS. Used instead of custom lod bias in GPU_SAMPLER_ICON. */
|
||||
fragColor = texture(image, texCoord_interp, -0.5) * finalColor;
|
||||
|
||||
#ifdef DO_CORNER_MASKING
|
||||
/* Top-left rounded corner parameters. */
|
||||
const float circle_radius_outer = 0.1;
|
||||
const float circle_radius_inner = 0.075;
|
||||
|
@ -18,7 +22,6 @@ void main()
|
|||
const float mask_transparency = 0.25;
|
||||
|
||||
vec2 circle_center = vec2(circle_radius_outer - text_width, 0.5);
|
||||
fragColor = texture(image, texCoord_interp) * color;
|
||||
|
||||
/* radius in icon space (1 is the icon width). */
|
||||
float radius = length(mask_coord_interp - circle_center);
|
||||
|
@ -39,4 +42,5 @@ void main()
|
|||
}
|
||||
|
||||
fragColor = mix(vec4(0.0), fragColor, max(mask_transparency, mask));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 rect = multi_rect_data.calls_data[gl_InstanceID * 3];
|
||||
vec4 tex = multi_rect_data.calls_data[gl_InstanceID * 3 + 1];
|
||||
finalColor = multi_rect_data.calls_data[gl_InstanceID * 3 + 2];
|
||||
vec4 rect = multi_icon_data.calls_data[gl_InstanceID * 3];
|
||||
vec4 tex = multi_icon_data.calls_data[gl_InstanceID * 3 + 1];
|
||||
finalColor = multi_icon_data.calls_data[gl_InstanceID * 3 + 2];
|
||||
|
||||
/* Use pos to select the right swizzle (instead of gl_VertexID)
|
||||
* in order to workaround an OSX driver bug. */
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
void main()
|
||||
{
|
||||
fragColor = texture(image, texCoord_interp) * finalColor;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "gpu_interface_info.hh"
|
||||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_2D_image_multi_rect_color)
|
||||
.vertex_in(0, Type::VEC2, "pos")
|
||||
.vertex_out(flat_color_smooth_tex_coord_interp_iface)
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.uniform_buf(0, "MultiRectCallData", "multi_rect_data")
|
||||
.sampler(0, ImageType::FLOAT_2D, "image")
|
||||
.typedef_source("GPU_shader_shared.h")
|
||||
.vertex_source("gpu_shader_2D_image_multi_rect_vert.glsl")
|
||||
.fragment_source("gpu_shader_image_varying_color_frag.glsl")
|
||||
.do_static_compilation(true);
|
|
@ -25,17 +25,20 @@ GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke_base)
|
|||
|
||||
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
|
||||
.push_constant(Type::MAT4, "ProjectionMatrix")
|
||||
.vertex_source("gpu_shader_gpencil_stroke_vert.glsl")
|
||||
.fragment_source("gpu_shader_gpencil_stroke_frag.glsl")
|
||||
.typedef_source("GPU_shader_shared.h");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke_geom)
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke)
|
||||
.additional_info("gpu_shader_gpencil_stroke_base")
|
||||
.geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::TRIANGLE_STRIP, 13)
|
||||
.geometry_out(gpencil_stroke_geom_iface)
|
||||
.vertex_source("gpu_shader_gpencil_stroke_vert.glsl")
|
||||
.geometry_source("gpu_shader_gpencil_stroke_geom.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke_nogeom)
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke_no_geom)
|
||||
.metal_backend_only(true)
|
||||
.additional_info("gpu_shader_gpencil_stroke_base")
|
||||
.vertex_out(gpencil_stroke_geom_iface)
|
||||
.vertex_source("gpu_shader_gpencil_stroke_vert_no_geom.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
#include "gpu_shader_create_info.hh"
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_icon)
|
||||
.define("DO_CORNER_MASKING")
|
||||
.vertex_out(smooth_icon_interp_iface)
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
|
||||
.push_constant(Type::VEC4, "color")
|
||||
.push_constant(Type::VEC4, "finalColor")
|
||||
.push_constant(Type::VEC4, "rect_icon")
|
||||
.push_constant(Type::VEC4, "rect_geom")
|
||||
.push_constant(Type::FLOAT, "text_width")
|
||||
|
@ -20,3 +21,14 @@ GPU_SHADER_CREATE_INFO(gpu_shader_icon)
|
|||
.vertex_source("gpu_shader_icon_vert.glsl")
|
||||
.fragment_source("gpu_shader_icon_frag.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
||||
GPU_SHADER_CREATE_INFO(gpu_shader_icon_multi)
|
||||
.vertex_in(0, Type::VEC2, "pos")
|
||||
.vertex_out(flat_color_smooth_tex_coord_interp_iface)
|
||||
.fragment_out(0, Type::VEC4, "fragColor")
|
||||
.uniform_buf(0, "MultiIconCallData", "multi_icon_data")
|
||||
.sampler(0, ImageType::FLOAT_2D, "image")
|
||||
.typedef_source("GPU_shader_shared.h")
|
||||
.vertex_source("gpu_shader_icon_multi_vert.glsl")
|
||||
.fragment_source("gpu_shader_icon_frag.glsl")
|
||||
.do_static_compilation(true);
|
||||
|
|
|
@ -36,7 +36,7 @@ static void test_shader_builtin()
|
|||
test_compile_builtin_shader(GPU_SHADER_3D_IMAGE_COLOR, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_ICON_MULTI, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_2D_CHECKER, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_2D_DIAG_STRIPES, GPU_SHADER_CFG_DEFAULT);
|
||||
test_compile_builtin_shader(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, GPU_SHADER_CFG_DEFAULT);
|
||||
|
|
Loading…
Reference in New Issue