Copy as Markdown

Other Tools

struct cs_border_segment_common {
struct Samplers {
bool set_slot(int index, int value) {
switch (index) {
}
return false;
}
} samplers;
struct AttribLocations {
int aPosition = NULL_ATTRIB;
int aTaskOrigin = NULL_ATTRIB;
int aRect = NULL_ATTRIB;
int aColor0 = NULL_ATTRIB;
int aColor1 = NULL_ATTRIB;
int aFlags = NULL_ATTRIB;
int aWidths = NULL_ATTRIB;
int aRadii = NULL_ATTRIB;
int aClipParams1 = NULL_ATTRIB;
int aClipParams2 = NULL_ATTRIB;
void bind_loc(const char* name, int index) {
if (strcmp("aPosition", name) == 0) { aPosition = index; return; }
if (strcmp("aTaskOrigin", name) == 0) { aTaskOrigin = index; return; }
if (strcmp("aRect", name) == 0) { aRect = index; return; }
if (strcmp("aColor0", name) == 0) { aColor0 = index; return; }
if (strcmp("aColor1", name) == 0) { aColor1 = index; return; }
if (strcmp("aFlags", name) == 0) { aFlags = index; return; }
if (strcmp("aWidths", name) == 0) { aWidths = index; return; }
if (strcmp("aRadii", name) == 0) { aRadii = index; return; }
if (strcmp("aClipParams1", name) == 0) { aClipParams1 = index; return; }
if (strcmp("aClipParams2", name) == 0) { aClipParams2 = index; return; }
}
int get_loc(const char* name) const {
if (strcmp("aPosition", name) == 0) { return aPosition != NULL_ATTRIB ? aPosition : -1; }
if (strcmp("aTaskOrigin", name) == 0) { return aTaskOrigin != NULL_ATTRIB ? aTaskOrigin : -1; }
if (strcmp("aRect", name) == 0) { return aRect != NULL_ATTRIB ? aRect : -1; }
if (strcmp("aColor0", name) == 0) { return aColor0 != NULL_ATTRIB ? aColor0 : -1; }
if (strcmp("aColor1", name) == 0) { return aColor1 != NULL_ATTRIB ? aColor1 : -1; }
if (strcmp("aFlags", name) == 0) { return aFlags != NULL_ATTRIB ? aFlags : -1; }
if (strcmp("aWidths", name) == 0) { return aWidths != NULL_ATTRIB ? aWidths : -1; }
if (strcmp("aRadii", name) == 0) { return aRadii != NULL_ATTRIB ? aRadii : -1; }
if (strcmp("aClipParams1", name) == 0) { return aClipParams1 != NULL_ATTRIB ? aClipParams1 : -1; }
if (strcmp("aClipParams2", name) == 0) { return aClipParams2 != NULL_ATTRIB ? aClipParams2 : -1; }
return -1;
}
} attrib_locations;
vec4_scalar vColor00;
vec4_scalar vColor01;
vec4_scalar vColor10;
vec4_scalar vColor11;
vec4_scalar vColorLine;
vec2_scalar vSegmentClipMode;
vec4_scalar vStyleEdgeAxis;
vec4_scalar vClipCenter_Sign;
vec4_scalar vClipRadii;
vec4_scalar vEdgeReference;
vec4_scalar vPartialWidths;
vec4_scalar vClipParams1;
vec4_scalar vClipParams2;
mat4_scalar uTransform;
void bind_textures() {
}
};
struct cs_border_segment_vert : VertexShaderImpl, cs_border_segment_common {
private:
typedef cs_border_segment_vert Self;
// mat4_scalar uTransform;
vec2 aPosition;
struct RectWithSize_scalar {
vec2_scalar p0;
vec2_scalar size;
RectWithSize_scalar() = default;
RectWithSize_scalar(vec2_scalar p0, vec2_scalar size) : p0(p0), size(size){}
};
struct RectWithSize {
vec2 p0;
vec2 size;
RectWithSize() = default;
RectWithSize(vec2 p0, vec2 size) : p0(p0), size(size){}
RectWithSize(vec2_scalar p0, vec2_scalar size):p0(p0),size(size){
}
IMPLICIT RectWithSize(RectWithSize_scalar s):p0(s.p0),size(s.size){
}
friend RectWithSize if_then_else(I32 c, RectWithSize t, RectWithSize e) { return RectWithSize(
if_then_else(c, t.p0, e.p0), if_then_else(c, t.size, e.size));
}};
struct RectWithEndpoint_scalar {
vec2_scalar p0;
vec2_scalar p1;
RectWithEndpoint_scalar() = default;
RectWithEndpoint_scalar(vec2_scalar p0, vec2_scalar p1) : p0(p0), p1(p1){}
};
struct RectWithEndpoint {
vec2 p0;
vec2 p1;
RectWithEndpoint() = default;
RectWithEndpoint(vec2 p0, vec2 p1) : p0(p0), p1(p1){}
RectWithEndpoint(vec2_scalar p0, vec2_scalar p1):p0(p0),p1(p1){
}
IMPLICIT RectWithEndpoint(RectWithEndpoint_scalar s):p0(s.p0),p1(s.p1){
}
friend RectWithEndpoint if_then_else(I32 c, RectWithEndpoint t, RectWithEndpoint e) { return RectWithEndpoint(
if_then_else(c, t.p0, e.p0), if_then_else(c, t.p1, e.p1));
}};
// vec4_scalar vColor00;
// vec4_scalar vColor01;
// vec4_scalar vColor10;
// vec4_scalar vColor11;
// vec4_scalar vColorLine;
// vec2_scalar vSegmentClipMode;
// vec4_scalar vStyleEdgeAxis;
// vec4_scalar vClipCenter_Sign;
// vec4_scalar vClipRadii;
// vec4_scalar vEdgeReference;
// vec4_scalar vPartialWidths;
// vec4_scalar vClipParams1;
// vec4_scalar vClipParams2;
vec2 vPos;
vec2_scalar aTaskOrigin;
vec4_scalar aRect;
vec4_scalar aColor0;
vec4_scalar aColor1;
int32_t aFlags;
vec2_scalar aWidths;
vec2_scalar aRadii;
vec4_scalar aClipParams1;
vec4_scalar aClipParams2;
vec2_scalar get_outer_corner_scale(int32_t segment) {
vec2_scalar p;
switch (segment) {
case 0:
p = make_vec2(0.f, 0.f);
break;
case 1:
p = make_vec2(1.f, 0.f);
break;
case 2:
p = make_vec2(1.f, 1.f);
break;
case 3:
p = make_vec2(0.f, 1.f);
break;
default:
p = make_vec2(0.f);
break;
}
return p;
}
vec4_scalar mod_color(vec4_scalar color, bool is_black, bool lighter) {
float const light_black = 0.7f;
float const dark_black = 0.3f;
float const dark_scale = 0.6666667f;
float const light_scale = 1.f;
if (is_black) {
{
if (lighter) {
{
return make_vec4(make_vec3(light_black), (color).w);
}
}
return make_vec4(make_vec3(dark_black), (color).w);
}
}
if (lighter) {
{
return make_vec4(((color).sel(R,G,B))*(light_scale), (color).w);
}
}
return make_vec4(((color).sel(R,G,B))*(dark_scale), (color).w);
}
Array<vec4_scalar,2> get_colors_for_side(vec4_scalar color, int32_t style) {
Array<vec4_scalar,2> result;
bool is_black = ((color).sel(R,G,B))==(make_vec3(0.f, 0.f, 0.f));
switch (style) {
case 6:
result[0] = mod_color(color, is_black, true);
result[1] = mod_color(color, is_black, false);
break;
case 7:
result[0] = mod_color(color, is_black, false);
result[1] = mod_color(color, is_black, true);
break;
default:
result[0] = color;
result[1] = color;
break;
}
return result;
}
ALWAYS_INLINE void main(void) {
int32_t segment = (aFlags)&(255);
int32_t style0 = ((aFlags)>>(8))&(255);
int32_t style1 = ((aFlags)>>(16))&(255);
int32_t clip_mode = ((aFlags)>>(24))&(15);
vec2_scalar size = ((aRect).sel(Z,W))-((aRect).sel(X,Y));
vec2_scalar outer_scale = get_outer_corner_scale(segment);
vec2_scalar outer = (outer_scale)*(size);
vec2_scalar clip_sign = (1.f)-((2.f)*(outer_scale));
ivec2_scalar edge_axis = make_ivec2(0, 0);
vec2_scalar edge_reference = make_vec2(0.f);
switch (segment) {
case 0:
edge_axis = make_ivec2(0, 1);
edge_reference = outer;
break;
case 1:
edge_axis = make_ivec2(1, 0);
edge_reference = make_vec2(((outer).x)-((aWidths).x), (outer).y);
break;
case 2:
edge_axis = make_ivec2(0, 1);
edge_reference = (outer)-(aWidths);
break;
case 3:
edge_axis = make_ivec2(1, 0);
edge_reference = make_vec2((outer).x, ((outer).y)-((aWidths).y));
break;
case 5:
case 7:
edge_axis = make_ivec2(1, 1);
break;
case 4:
case 6:
default:
break;
}
vSegmentClipMode = make_vec2(make_float(segment), make_float(clip_mode));
vStyleEdgeAxis = make_vec4(make_float(style0), make_float(style1), make_float((edge_axis).x), make_float((edge_axis).y));
vPartialWidths = make_vec4((aWidths)/(3.f), (aWidths)/(2.f));
vPos = (size)*((aPosition).sel(X,Y));
Array<vec4_scalar,2> color0 = get_colors_for_side(aColor0, style0);
vColor00 = color0[0];
vColor01 = color0[1];
Array<vec4_scalar,2> color1 = get_colors_for_side(aColor1, style1);
vColor10 = color1[0];
vColor11 = color1[1];
vClipCenter_Sign = make_vec4((outer)+((clip_sign)*(aRadii)), clip_sign);
vClipRadii = make_vec4(aRadii, max((aRadii)-(aWidths), 0.f));
vColorLine = make_vec4(outer, ((aWidths).y)*(-((clip_sign).y)), ((aWidths).x)*((clip_sign).x));
vEdgeReference = make_vec4(edge_reference, (edge_reference)+(aWidths));
vClipParams1 = aClipParams1;
vClipParams2 = aClipParams2;
if ((clip_mode)==(3)) {
{
float radius = (aClipParams1).z;
if ((radius)>(0.5f)) {
radius += 2.f;
}
vPos = ((vClipParams1).sel(X,Y))+((radius)*(((2.f)*((aPosition).sel(X,Y)))-(1.f)));
vPos = clamp(vPos, make_vec2(0.f), size);
}
} else if ((clip_mode)==(1)) {
{
vec2_scalar center = (((aClipParams1).sel(X,Y))+((aClipParams2).sel(X,Y)))*(0.5f);
float dash_length = length(((aClipParams1).sel(X,Y))-((aClipParams2).sel(X,Y)));
float width = max((aWidths).x, (aWidths).y);
vec2_scalar r = (make_vec2(max(dash_length, width)))+(2.f);
vPos = clamp(vPos, (center)-(r), (center)+(r));
}
}
gl_Position = (uTransform)*(make_vec4(((aTaskOrigin)+((aRect).sel(X,Y)))+(vPos), 0.f, 1.f));
}
static void set_uniform_1i(VertexShaderImpl* impl, int index, int value) {
Self* self = (Self*)impl;
if (self->samplers.set_slot(index, value)) return;
switch (index) {
case 1:
assert(0); // uTransform
break;
}
}
static void set_uniform_4fv(VertexShaderImpl* impl, int index, const float *value) {
Self* self = (Self*)impl;
switch (index) {
case 1:
assert(0); // uTransform
break;
}
}
static void set_uniform_matrix4fv(VertexShaderImpl* impl, int index, const float *value) {
Self* self = (Self*)impl;
switch (index) {
case 1:
self->uTransform = mat4_scalar::load_from_ptr(value);
break;
}
}
static void load_attribs(VertexShaderImpl* impl, VertexAttrib *attribs, uint32_t start, int instance, int count) {Self* self = (Self*)impl;
load_attrib(self->aPosition, attribs[self->attrib_locations.aPosition], start, instance, count);
load_flat_attrib(self->aTaskOrigin, attribs[self->attrib_locations.aTaskOrigin], start, instance, count);
load_flat_attrib(self->aRect, attribs[self->attrib_locations.aRect], start, instance, count);
load_flat_attrib(self->aColor0, attribs[self->attrib_locations.aColor0], start, instance, count);
load_flat_attrib(self->aColor1, attribs[self->attrib_locations.aColor1], start, instance, count);
load_flat_attrib(self->aFlags, attribs[self->attrib_locations.aFlags], start, instance, count);
load_flat_attrib(self->aWidths, attribs[self->attrib_locations.aWidths], start, instance, count);
load_flat_attrib(self->aRadii, attribs[self->attrib_locations.aRadii], start, instance, count);
load_flat_attrib(self->aClipParams1, attribs[self->attrib_locations.aClipParams1], start, instance, count);
load_flat_attrib(self->aClipParams2, attribs[self->attrib_locations.aClipParams2], start, instance, count);
}
public:
struct InterpOutputs {
vec2_scalar vPos;
};
private:
ALWAYS_INLINE void store_interp_outputs(char* dest_ptr, size_t stride) {
for(int n = 0; n < 4; n++) {
auto* dest = reinterpret_cast<InterpOutputs*>(dest_ptr);
dest->vPos = get_nth(vPos, n);
dest_ptr += stride;
}
}
static void run(VertexShaderImpl* impl, char* interps, size_t interp_stride) {
Self* self = (Self*)impl;
self->main();
self->store_interp_outputs(interps, interp_stride);
}
static void init_batch(VertexShaderImpl* impl) {
Self* self = (Self*)impl; self->bind_textures(); }
public:
cs_border_segment_vert() {
set_uniform_1i_func = &set_uniform_1i;
set_uniform_4fv_func = &set_uniform_4fv;
set_uniform_matrix4fv_func = &set_uniform_matrix4fv;
init_batch_func = &init_batch;
load_attribs_func = &load_attribs;
run_primitive_func = &run;
}
};
struct cs_border_segment_frag : FragmentShaderImpl, cs_border_segment_vert {
private:
typedef cs_border_segment_frag Self;
#define oFragColor gl_FragColor
// vec4 oFragColor;
struct RectWithSize_scalar {
vec2_scalar p0;
vec2_scalar size;
RectWithSize_scalar() = default;
RectWithSize_scalar(vec2_scalar p0, vec2_scalar size) : p0(p0), size(size){}
};
struct RectWithSize {
vec2 p0;
vec2 size;
RectWithSize() = default;
RectWithSize(vec2 p0, vec2 size) : p0(p0), size(size){}
RectWithSize(vec2_scalar p0, vec2_scalar size):p0(p0),size(size){
}
IMPLICIT RectWithSize(RectWithSize_scalar s):p0(s.p0),size(s.size){
}
friend RectWithSize if_then_else(I32 c, RectWithSize t, RectWithSize e) { return RectWithSize(
if_then_else(c, t.p0, e.p0), if_then_else(c, t.size, e.size));
}};
struct RectWithEndpoint_scalar {
vec2_scalar p0;
vec2_scalar p1;
RectWithEndpoint_scalar() = default;
RectWithEndpoint_scalar(vec2_scalar p0, vec2_scalar p1) : p0(p0), p1(p1){}
};
struct RectWithEndpoint {
vec2 p0;
vec2 p1;
RectWithEndpoint() = default;
RectWithEndpoint(vec2 p0, vec2 p1) : p0(p0), p1(p1){}
RectWithEndpoint(vec2_scalar p0, vec2_scalar p1):p0(p0),p1(p1){
}
IMPLICIT RectWithEndpoint(RectWithEndpoint_scalar s):p0(s.p0),p1(s.p1){
}
friend RectWithEndpoint if_then_else(I32 c, RectWithEndpoint t, RectWithEndpoint e) { return RectWithEndpoint(
if_then_else(c, t.p0, e.p0), if_then_else(c, t.p1, e.p1));
}};
// vec4_scalar vColor00;
// vec4_scalar vColor01;
// vec4_scalar vColor10;
// vec4_scalar vColor11;
// vec4_scalar vColorLine;
// vec2_scalar vSegmentClipMode;
// vec4_scalar vStyleEdgeAxis;
// vec4_scalar vClipCenter_Sign;
// vec4_scalar vClipRadii;
// vec4_scalar vEdgeReference;
// vec4_scalar vPartialWidths;
// vec4_scalar vClipParams1;
// vec4_scalar vClipParams2;
vec2 vPos;
float compute_aa_range(vec2 position) {
return recip((fwidth(position)).x);
}
Float distance_to_line(vec2_scalar p0, vec2_scalar perp_dir, vec2 p) {
vec2 dir_to_p0 = (p0)-(p);
return dot(normalize(perp_dir), dir_to_p0);
}
Float distance_aa(float aa_range, Float signed_distance) {
Float dist = (signed_distance)*(aa_range);
return clamp((0.5f)-(dist), 0.f, 1.f);
}
Float distance_to_ellipse_approx(vec2 p, vec2_scalar inv_radii_sq, float scale) {
vec2 p_r = (p)*(inv_radii_sq);
Float g = (dot(p, p_r))-(scale);
vec2 dG = ((1.f)+(scale))*(p_r);
return (g)*(inversesqrt(dot(dG, dG)));
}
vec2_scalar inverse_radii_squared(vec2_scalar radii) {
return (1.f)/(max((radii)*(radii), 0.000001f));
}
Float distance_to_ellipse(vec2 p, vec2_scalar radii) {
return distance_to_ellipse_approx(p, inverse_radii_squared(radii), make_float((make_int(all(greaterThan(radii, make_vec2(0.f)))))&(1)));
}
vec4 evaluate_color_for_style_in_corner(vec2 clip_relative_pos, int32_t style, vec4 color0, vec4_scalar color1, vec4_scalar clip_radii, Float mix_factor, int32_t segment, float aa_range) {
switch (style) {
case 2:
{
Float d_radii_a = distance_to_ellipse(clip_relative_pos, ((clip_radii).sel(X,Y))-((vPartialWidths).sel(X,Y)));
Float d_radii_b = distance_to_ellipse(clip_relative_pos, ((clip_radii).sel(X,Y))-((2.f)*((vPartialWidths).sel(X,Y))));
Float d = min(-(d_radii_a), d_radii_b);
color0 *= distance_aa(aa_range, d);
break;
}
case 6:
case 7:
{
Float d = distance_to_ellipse(clip_relative_pos, ((clip_radii).sel(X,Y))-((vPartialWidths).sel(Z,W)));
Float alpha = distance_aa(aa_range, d);
Float swizzled_factor;
switch (segment) {
case 0:
swizzled_factor = 0.f;
break;
case 1:
swizzled_factor = mix_factor;
break;
case 2:
swizzled_factor = 1.f;
break;
case 3:
swizzled_factor = (1.f)-(mix_factor);
break;
default:
swizzled_factor = 0.f;
break;
}
;
vec4 c0 = mix(color1, color0, swizzled_factor);
vec4 c1 = mix(color0, color1, swizzled_factor);
color0 = mix(c0, c1, alpha);
break;
}
default:
break;
}
return color0;
}
vec4 evaluate_color_for_style_in_edge(vec2 pos_vec, int32_t style, vec4 color0, vec4_scalar color1, float aa_range, int32_t edge_axis_id) {
vec2_scalar edge_axis = (edge_axis_id)!=(0) ? make_vec2(0.f, 1.f) : make_vec2(1.f, 0.f);
Float pos = dot(pos_vec, edge_axis);
switch (style) {
case 2:
{
Float d = -(1.f);
float partial_width = dot((vPartialWidths).sel(X,Y), edge_axis);
if ((partial_width)>=(1.f)) {
{
vec2_scalar ref = make_vec2((dot((vEdgeReference).sel(X,Y), edge_axis))+(partial_width), (dot((vEdgeReference).sel(Z,W), edge_axis))-(partial_width));
d = min((pos)-((ref).x), ((ref).y)-(pos));
}
}
color0 *= distance_aa(aa_range, d);
break;
}
case 6:
case 7:
{
float ref = dot(((vEdgeReference).sel(X,Y))+((vPartialWidths).sel(Z,W)), edge_axis);
Float d = (pos)-(ref);
Float alpha = distance_aa(aa_range, d);
color0 = mix(color0, color1, alpha);
break;
}
default:
break;
}
return color0;
}
ALWAYS_INLINE void main(void) {
float aa_range = compute_aa_range(vPos);
vec4 color0, color1;
int32_t segment = make_int((vSegmentClipMode).x);
int32_t clip_mode = make_int((vSegmentClipMode).y);
ivec2_scalar style = make_ivec2(make_int((vStyleEdgeAxis).x), make_int((vStyleEdgeAxis).y));
ivec2_scalar edge_axis = make_ivec2(make_int((vStyleEdgeAxis).z), make_int((vStyleEdgeAxis).w));
Float mix_factor = 0.f;
if (((edge_axis).x)!=((edge_axis).y)) {
{
Float d_line = distance_to_line((vColorLine).sel(X,Y), (vColorLine).sel(Z,W), vPos);
mix_factor = distance_aa(aa_range, -(d_line));
}
}
vec2 clip_relative_pos = (vPos)-((vClipCenter_Sign).sel(X,Y));
Bool in_clip_region = all(lessThan(((vClipCenter_Sign).sel(Z,W))*(clip_relative_pos), make_vec2(0.f)));
Float d = -(1.f);
switch (clip_mode) {
case 3:
{
d = (distance((vClipParams1).sel(X,Y), vPos))-((vClipParams1).z);
break;
}
case 2:
{
bool is_vertical = ((vClipParams1).x)==(0.f);
float half_dash = is_vertical ? (vClipParams1).y : (vClipParams1).x;
Float pos = is_vertical ? (vPos).y : (vPos).x;
Bool in_dash = ((pos)<(half_dash))||((pos)>((3.f)*(half_dash)));
auto _c3_ = !(in_dash);
{
d = if_then_else(_c3_,1.f,d);
}
break;
}
case 1:
{
Float d0 = distance_to_line((vClipParams1).sel(X,Y), (vClipParams1).sel(Z,W), vPos);
Float d1 = distance_to_line((vClipParams2).sel(X,Y), (vClipParams2).sel(Z,W), vPos);
d = max(d0, -(d1));
break;
}
case 0:
default:
break;
}
auto _c4_ = in_clip_region;
{
Float d_radii_a = distance_to_ellipse(clip_relative_pos, (vClipRadii).sel(X,Y));
Float d_radii_b = distance_to_ellipse(clip_relative_pos, (vClipRadii).sel(Z,W));
Float d_radii = max(d_radii_a, -(d_radii_b));
d = if_then_else(_c4_,max(d, d_radii),d);
color0 = if_then_else(_c4_,evaluate_color_for_style_in_corner(clip_relative_pos, (style).x, vColor00, vColor01, vClipRadii, mix_factor, segment, aa_range),color0);
color1 = if_then_else(_c4_,evaluate_color_for_style_in_corner(clip_relative_pos, (style).y, vColor10, vColor11, vClipRadii, mix_factor, segment, aa_range),color1);
}
{
color0 = if_then_else(~(_c4_),evaluate_color_for_style_in_edge(vPos, (style).x, vColor00, vColor01, aa_range, (edge_axis).x),color0);
color1 = if_then_else(~(_c4_),evaluate_color_for_style_in_edge(vPos, (style).y, vColor10, vColor11, aa_range, (edge_axis).y),color1);
}
Float alpha = distance_aa(aa_range, d);
vec4 color = mix(color0, color1, mix_factor);
oFragColor = (color)*(alpha);
}
typedef cs_border_segment_vert::InterpOutputs InterpInputs;
InterpInputs interp_step;
struct InterpPerspective {
vec2 vPos;
};
InterpPerspective interp_perspective;
static void read_interp_inputs(FragmentShaderImpl* impl, const void* init_, const void* step_) {Self* self = (Self*)impl;const InterpInputs* init = (const InterpInputs*)init_;const InterpInputs* step = (const InterpInputs*)step_;
self->vPos = init_interp(init->vPos, step->vPos);
self->interp_step.vPos = step->vPos * 4.0f;
}
static void read_perspective_inputs(FragmentShaderImpl* impl, const void* init_, const void* step_) {Self* self = (Self*)impl;const InterpInputs* init = (const InterpInputs*)init_;const InterpInputs* step = (const InterpInputs*)step_;
Float w = 1.0f / self->gl_FragCoord.w;
self->interp_perspective.vPos = init_interp(init->vPos, step->vPos);
self->vPos = self->interp_perspective.vPos * w;
self->interp_step.vPos = step->vPos * 4.0f;
}
ALWAYS_INLINE void step_interp_inputs(int steps = 4) {
float chunks = steps * 0.25f;
vPos += interp_step.vPos * chunks;
}
ALWAYS_INLINE void step_perspective_inputs(int steps = 4) {
step_perspective(steps);
float chunks = steps * 0.25f;
Float w = 1.0f / gl_FragCoord.w;
interp_perspective.vPos += interp_step.vPos * chunks;
vPos = w * interp_perspective.vPos;
}
static void run(FragmentShaderImpl* impl) {
Self* self = (Self*)impl;
self->main();
self->step_interp_inputs();
}
static void skip(FragmentShaderImpl* impl, int steps) {
Self* self = (Self*)impl;
self->step_interp_inputs(steps);
}
static void run_perspective(FragmentShaderImpl* impl) {
Self* self = (Self*)impl;
self->main();
self->step_perspective_inputs();
}
static void skip_perspective(FragmentShaderImpl* impl, int steps) {
Self* self = (Self*)impl;
self->step_perspective_inputs(steps);
}
public:
cs_border_segment_frag() {
init_span_func = &read_interp_inputs;
run_func = &run;
skip_func = &skip;
enable_perspective();
init_span_w_func = &read_perspective_inputs;
run_w_func = &run_perspective;
skip_w_func = &skip_perspective;
}
};
struct cs_border_segment_program : ProgramImpl, cs_border_segment_frag {
int get_uniform(const char *name) const override {
if (strcmp("uTransform", name) == 0) { return 1; }
return -1;
}
void bind_attrib(const char* name, int index) override {
attrib_locations.bind_loc(name, index);
}
int get_attrib(const char* name) const override {
return attrib_locations.get_loc(name);
}
size_t interpolants_size() const override { return sizeof(InterpOutputs); }
VertexShaderImpl* get_vertex_shader() override {
return this;
}
FragmentShaderImpl* get_fragment_shader() override {
return this;
}
const char* get_name() const override { return "cs_border_segment"; }
static ProgramImpl* loader() { return new cs_border_segment_program; }
};