mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 21:53:41 +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.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "tvgMath.h"
|
||||||
#include "tvgGlRenderer.h"
|
#include "tvgGlRenderer.h"
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
#include "tvgGlGeometry.h"
|
#include "tvgGlGeometry.h"
|
||||||
|
@ -600,6 +601,22 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
||||||
// matrix buffer
|
// matrix buffer
|
||||||
{
|
{
|
||||||
auto matrix = sdata.geometry->getTransforMatrix();
|
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 loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||||
|
|
||||||
uint32_t viewOffset = mGpuBuffer->push(matrix, 16 * sizeof(float), true);
|
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),
|
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
|
// gradient block
|
||||||
|
@ -633,29 +661,31 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
||||||
|
|
||||||
GlLinearGradientBlock gradientBlock;
|
GlLinearGradientBlock gradientBlock;
|
||||||
|
|
||||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
|
||||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||||
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
||||||
|
uint32_t nStops = 0;
|
||||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
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.stopPoints[i] = stops[i].offset;
|
||||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 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 + 2] = stops[i].b / 255.f;
|
||||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||||
|
nStops++;
|
||||||
}
|
}
|
||||||
|
gradientBlock.nStops[0] = nStops * 1.f;
|
||||||
|
|
||||||
float x1, x2, y1, y2;
|
float x1, x2, y1, y2;
|
||||||
linearFill->linear(&x1, &y1, &x2, &y2);
|
linearFill->linear(&x1, &y1, &x2, &y2);
|
||||||
|
|
||||||
auto transform = linearFill->transform();
|
gradientBlock.startPos[0] = x1;
|
||||||
|
gradientBlock.startPos[1] = y1;
|
||||||
gradientBlock.startPos[0] = x1 * transform.e11 + transform.e13;
|
gradientBlock.stopPos[0] = x2;
|
||||||
gradientBlock.startPos[1] = y1 * transform.e22 + transform.e23;
|
gradientBlock.stopPos[1] = y2;
|
||||||
gradientBlock.stopPos[0] = x2 * transform.e11 + transform.e13;
|
|
||||||
gradientBlock.stopPos[1] = y2 * transform.e22 + transform.e23;
|
|
||||||
|
|
||||||
gradientBinding = GlBindingResource{
|
gradientBinding = GlBindingResource{
|
||||||
1,
|
2,
|
||||||
loc,
|
loc,
|
||||||
mGpuBuffer->getBufferId(),
|
mGpuBuffer->getBufferId(),
|
||||||
mGpuBuffer->push(&gradientBlock, sizeof(GlLinearGradientBlock), true),
|
mGpuBuffer->push(&gradientBlock, sizeof(GlLinearGradientBlock), true),
|
||||||
|
@ -666,28 +696,31 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
||||||
|
|
||||||
GlRadialGradientBlock gradientBlock;
|
GlRadialGradientBlock gradientBlock;
|
||||||
|
|
||||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
|
||||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||||
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
gradientBlock.nStops[2] = static_cast<int32_t>(fill->spread()) * 1.f;
|
||||||
|
|
||||||
|
uint32_t nStops = 0;
|
||||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
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.stopPoints[i] = stops[i].offset;
|
||||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 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 + 2] = stops[i].b / 255.f;
|
||||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||||
|
nStops++;
|
||||||
}
|
}
|
||||||
|
gradientBlock.nStops[0] = nStops * 1.f;
|
||||||
|
|
||||||
float x, y, r;
|
float x, y, r;
|
||||||
radialFill->radial(&x, &y, &r);
|
radialFill->radial(&x, &y, &r);
|
||||||
|
|
||||||
auto transform = radialFill->transform();
|
gradientBlock.centerPos[0] = x;
|
||||||
|
gradientBlock.centerPos[1] = y;
|
||||||
gradientBlock.centerPos[0] = x * transform.e11 + transform.e13;
|
gradientBlock.radius[0] = r;
|
||||||
gradientBlock.centerPos[1] = y * transform.e22 + transform.e23;
|
|
||||||
gradientBlock.radius[0] = r * transform.e11;
|
|
||||||
|
|
||||||
gradientBinding = GlBindingResource{
|
gradientBinding = GlBindingResource{
|
||||||
1,
|
2,
|
||||||
loc,
|
loc,
|
||||||
mGpuBuffer->getBufferId(),
|
mGpuBuffer->getBufferId(),
|
||||||
mGpuBuffer->push(&gradientBlock, sizeof(GlRadialGradientBlock), true),
|
mGpuBuffer->push(&gradientBlock, sizeof(GlRadialGradientBlock), true),
|
||||||
|
|
|
@ -52,11 +52,15 @@ out vec2 vPos;
|
||||||
layout(std140) uniform Matrix { \n
|
layout(std140) uniform Matrix { \n
|
||||||
mat4 transform; \n
|
mat4 transform; \n
|
||||||
} uMatrix; \n
|
} uMatrix; \n
|
||||||
|
layout(std140) uniform InvMatrix { \n
|
||||||
|
mat4 transform; \n
|
||||||
|
} uInvMatrix; \n
|
||||||
\n
|
\n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
gl_Position = uMatrix.transform * vec4(aLocation, 0.0, 1.0); \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
|
return clamp(d, 0.0, 1.0); \n
|
||||||
} \n
|
} \n
|
||||||
\n
|
\n
|
||||||
int i = 1; \n
|
if (spread == 1) { /* Reflect */ \n
|
||||||
while (d > 1.0) { \n
|
float n = mod(d, 2.0); \n
|
||||||
d = d - 1.0; \n
|
if (n > 1.0) \n
|
||||||
i *= -1; \n
|
{ \n
|
||||||
|
n = 2.0 - n; \n
|
||||||
|
} \n
|
||||||
|
return n; \n
|
||||||
} \n
|
} \n
|
||||||
\n
|
\n
|
||||||
if (spread == 2) { /* Reflect */ \n
|
if (spread == 2) { /* Repeat */ \n
|
||||||
return smoothstep(0.0, 1.0, d); \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
|
||||||
\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
|
||||||
\n
|
\n
|
||||||
vec4 gradient(float t) \n
|
vec4 gradient(float t) \n
|
||||||
|
@ -112,11 +119,11 @@ vec4 gradient(float t)
|
||||||
int count = int(uGradientInfo.nStops[0]); \n
|
int count = int(uGradientInfo.nStops[0]); \n
|
||||||
if (t <= gradientStop(0)) \n
|
if (t <= gradientStop(0)) \n
|
||||||
{ \n
|
{ \n
|
||||||
col += uGradientInfo.stopColors[0]; \n
|
col = uGradientInfo.stopColors[0]; \n
|
||||||
} \n
|
} \n
|
||||||
else if (t >= gradientStop(count - 1)) \n
|
else if (t >= gradientStop(count - 1)) \n
|
||||||
{ \n
|
{ \n
|
||||||
col += uGradientInfo.stopColors[count - 1]; \n
|
col = uGradientInfo.stopColors[count - 1]; \n
|
||||||
} \n
|
} \n
|
||||||
else \n
|
else \n
|
||||||
{ \n
|
{ \n
|
||||||
|
@ -126,7 +133,7 @@ vec4 gradient(float t)
|
||||||
float stopi1 = gradientStop(i + 1); \n
|
float stopi1 = gradientStop(i + 1); \n
|
||||||
if (t > stopi && t <stopi1) \n
|
if (t > stopi && t <stopi1) \n
|
||||||
{ \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
|
col += (uGradientInfo.stopColors[i + 1] * gradientStep(stopi, stopi1, t)); \n
|
||||||
break; \n
|
break; \n
|
||||||
} \n
|
} \n
|
||||||
|
@ -163,15 +170,13 @@ void main()
|
||||||
\n
|
\n
|
||||||
vec2 ba = ed - st; \n
|
vec2 ba = ed - st; \n
|
||||||
\n
|
\n
|
||||||
float t = dot(pos - st, ba) / dot(ba, ba); \n
|
float t = abs(dot(pos - st, ba) / dot(ba, ba)); \n
|
||||||
\n
|
\n
|
||||||
t = gradientWrap(t); \n
|
t = gradientWrap(t); \n
|
||||||
\n
|
\n
|
||||||
vec4 color = gradient(t); \n
|
vec4 color = gradient(t); \n
|
||||||
\n
|
\n
|
||||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
FragColor = vec4(color.rgb * color.a, color.a); \n
|
||||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
|
||||||
FragColor = vec4(finalCol.rgb * finalCol.a, finalCol.a); \n
|
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||||
|
@ -198,9 +203,7 @@ void main()
|
||||||
\n
|
\n
|
||||||
vec4 color = gradient(t); \n
|
vec4 color = gradient(t); \n
|
||||||
\n
|
\n
|
||||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
FragColor = vec4(color.rgb * color.a, color.a); \n
|
||||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
|
||||||
FragColor = vec4(finalCol.rgb * finalCol.a, finalCol.a); \n
|
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string STR_LINEAR_GRADIENT_FRAG_SHADER =
|
std::string STR_LINEAR_GRADIENT_FRAG_SHADER =
|
||||||
|
|
|
@ -2154,7 +2154,7 @@ void BWTessellator::tessellate(const RenderShape *rshape)
|
||||||
|
|
||||||
float step = 1.f / stepCount;
|
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 pt = bezPointAt(curve, step * s);
|
||||||
auto currIndex = pushVertex(pt.x, pt.y);
|
auto currIndex = pushVertex(pt.x, pt.y);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue