Tess Renderer: compute gradient F in vertex shader.

Compute gradient F in vertex shader as discussed on Slack with @csmartdalton

Diffs=
d4d6067a3 Fix radial gradient interpolation
14026d5dc Compute gradient F in vertex shader.
This commit is contained in:
luigi-rosso
2022-08-24 21:40:04 +00:00
parent a7bf91d9dd
commit 7d504de290
4 changed files with 663 additions and 567 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -34,14 +34,27 @@ void main() {
@vs vs_path
uniform vs_path_params {
mat4 mvp;
int fillType;
vec2 gradientStart;
vec2 gradientEnd;
};
in vec2 position;
out vec2 pos;
out vec2 gradient_uv;
void main() {
pos = position;
gl_Position = mvp * vec4(position, 0.0, 1.0);
if(fillType == 1) {
// Linear gradient.
vec2 toEnd = gradientEnd - gradientStart;
float lengthSquared = toEnd.x * toEnd.x + toEnd.y * toEnd.y;
gradient_uv.x = dot(position - gradientStart, toEnd) / lengthSquared;
}
else if(fillType == 2) {
// fillType == 2 (Radial gradient)
gradient_uv = (position - gradientStart) / distance(gradientStart, gradientEnd);
}
}
@end
@@ -51,12 +64,10 @@ uniform fs_path_uniforms {
int fillType;
vec4 colors[16];
vec4 stops[4];
vec2 gradientStart;
vec2 gradientEnd;
int stopCount;
};
in vec2 pos;
in vec2 gradient_uv;
out vec4 frag_color;
void main() {
@@ -65,18 +76,7 @@ void main() {
frag_color = colors[0];
}
else {
float f;
if(fillType == 1) {
// Linear gradient.
vec2 toEnd = gradientEnd - gradientStart;
float lengthSquared = toEnd.x * toEnd.x + toEnd.y * toEnd.y;
f = dot(pos - gradientStart, toEnd) / lengthSquared;
}
else {
// fillType == 2 (Radial gradient)
f = distance(gradientStart, pos) / distance(gradientStart, gradientEnd);
}
float f = fillType == 1 ? gradient_uv.x : length(gradient_uv);
vec4 color =
mix(colors[0], colors[1], smoothstep(stops[0][0], stops[0][1], f));
for (int i = 1; i < 15; ++i)

View File

@@ -636,18 +636,18 @@ public:
m_end = Vec2D(cx + radius, cy);
}
void bind(fs_path_uniforms_t& uniforms) {
void bind(vs_path_params_t& vertexUniforms, fs_path_uniforms_t& fragmentUniforms) {
auto stopCount = m_stops.size();
uniforms.fillType = m_type;
uniforms.stopCount = stopCount;
uniforms.gradientStart = m_start;
uniforms.gradientEnd = m_end;
vertexUniforms.fillType = fragmentUniforms.fillType = m_type;
vertexUniforms.gradientStart = m_start;
vertexUniforms.gradientEnd = m_end;
fragmentUniforms.stopCount = stopCount;
for (int i = 0; i < stopCount; i++) {
auto colorBufferIndex = i * 4;
for (int j = 0; j < 4; j++) {
uniforms.colors[i][j] = m_colors[colorBufferIndex + j];
fragmentUniforms.colors[i][j] = m_colors[colorBufferIndex + j];
}
uniforms.stops[i / 4][i % 4] = m_stops[i];
fragmentUniforms.stops[i / 4][i % 4] = m_stops[i];
}
}
};
@@ -737,10 +737,11 @@ public:
void shader(rcp<RenderShader> shader) override { m_shader = shader; }
void draw(SokolRenderPath* path) {
void draw(vs_path_params_t& vertexUniforms, SokolRenderPath* path) {
if (m_shader) {
static_cast<SokolGradient*>(m_shader.get())->bind(m_uniforms);
static_cast<SokolGradient*>(m_shader.get())->bind(vertexUniforms, m_uniforms);
}
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, SG_RANGE_REF(vertexUniforms));
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_fs_path_uniforms, SG_RANGE_REF(m_uniforms));
if (m_stroke != nullptr) {
if (m_strokeDirty) {
@@ -943,9 +944,8 @@ void SokolTessRenderer::drawPath(RenderPath* path, RenderPaint* paint) {
case BlendMode::multiply: setPipeline(m_pathMultiplyPipeline[m_clipCount]); break;
default: setPipeline(m_pathScreenPipeline[m_clipCount]); break;
}
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_params, SG_RANGE_REF(vs_params));
static_cast<SokolRenderPaint*>(paint)->draw(static_cast<SokolRenderPath*>(path));
static_cast<SokolRenderPaint*>(paint)->draw(vs_params, static_cast<SokolRenderPath*>(path));
}
SokolRenderImage::SokolRenderImage(const uint8_t* bytes, uint32_t width, uint32_t height) :