mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-13 19:44:28 +00:00
gl_engine: support render image
This commit is contained in:
parent
8149194c61
commit
d257835507
8 changed files with 247 additions and 9 deletions
|
@ -57,6 +57,10 @@ struct GlShape
|
|||
const RenderShape* rshape = nullptr;
|
||||
float viewWd;
|
||||
float viewHt;
|
||||
GLuint texId = 0;
|
||||
uint32_t texOpacity = 0;
|
||||
uint32_t texFlipY = 0;
|
||||
ColorSpace texColorSpace = ColorSpace::ABGR8888;
|
||||
RenderUpdateFlag updateFlag = None;
|
||||
unique_ptr<GlGeometry> geometry;
|
||||
};
|
||||
|
|
|
@ -56,6 +56,89 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GlGeometry::tesselate(const Surface* image, const RenderMesh* mesh, RenderUpdateFlag flag)
|
||||
{
|
||||
if (flag & RenderUpdateFlag::Image) {
|
||||
fillVertex.clear();
|
||||
fillIndex.clear();
|
||||
|
||||
if (mesh && mesh->triangleCnt) {
|
||||
fillVertex.reserve(mesh->triangleCnt * 3 * 5);
|
||||
fillIndex.reserve(mesh->triangleCnt * 3);
|
||||
|
||||
uint32_t index = 0;
|
||||
for (uint32_t i = 0; i < mesh->triangleCnt; i++) {
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].pt.y);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[0].uv.y);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].pt.y);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[1].uv.y);
|
||||
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].pt.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].pt.y);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].uv.x);
|
||||
fillVertex.push(mesh->triangles[i].vertex[2].uv.y);
|
||||
|
||||
fillIndex.push(index);
|
||||
fillIndex.push(index + 1);
|
||||
fillIndex.push(index + 2);
|
||||
index += 3;
|
||||
}
|
||||
|
||||
} else {
|
||||
fillVertex.reserve(5 * 4);
|
||||
fillIndex.reserve(6);
|
||||
|
||||
float left = 0.f;
|
||||
float top = 0.f;
|
||||
float right = image->w;
|
||||
float bottom = image->h;
|
||||
|
||||
// left top point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(top);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(1.f);
|
||||
// left bottom point
|
||||
fillVertex.push(left);
|
||||
fillVertex.push(bottom);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
fillVertex.push(0.f);
|
||||
// right top point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(top);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
// right bottom point
|
||||
fillVertex.push(right);
|
||||
fillVertex.push(bottom);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(1.f);
|
||||
fillVertex.push(0.f);
|
||||
|
||||
fillIndex.push(0);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(2);
|
||||
|
||||
fillIndex.push(2);
|
||||
fillIndex.push(1);
|
||||
fillIndex.push(3);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void GlGeometry::disableVertex(uint32_t location)
|
||||
{
|
||||
|
@ -87,7 +170,13 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
|
|||
uint32_t indexOffset = gpuBuffer->push(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
|
||||
|
||||
// vertex layout
|
||||
task->addVertexLayout(GlVertexLayout{0, 3, 3 * sizeof(float), vertexOffset});
|
||||
if (flag & RenderUpdateFlag::Image) {
|
||||
// image has two attribute: [pos, uv]
|
||||
task->addVertexLayout(GlVertexLayout{0, 3, 5 * sizeof(float), vertexOffset});
|
||||
task->addVertexLayout(GlVertexLayout{1, 2, 5 * sizeof(float), vertexOffset + 3 * sizeof(float)});
|
||||
} else {
|
||||
task->addVertexLayout(GlVertexLayout{0, 3, 3 * sizeof(float), vertexOffset});
|
||||
}
|
||||
task->setDrawRange(indexOffset, indexBuffer->count);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -189,6 +189,7 @@ public:
|
|||
~GlGeometry();
|
||||
|
||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
|
||||
bool tesselate(const Surface* image, const RenderMesh* mesh, RenderUpdateFlag flag);
|
||||
void disableVertex(uint32_t location);
|
||||
bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag);
|
||||
void updateTransform(const RenderTransform* transform, float w, float h);
|
||||
|
|
|
@ -83,7 +83,7 @@ int32_t GlProgram::getAttributeLocation(const char* name)
|
|||
|
||||
int32_t GlProgram::getUniformLocation(const char* name)
|
||||
{
|
||||
GL_CHECK(int32_t location = glGetUniformLocation(mCurrentProgram, name));
|
||||
GL_CHECK(int32_t location = glGetUniformLocation(mProgramObj, name));
|
||||
return location;
|
||||
}
|
||||
|
||||
|
|
|
@ -146,10 +146,53 @@ bool GlRenderer::blend(TVG_UNUSED BlendMethod method)
|
|||
}
|
||||
|
||||
|
||||
bool GlRenderer::renderImage(TVG_UNUSED void* data)
|
||||
bool GlRenderer::renderImage(void* data)
|
||||
{
|
||||
//TODO: render requested images
|
||||
return false;
|
||||
auto sdata = static_cast<GlShape*>(data);
|
||||
|
||||
if (!sdata) return false;
|
||||
|
||||
if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return false;
|
||||
|
||||
auto task = make_unique<GlRenderTask>(mPrograms[RT_Image].get());
|
||||
|
||||
if (!sdata->geometry->draw(task.get(), mGpuBuffer.get(), RenderUpdateFlag::Image)) return false;
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
auto matrix = sdata->geometry->getTransforMatrix();
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
// image info
|
||||
{
|
||||
uint32_t info[4] = {sdata->texColorSpace, sdata->texFlipY, sdata->texOpacity, 0};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(info, 4 * sizeof(uint32_t), true),
|
||||
4 * sizeof(uint32_t),
|
||||
});
|
||||
}
|
||||
// texture id
|
||||
{
|
||||
uint32_t loc = task->getProgram()->getUniformLocation("uTexture");
|
||||
task->addBindResource(GlBindingResource{0, sdata->texId, loc});
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,15 +239,54 @@ bool GlRenderer::dispose(RenderData data)
|
|||
auto sdata = static_cast<GlShape*>(data);
|
||||
if (!sdata) return false;
|
||||
|
||||
if (sdata->texId) glDeleteTextures(1, &sdata->texId);
|
||||
|
||||
delete sdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
RenderData GlRenderer::prepare(TVG_UNUSED Surface* surface, TVG_UNUSED const RenderMesh* mesh, TVG_UNUSED RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED Array<RenderData>& clips, TVG_UNUSED uint8_t opacity, TVG_UNUSED RenderUpdateFlag flags)
|
||||
static GLuint _genTexture(Surface* image)
|
||||
{
|
||||
//TODO:
|
||||
return nullptr;
|
||||
GLuint tex = 0;
|
||||
|
||||
GL_CHECK(glGenTextures(1, &tex));
|
||||
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, tex));
|
||||
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->data));
|
||||
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
RenderData GlRenderer::prepare(Surface* image, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, TVG_UNUSED Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
|
||||
{
|
||||
if (flags == RenderUpdateFlag::None) return nullptr;
|
||||
|
||||
auto sdata = static_cast<GlShape*>(data);
|
||||
|
||||
if (!sdata) sdata = new GlShape;
|
||||
|
||||
sdata->viewWd = static_cast<float>(surface.w);
|
||||
sdata->viewHt = static_cast<float>(surface.h);
|
||||
sdata->updateFlag = flags;
|
||||
|
||||
sdata->texId = _genTexture(image);
|
||||
sdata->texOpacity = opacity;
|
||||
sdata->texColorSpace = image->cs;
|
||||
sdata->texFlipY = (mesh && mesh->triangleCnt) ? 0 : 1;
|
||||
sdata->geometry = make_unique<GlGeometry>();
|
||||
|
||||
sdata->geometry->updateTransform(transform, sdata->viewWd, sdata->viewHt);
|
||||
|
||||
sdata->geometry->tesselate(image, mesh, flags);
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,6 +406,9 @@ void GlRenderer::initShaders()
|
|||
|
||||
// Radial Gradient Renderer
|
||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(GRADIENT_VERT_SHADER, RADIAL_GRADIENT_FRAG_SHADER)));
|
||||
|
||||
// image Renderer
|
||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(IMAGE_VERT_SHADER, IMAGE_FRAG_SHADER)));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public:
|
|||
RT_Color = 0,
|
||||
RT_LinGradient,
|
||||
RT_RadGradient,
|
||||
RT_Image,
|
||||
|
||||
RT_None,
|
||||
};
|
||||
|
|
|
@ -196,3 +196,59 @@ STR_GRADIENT_FRAG_COMMON_FUNCTIONS +
|
|||
STR_RADIAL_GRADIENT_MAIN;
|
||||
|
||||
const char* RADIAL_GRADIENT_FRAG_SHADER = STR_RADIAL_GRADIENT_FRAG_SHADER.c_str();
|
||||
|
||||
|
||||
const char* IMAGE_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||
layout (location = 0) in vec3 aLocation; \n
|
||||
layout (location = 1) in vec2 aUV; \n
|
||||
layout (std140) uniform Matrix { \n
|
||||
mat4 transform; \n
|
||||
} uMatrix; \n
|
||||
\n
|
||||
out float aOpacity; \n
|
||||
out vec2 vUV; \n
|
||||
\n
|
||||
void main() { \n
|
||||
aOpacity = aLocation.z; \n
|
||||
vUV = aUV; \n
|
||||
gl_Position = uMatrix.transform * vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
} \n
|
||||
);
|
||||
|
||||
const char* IMAGE_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||
layout(std140) uniform ColorInfo { \n
|
||||
int format; \n
|
||||
int flipY; \n
|
||||
int opacity; \n
|
||||
int dummy; \n
|
||||
} uColorInfo; \n
|
||||
uniform sampler2D uTexture; \n
|
||||
\n
|
||||
in float aOpacity; \n
|
||||
in vec2 vUV; \n
|
||||
\n
|
||||
out vec4 FragColor; \n
|
||||
\n
|
||||
void main() { \n
|
||||
vec2 uv = vUV; \n
|
||||
if (uColorInfo.flipY == 1) { uv.y = 1.0 - uv.y; } \n
|
||||
\n
|
||||
vec4 color = texture(uTexture, uv); \n
|
||||
vec4 result = color; \n
|
||||
if (uColorInfo.format == 1) { /* FMT_ARGB8888 */ \n
|
||||
result.r = color.b; \n
|
||||
result.g = color.g; \n
|
||||
result.b = color.r; \n
|
||||
result.a = color.a; \n
|
||||
} else if (uColorInfo.format == 2) { /* FMT_ABGR8888S */ \n
|
||||
result = vec4(color.rgb * color.a, color.a); \n
|
||||
} else if (uColorInfo.format == 3) { /* FMT_ARGB8888S */ \n
|
||||
result.r = color.b * color.a; \n
|
||||
result.g = color.g * color.a; \n
|
||||
result.b = color.b * color.a; \n
|
||||
result.a = color.a; \n
|
||||
} \n
|
||||
float opacity = float(uColorInfo.opacity) / 255.0; \n
|
||||
FragColor = vec4(result.rgb, result.a * opacity * aOpacity); \n
|
||||
} \n
|
||||
);
|
||||
|
|
|
@ -28,5 +28,7 @@ extern const char* COLOR_FRAG_SHADER;
|
|||
extern const char* GRADIENT_VERT_SHADER;
|
||||
extern const char* LINEAR_GRADIENT_FRAG_SHADER;
|
||||
extern const char* RADIAL_GRADIENT_FRAG_SHADER;
|
||||
extern const char* IMAGE_VERT_SHADER;
|
||||
extern const char* IMAGE_FRAG_SHADER;
|
||||
|
||||
#endif /* _TVG_GL_SHADERSRC_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue