feat: revamp 2D pipeline to use SDF's for rendering
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
#version 460
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
#include "bindless.glsl"
|
||||
|
||||
layout(location = 0) in vec2 inUV;
|
||||
layout(location = 1) in vec4 inColor;
|
||||
layout(location = 2) flat in uint inTexId;
|
||||
|
||||
layout(location = 0) out vec4 outFragColor;
|
||||
|
||||
void main() {
|
||||
vec4 texColor = sampleTexture2DLinear(inTexId, inUV);
|
||||
outFragColor = texColor * inColor;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#version 460
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
layout(location = 0) in vec2 inPosition;
|
||||
layout(location = 1) in vec2 inUV;
|
||||
layout(location = 2) in vec4 inColor;
|
||||
layout(location = 3) in uint inTexId;
|
||||
|
||||
layout(location = 0) out vec2 outUV;
|
||||
layout(location = 1) out vec4 outColor;
|
||||
layout(location = 2) flat out uint outTexId;
|
||||
|
||||
layout(push_constant) uniform QuadPushConstants {
|
||||
mat4 viewProjection;
|
||||
} pcs;
|
||||
|
||||
void main() {
|
||||
gl_Position = pcs.viewProjection * vec4(inPosition, 0.0, 1.0);
|
||||
outUV = inUV;
|
||||
outColor = inColor;
|
||||
outTexId = inTexId;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#version 460
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
#include "bindless.glsl"
|
||||
#include "shape2d.glsl"
|
||||
|
||||
layout (location = 0) in vec2 inLocalPos;
|
||||
layout (location = 1) in vec2 inQuadPos;
|
||||
layout (location = 2) flat in uint inShapeIndex;
|
||||
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
float sdRoundedRect(vec2 p, vec2 halfSize, float radius)
|
||||
{
|
||||
radius = min(radius, min(halfSize.x, halfSize.y));
|
||||
vec2 q = abs(p) - halfSize + radius;
|
||||
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
|
||||
}
|
||||
|
||||
// Approximate, but exact on the boundary which is what the edge and outline need
|
||||
float sdEllipse(vec2 p, vec2 radii)
|
||||
{
|
||||
radii = max(radii, vec2(1e-4));
|
||||
float k0 = length(p / radii);
|
||||
float k1 = length(p / (radii * radii));
|
||||
return k0 < 1e-4 ? -min(radii.x, radii.y) : k0 * (k0 - 1.0) / k1;
|
||||
}
|
||||
|
||||
float sdTriangle(vec2 p, vec2 p0, vec2 p1, vec2 p2)
|
||||
{
|
||||
vec2 e0 = p1 - p0, e1 = p2 - p1, e2 = p0 - p2;
|
||||
vec2 v0 = p - p0, v1 = p - p1, v2 = p - p2;
|
||||
vec2 pq0 = v0 - e0 * clamp(dot(v0, e0) / max(dot(e0, e0), 1e-8), 0.0, 1.0);
|
||||
vec2 pq1 = v1 - e1 * clamp(dot(v1, e1) / max(dot(e1, e1), 1e-8), 0.0, 1.0);
|
||||
vec2 pq2 = v2 - e2 * clamp(dot(v2, e2) / max(dot(e2, e2), 1e-8), 0.0, 1.0);
|
||||
float winding = sign(e0.x * e2.y - e0.y * e2.x);
|
||||
vec2 d = min(min(vec2(dot(pq0, pq0), winding * (v0.x * e0.y - v0.y * e0.x)),
|
||||
vec2(dot(pq1, pq1), winding * (v1.x * e1.y - v1.y * e1.x))),
|
||||
vec2(dot(pq2, pq2), winding * (v2.x * e2.y - v2.y * e2.x)));
|
||||
return -sqrt(d.x) * sign(d.y);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
Shape2D shape = pcs.shapeBuffer.shapes[inShapeIndex];
|
||||
|
||||
float dist;
|
||||
if (shape.type == SHAPE_ELLIPSE) {
|
||||
dist = sdEllipse(inLocalPos, shape.halfSize);
|
||||
} else if (shape.type == SHAPE_TRIANGLE) {
|
||||
dist = sdTriangle(inLocalPos, shape.p0, shape.p1, shape.p2);
|
||||
} else {
|
||||
dist = sdRoundedRect(inLocalPos, shape.halfSize, shape.cornerRadius);
|
||||
}
|
||||
|
||||
// Outlines grow inwards so the outer edge matches the filled shape
|
||||
if (shape.outline > 0.0) {
|
||||
dist = abs(dist + shape.outline * 0.5) - shape.outline * 0.5;
|
||||
}
|
||||
|
||||
float edgeWidth = max(fwidth(dist), 1e-4);
|
||||
float coverage = clamp(0.5 - dist / edgeWidth, 0.0, 1.0);
|
||||
|
||||
vec2 uv = mix(shape.uvRect.xy, shape.uvRect.zw, clamp(inQuadPos, 0.0, 1.0));
|
||||
vec4 texColor = sampleTexture2D(shape.textureId, shape.samplerId, uv);
|
||||
|
||||
outFragColor = texColor * shape.color;
|
||||
outFragColor.a *= coverage;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#extension GL_EXT_buffer_reference : require
|
||||
#extension GL_EXT_scalar_block_layout : require
|
||||
|
||||
#define SHAPE_RECT 0
|
||||
#define SHAPE_ELLIPSE 1
|
||||
#define SHAPE_TRIANGLE 2
|
||||
|
||||
// Mirrors Shape2D in Renderer2D.h
|
||||
struct Shape2D {
|
||||
vec2 center;
|
||||
vec2 halfSize;
|
||||
vec4 color;
|
||||
vec4 uvRect;
|
||||
vec2 p0;
|
||||
vec2 p1;
|
||||
vec2 p2;
|
||||
float rotation;
|
||||
float outline;
|
||||
float cornerRadius;
|
||||
uint type;
|
||||
uint textureId;
|
||||
uint samplerId;
|
||||
};
|
||||
|
||||
layout (buffer_reference, scalar) readonly buffer Shape2DBuffer {
|
||||
Shape2D shapes[];
|
||||
};
|
||||
|
||||
layout (push_constant, scalar) uniform Shape2DPushConstants {
|
||||
mat4 projection;
|
||||
Shape2DBuffer shapeBuffer;
|
||||
} pcs;
|
||||
@@ -0,0 +1,33 @@
|
||||
#version 460
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
|
||||
#include "shape2d.glsl"
|
||||
|
||||
layout (location = 0) out vec2 outLocalPos;
|
||||
layout (location = 1) out vec2 outQuadPos;
|
||||
layout (location = 2) flat out uint outShapeIndex;
|
||||
|
||||
// Room for the antialiased edge outside the shape's bounds
|
||||
const float EDGE_MARGIN = 1.0;
|
||||
|
||||
const vec2 CORNERS[6] = vec2[](
|
||||
vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(1.0, 1.0),
|
||||
vec2(-1.0, -1.0), vec2(1.0, 1.0), vec2(-1.0, 1.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
Shape2D shape = pcs.shapeBuffer.shapes[gl_InstanceIndex];
|
||||
|
||||
vec2 corner = CORNERS[gl_VertexIndex];
|
||||
vec2 localPos = corner * (shape.halfSize + EDGE_MARGIN);
|
||||
|
||||
float c = cos(shape.rotation);
|
||||
float s = sin(shape.rotation);
|
||||
vec2 rotated = vec2(localPos.x * c - localPos.y * s, localPos.x * s + localPos.y * c);
|
||||
|
||||
gl_Position = pcs.projection * vec4(shape.center + rotated, 0.0, 1.0);
|
||||
outLocalPos = localPos;
|
||||
outQuadPos = localPos / max(shape.halfSize, vec2(1e-6)) * 0.5 + 0.5;
|
||||
outShapeIndex = gl_InstanceIndex;
|
||||
}
|
||||
Reference in New Issue
Block a user