gl_engine: support render image

This commit is contained in:
RuiwenTang 2023-09-22 18:59:34 +08:00 committed by Hermet Park
parent 8149194c61
commit d257835507
8 changed files with 247 additions and 9 deletions

View file

@ -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;
};

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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)));
}

View file

@ -36,6 +36,7 @@ public:
RT_Color = 0,
RT_LinGradient,
RT_RadGradient,
RT_Image,
RT_None,
};

View file

@ -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
);

View file

@ -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_ */