mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
gl_engine: fix gradient rendering error
* Fix error when handle GradientTransform calculation. And move the inv calculation into gradient vertex shader. * Fix cubic tessellation not close the last point
This commit is contained in:
parent
d55b8afd6a
commit
25d43ddacf
3 changed files with 74 additions and 38 deletions
|
@ -20,6 +20,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tvgMath.h"
|
||||
#include "tvgGlRenderer.h"
|
||||
#include "tvgGlGpuBuffer.h"
|
||||
#include "tvgGlGeometry.h"
|
||||
|
@ -600,6 +601,22 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
// matrix buffer
|
||||
{
|
||||
auto matrix = sdata.geometry->getTransforMatrix();
|
||||
|
||||
auto gradientTransform = fill->transform();
|
||||
float invMat4[16];
|
||||
if (!mathIdentity(const_cast<const Matrix*>(&gradientTransform))) {
|
||||
Matrix inv{};
|
||||
mathInverse(&gradientTransform , &inv);
|
||||
|
||||
GET_MATRIX44(inv, invMat4);
|
||||
} else {
|
||||
memset(invMat4, 0, 16 * sizeof(float));
|
||||
invMat4[0] = 1.f;
|
||||
invMat4[5] = 1.f;
|
||||
invMat4[10] = 1.f;
|
||||
invMat4[15] = 1.f;
|
||||
}
|
||||
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
uint32_t viewOffset = mGpuBuffer->push(matrix, 16 * sizeof(float), true);
|
||||
|
@ -621,6 +638,17 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
|
||||
loc = task->getProgram()->getUniformBlockIndex("InvMatrix");
|
||||
viewOffset = mGpuBuffer->push(invMat4, 16 * sizeof(float), true);
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
viewOffset,
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
|
||||
// gradient block
|
||||
|
@ -633,29 +661,31 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
|
||||
GlLinearGradientBlock gradientBlock;
|
||||
|
||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
||||
uint32_t nStops = 0;
|
||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||
if (i > 0 && gradientBlock.stopPoints[nStops - 1] > stops[i].offset) continue;
|
||||
|
||||
gradientBlock.stopPoints[i] = stops[i].offset;
|
||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||
nStops++;
|
||||
}
|
||||
gradientBlock.nStops[0] = nStops * 1.f;
|
||||
|
||||
float x1, x2, y1, y2;
|
||||
linearFill->linear(&x1, &y1, &x2, &y2);
|
||||
|
||||
auto transform = linearFill->transform();
|
||||
|
||||
gradientBlock.startPos[0] = x1 * transform.e11 + transform.e13;
|
||||
gradientBlock.startPos[1] = y1 * transform.e22 + transform.e23;
|
||||
gradientBlock.stopPos[0] = x2 * transform.e11 + transform.e13;
|
||||
gradientBlock.stopPos[1] = y2 * transform.e22 + transform.e23;
|
||||
gradientBlock.startPos[0] = x1;
|
||||
gradientBlock.startPos[1] = y1;
|
||||
gradientBlock.stopPos[0] = x2;
|
||||
gradientBlock.stopPos[1] = y2;
|
||||
|
||||
gradientBinding = GlBindingResource{
|
||||
1,
|
||||
2,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(&gradientBlock, sizeof(GlLinearGradientBlock), true),
|
||||
|
@ -666,28 +696,31 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
|
||||
GlRadialGradientBlock gradientBlock;
|
||||
|
||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
||||
|
||||
uint32_t nStops = 0;
|
||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||
if (i > 0 && gradientBlock.stopPoints[nStops - 1] > stops[i].offset) continue;
|
||||
|
||||
gradientBlock.stopPoints[i] = stops[i].offset;
|
||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||
nStops++;
|
||||
}
|
||||
gradientBlock.nStops[0] = nStops * 1.f;
|
||||
|
||||
float x, y, r;
|
||||
radialFill->radial(&x, &y, &r);
|
||||
|
||||
auto transform = radialFill->transform();
|
||||
|
||||
gradientBlock.centerPos[0] = x * transform.e11 + transform.e13;
|
||||
gradientBlock.centerPos[1] = y * transform.e22 + transform.e23;
|
||||
gradientBlock.radius[0] = r * transform.e11;
|
||||
gradientBlock.centerPos[0] = x;
|
||||
gradientBlock.centerPos[1] = y;
|
||||
gradientBlock.radius[0] = r;
|
||||
|
||||
gradientBinding = GlBindingResource{
|
||||
1,
|
||||
2,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(&gradientBlock, sizeof(GlRadialGradientBlock), true),
|
||||
|
|
|
@ -52,11 +52,15 @@ out vec2 vPos;
|
|||
layout(std140) uniform Matrix { \n
|
||||
mat4 transform; \n
|
||||
} uMatrix; \n
|
||||
layout(std140) uniform InvMatrix { \n
|
||||
mat4 transform; \n
|
||||
} uInvMatrix; \n
|
||||
\n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_Position = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||
vPos = aLocation; \n
|
||||
vec4 pos = uInvMatrix.transform * vec4(aLocation, 0.0, 1.0); \n
|
||||
vPos = pos.xy / pos.w; \n
|
||||
});
|
||||
|
||||
|
||||
|
@ -89,20 +93,23 @@ float gradientWrap(float d)
|
|||
return clamp(d, 0.0, 1.0); \n
|
||||
} \n
|
||||
\n
|
||||
int i = 1; \n
|
||||
while (d > 1.0) { \n
|
||||
d = d - 1.0; \n
|
||||
i *= -1; \n
|
||||
if (spread == 1) { /* Reflect */ \n
|
||||
float n = mod(d, 2.0); \n
|
||||
if (n > 1.0) \n
|
||||
{ \n
|
||||
n = 2.0 - n; \n
|
||||
} \n
|
||||
return n; \n
|
||||
} \n
|
||||
\n
|
||||
if (spread == 2) { /* Reflect */ \n
|
||||
return smoothstep(0.0, 1.0, d); \n
|
||||
if (spread == 2) { /* Repeat */ \n
|
||||
float n = mod(d, 1.0); \n
|
||||
if (n < 0.0) \n
|
||||
{ \n
|
||||
n += 1.0 + n; \n
|
||||
} \n
|
||||
return n; \n
|
||||
} \n
|
||||
\n
|
||||
if (i == 1) \n
|
||||
return smoothstep(0.0, 1.0, d); \n
|
||||
else \n
|
||||
return smoothstep(1.0, 0.0, d); \n
|
||||
} \n
|
||||
\n
|
||||
vec4 gradient(float t) \n
|
||||
|
@ -112,11 +119,11 @@ vec4 gradient(float t)
|
|||
int count = int(uGradientInfo.nStops[0]); \n
|
||||
if (t <= gradientStop(0)) \n
|
||||
{ \n
|
||||
col += uGradientInfo.stopColors[0]; \n
|
||||
col = uGradientInfo.stopColors[0]; \n
|
||||
} \n
|
||||
else if (t >= gradientStop(count - 1)) \n
|
||||
{ \n
|
||||
col += uGradientInfo.stopColors[count - 1]; \n
|
||||
col = uGradientInfo.stopColors[count - 1]; \n
|
||||
} \n
|
||||
else \n
|
||||
{ \n
|
||||
|
@ -126,7 +133,7 @@ vec4 gradient(float t)
|
|||
float stopi1 = gradientStop(i + 1); \n
|
||||
if (t > stopi && t <stopi1) \n
|
||||
{ \n
|
||||
col += (uGradientInfo.stopColors[i] * (1. - gradientStep(stopi, stopi1, t))); \n
|
||||
col = (uGradientInfo.stopColors[i] * (1. - gradientStep(stopi, stopi1, t))); \n
|
||||
col += (uGradientInfo.stopColors[i + 1] * gradientStep(stopi, stopi1, t)); \n
|
||||
break; \n
|
||||
} \n
|
||||
|
@ -163,15 +170,13 @@ void main()
|
|||
\n
|
||||
vec2 ba = ed - st; \n
|
||||
\n
|
||||
float t = dot(pos - st, ba) / dot(ba, ba); \n
|
||||
float t = abs(dot(pos - st, ba) / dot(ba, ba)); \n
|
||||
\n
|
||||
t = gradientWrap(t); \n
|
||||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
FragColor = vec4(finalCol.rgb * finalCol.a, finalCol.a); \n
|
||||
FragColor = vec4(color.rgb * color.a, color.a); \n
|
||||
});
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
|
@ -198,9 +203,7 @@ void main()
|
|||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
FragColor = vec4(finalCol.rgb * finalCol.a, finalCol.a); \n
|
||||
FragColor = vec4(color.rgb * color.a, color.a); \n
|
||||
});
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_FRAG_SHADER =
|
||||
|
|
|
@ -2154,7 +2154,7 @@ void BWTessellator::tessellate(const RenderShape *rshape)
|
|||
|
||||
float step = 1.f / stepCount;
|
||||
|
||||
for (uint32_t s = 1; s < static_cast<uint32_t>(stepCount); s++) {
|
||||
for (uint32_t s = 1; s <= static_cast<uint32_t>(stepCount); s++) {
|
||||
auto pt = bezPointAt(curve, step * s);
|
||||
auto currIndex = pushVertex(pt.x, pt.y);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue