mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-25 07:39:02 +00:00
gl_engine: gradient implementation
Change-Id: If2413328437847d52ba1badc3b5c510fdd47ccd3
This commit is contained in:
parent
5f100b8cff
commit
af190033bb
16 changed files with 1028 additions and 132 deletions
5
src/lib/gl_engine/meson.build
Normal file → Executable file
5
src/lib/gl_engine/meson.build
Normal file → Executable file
|
@ -3,13 +3,18 @@ source_file = [
|
|||
'tvgGlGeometry.h',
|
||||
'tvgGlGpuBuffer.h',
|
||||
'tvgGlProgram.h',
|
||||
'tvgGlPropertyInterface.h',
|
||||
'tvgGlRenderer.h',
|
||||
'tvgGlRendererProperties.h',
|
||||
'tvgGlRenderTask.h',
|
||||
'tvgGlShader.h',
|
||||
'tvgGlShaderSrc.h',
|
||||
'tvgGlGeometry.cpp',
|
||||
'tvgGlGpuBuffer.cpp',
|
||||
'tvgGlProgram.cpp',
|
||||
'tvgGlPropertyInterface.cpp',
|
||||
'tvgGlRenderer.cpp',
|
||||
'tvgGlRenderTask.cpp',
|
||||
'tvgGlShader.cpp',
|
||||
'tvgGlShaderSrc.cpp',
|
||||
]
|
||||
|
|
1
src/lib/gl_engine/tvgGlCommon.h
Normal file → Executable file
1
src/lib/gl_engine/tvgGlCommon.h
Normal file → Executable file
|
@ -24,6 +24,7 @@
|
|||
#define _TVG_GL_COMMON_H_
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#define GL_CHECK(x) \
|
||||
|
|
103
src/lib/gl_engine/tvgGlGeometry.cpp
Normal file → Executable file
103
src/lib/gl_engine/tvgGlGeometry.cpp
Normal file → Executable file
|
@ -33,6 +33,17 @@ uint32_t GlGeometry::getPrimitiveCount()
|
|||
}
|
||||
|
||||
|
||||
const GlSize GlGeometry::getPrimitiveSize(const uint32_t primitiveIndex) const
|
||||
{
|
||||
if (primitiveIndex >= mPrimitives.size())
|
||||
{
|
||||
return GlSize();
|
||||
}
|
||||
GlSize size = mPrimitives[primitiveIndex].mBottomRight - mPrimitives[primitiveIndex].mTopLeft;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
bool GlGeometry::decomposeOutline(const Shape &shape)
|
||||
{
|
||||
const PathCommand *cmds = nullptr;
|
||||
|
@ -46,43 +57,63 @@ bool GlGeometry::decomposeOutline(const Shape &shape)
|
|||
return false;
|
||||
|
||||
GlPrimitive* curPrimitive = nullptr;
|
||||
GlPoint min = { FLT_MAX, FLT_MAX };
|
||||
GlPoint max = { 0.0f, 0.0f };
|
||||
|
||||
for (size_t i = 0; i < cmdCnt; ++i)
|
||||
{
|
||||
switch (*(cmds + i))
|
||||
{
|
||||
case PathCommand::Close:
|
||||
{
|
||||
if (curPrimitive && curPrimitive->mAAPoints.size() > 0 &&
|
||||
(curPrimitive->mAAPoints[0].orgPt != curPrimitive->mAAPoints.back().orgPt) )
|
||||
switch (*(cmds + i)) {
|
||||
case PathCommand::Close: {
|
||||
if (curPrimitive)
|
||||
{
|
||||
curPrimitive->mAAPoints.push_back(curPrimitive->mAAPoints[0].orgPt);
|
||||
if (curPrimitive->mAAPoints.size() > 0 &&
|
||||
(curPrimitive->mAAPoints[0].orgPt != curPrimitive->mAAPoints.back().orgPt))
|
||||
{
|
||||
curPrimitive->mAAPoints.push_back(curPrimitive->mAAPoints[0].orgPt);
|
||||
}
|
||||
curPrimitive->mIsClosed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PathCommand::MoveTo:
|
||||
mPrimitives.push_back(GlPrimitive());
|
||||
curPrimitive = &mPrimitives.back();
|
||||
__attribute__ ((fallthrough));
|
||||
case PathCommand::LineTo:
|
||||
{
|
||||
case PathCommand::MoveTo: {
|
||||
if (curPrimitive)
|
||||
{
|
||||
addPoint(*curPrimitive, pts[0]);
|
||||
curPrimitive->mTopLeft = min;
|
||||
curPrimitive->mBottomRight = max;
|
||||
if (curPrimitive->mAAPoints.size() > 2 &&
|
||||
(curPrimitive->mAAPoints[0].orgPt == curPrimitive->mAAPoints.back().orgPt))
|
||||
{
|
||||
curPrimitive->mIsClosed = true;
|
||||
}
|
||||
}
|
||||
mPrimitives.push_back(GlPrimitive());
|
||||
curPrimitive = &mPrimitives.back();
|
||||
}
|
||||
__attribute__ ((fallthrough));
|
||||
case PathCommand::LineTo: {
|
||||
if (curPrimitive)
|
||||
{
|
||||
addPoint(*curPrimitive, pts[0], min, max);
|
||||
}
|
||||
pts++;
|
||||
break;
|
||||
}
|
||||
case PathCommand::CubicTo:
|
||||
{
|
||||
case PathCommand::CubicTo: {
|
||||
if (curPrimitive)
|
||||
{
|
||||
decomposeCubicCurve(*curPrimitive, curPrimitive->mAAPoints.back().orgPt, pts[0], pts[1], pts[2]);
|
||||
decomposeCubicCurve(*curPrimitive, curPrimitive->mAAPoints.back().orgPt, pts[0], pts[1], pts[2], min, max);
|
||||
}
|
||||
pts += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curPrimitive)
|
||||
{
|
||||
curPrimitive->mTopLeft = min;
|
||||
curPrimitive->mBottomRight = max;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -107,20 +138,30 @@ bool GlGeometry::generateAAPoints(TVG_UNUSED const Shape &shape, float strokeWd,
|
|||
|
||||
size_t fPoint = 0;
|
||||
size_t sPoint = 1;
|
||||
for (size_t i = 0; i < nPoints; ++i)
|
||||
for (size_t i = 0; i < nPoints - 1; ++i)
|
||||
{
|
||||
fPoint = i;
|
||||
sPoint = i + 1;
|
||||
if (fPoint == nPoints - 1)
|
||||
if (shapeGeometry.mIsClosed && sPoint == nPoints - 1)
|
||||
{
|
||||
sPoint = 0;
|
||||
}
|
||||
|
||||
GlPoint normal = getNormal(aaPts[fPoint].orgPt, aaPts[sPoint].orgPt);
|
||||
|
||||
normalInfo[fPoint].normal1 = normal;
|
||||
normalInfo[sPoint].normal2 = normal;
|
||||
}
|
||||
normalInfo[0].normal2 = normalInfo[0].normal1;
|
||||
normalInfo[nPoints - 1].normal1 = normalInfo[nPoints - 1].normal2;
|
||||
if (shapeGeometry.mIsClosed)
|
||||
{
|
||||
normalInfo[nPoints - 1].normal1 = normalInfo[0].normal1;
|
||||
normalInfo[nPoints - 1].normal2 = normalInfo[0].normal2;
|
||||
}
|
||||
else
|
||||
{
|
||||
normalInfo[nPoints - 1].normal1 = normalInfo[nPoints - 1].normal2;
|
||||
normalInfo[0].normal2 = normalInfo[0].normal1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < nPoints; ++i)
|
||||
{
|
||||
|
@ -133,7 +174,7 @@ bool GlGeometry::generateAAPoints(TVG_UNUSED const Shape &shape, float strokeWd,
|
|||
else
|
||||
normalInfo[i].normalF = GlPoint(0, 0);
|
||||
|
||||
if (flag & RenderUpdateFlag::Color)
|
||||
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient))
|
||||
{
|
||||
aaPts[i].fillOuterBlur = extendEdge(aaPts[i].orgPt, normalInfo[i].normalF, blurDir * stroke);
|
||||
aaPts[i].fillOuter = extendEdge(aaPts[i].fillOuterBlur, normalInfo[i].normalF, blurDir*antiAliasWidth);
|
||||
|
@ -161,7 +202,7 @@ bool GlGeometry::tesselate(TVG_UNUSED const Shape &shape, float viewWd, float vi
|
|||
VertexDataArray& fill = shapeGeometry.mFill;
|
||||
VertexDataArray& stroke = shapeGeometry.mStroke;
|
||||
|
||||
if (flag & RenderUpdateFlag::Color)
|
||||
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient) )
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (size_t pt = 0; pt < aaPts.size(); ++pt)
|
||||
|
@ -229,7 +270,7 @@ void GlGeometry::draw(const uint32_t location, const uint32_t primitiveIndex, Re
|
|||
{
|
||||
return;
|
||||
}
|
||||
VertexDataArray& geometry = (flag == RenderUpdateFlag::Color) ? mPrimitives[primitiveIndex].mFill : mPrimitives[primitiveIndex].mStroke;
|
||||
VertexDataArray& geometry = (flag == RenderUpdateFlag::Stroke) ? mPrimitives[primitiveIndex].mStroke : mPrimitives[primitiveIndex].mFill;
|
||||
|
||||
updateBuffer(location, geometry);
|
||||
GL_CHECK(glDrawElements(GL_TRIANGLES, geometry.indices.size(), GL_UNSIGNED_INT, geometry.indices.data()));
|
||||
|
@ -280,8 +321,12 @@ GlPoint GlGeometry::extendEdge(const GlPoint &pt, const GlPoint &normal, float s
|
|||
return (pt + tmp);
|
||||
}
|
||||
|
||||
void GlGeometry::addPoint(GlPrimitive& primitve, const GlPoint &pt)
|
||||
void GlGeometry::addPoint(GlPrimitive& primitve, const GlPoint &pt, GlPoint &min, GlPoint &max)
|
||||
{
|
||||
if (pt.x < min.x) min.x = pt.x;
|
||||
if (pt.y < min.y) min.y = pt.y;
|
||||
if (pt.x > max.x) max.x = pt.x;
|
||||
if (pt.y > max.y) max.y = pt.y;
|
||||
primitve.mAAPoints.push_back(GlPoint(pt.x, pt.y));
|
||||
}
|
||||
|
||||
|
@ -320,11 +365,11 @@ bool GlGeometry::isBezierFlat(const GlPoint &p1, const GlPoint &c1, const GlPoin
|
|||
return false;
|
||||
}
|
||||
|
||||
void GlGeometry::decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2)
|
||||
void GlGeometry::decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2, GlPoint &min, GlPoint &max)
|
||||
{
|
||||
if (isBezierFlat(pt1, cpt1, cpt2, pt2))
|
||||
{
|
||||
addPoint(primitve, pt2);
|
||||
addPoint(primitve, pt2, min, max);
|
||||
return;
|
||||
}
|
||||
GlPoint p12 = (pt1 + cpt1) * 0.5f;
|
||||
|
@ -336,7 +381,7 @@ void GlGeometry::decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1,
|
|||
|
||||
GlPoint p1234 = (p123 + p234) * 0.5f;
|
||||
|
||||
decomposeCubicCurve(primitve, pt1, p12, p123, p1234);
|
||||
decomposeCubicCurve(primitve, p1234, p234, p34, pt2);
|
||||
decomposeCubicCurve(primitve, pt1, p12, p123, p1234, min, max);
|
||||
decomposeCubicCurve(primitve, p1234, p234, p34, pt2, min, max);
|
||||
}
|
||||
|
||||
|
|
14
src/lib/gl_engine/tvgGlGeometry.h
Normal file → Executable file
14
src/lib/gl_engine/tvgGlGeometry.h
Normal file → Executable file
|
@ -128,6 +128,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
typedef GlPoint GlSize;
|
||||
|
||||
struct SmoothPoint
|
||||
{
|
||||
GlPoint orgPt;
|
||||
|
@ -174,6 +176,9 @@ struct GlPrimitive
|
|||
vector<SmoothPoint> mAAPoints;
|
||||
VertexDataArray mFill;
|
||||
VertexDataArray mStroke;
|
||||
GlPoint mTopLeft;
|
||||
GlPoint mBottomRight;
|
||||
bool mIsClosed = false;
|
||||
};
|
||||
|
||||
class GlGpuBuffer;
|
||||
|
@ -183,9 +188,10 @@ class GlGeometry
|
|||
public:
|
||||
|
||||
uint32_t getPrimitiveCount();
|
||||
const GlSize getPrimitiveSize(const uint32_t primitiveIndex) const;
|
||||
bool decomposeOutline(const Shape& shape);
|
||||
bool generateAAPoints(const Shape& shape, float strokeWd, RenderUpdateFlag flag);
|
||||
bool tesselate(const Shape &shape, float viewWd, float viewHt, RenderUpdateFlag flag);
|
||||
bool generateAAPoints(TVG_UNUSED const Shape& shape, float strokeWd, RenderUpdateFlag flag);
|
||||
bool tesselate(TVG_UNUSED const Shape &shape, float viewWd, float viewHt, RenderUpdateFlag flag);
|
||||
void disableVertex(uint32_t location);
|
||||
void draw(const uint32_t location, const uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||
|
||||
|
@ -196,11 +202,11 @@ private:
|
|||
float dotProduct(const GlPoint &p1, const GlPoint &p2);
|
||||
GlPoint extendEdge(const GlPoint &pt, const GlPoint &normal, float scalar);
|
||||
|
||||
void addPoint(GlPrimitive& primitve, const GlPoint &pt);
|
||||
void addPoint(GlPrimitive& primitve, const GlPoint &pt, GlPoint &min, GlPoint &max);
|
||||
void addTriangleFanIndices(uint32_t &curPt, vector<uint32_t> &indices);
|
||||
void addQuadIndices(uint32_t &curPt, vector<uint32_t> &indices);
|
||||
bool isBezierFlat(const GlPoint &p1, const GlPoint &c1, const GlPoint &c2, const GlPoint &p2);
|
||||
void decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2);
|
||||
void decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2, GlPoint &min, GlPoint &max);
|
||||
void updateBuffer(const uint32_t location, const VertexDataArray& vertexArray);
|
||||
|
||||
unique_ptr<GlGpuBuffer> mGpuBuffer;
|
||||
|
|
84
src/lib/gl_engine/tvgGlProgram.cpp
Normal file → Executable file
84
src/lib/gl_engine/tvgGlProgram.cpp
Normal file → Executable file
|
@ -26,17 +26,7 @@
|
|||
#include <GLES2/gl2.h>
|
||||
|
||||
|
||||
static std::vector<string> gStdAttributes = {
|
||||
"aLocation"
|
||||
};
|
||||
|
||||
static std::vector<string> gStdUniforms = {
|
||||
"uColor"
|
||||
};
|
||||
|
||||
uint32_t GlProgram::mCurrentProgram = 0;
|
||||
map<string, int32_t> GlProgram::mAttributeBuffer;
|
||||
map<string, int32_t> GlProgram::mUniformBuffer;
|
||||
|
||||
|
||||
unique_ptr<GlProgram> GlProgram::gen(std::shared_ptr<GlShader> shader)
|
||||
|
@ -48,17 +38,6 @@ unique_ptr<GlProgram> GlProgram::gen(std::shared_ptr<GlShader> shader)
|
|||
GlProgram::GlProgram(std::shared_ptr<GlShader> shader)
|
||||
{
|
||||
linkProgram(shader);
|
||||
load();
|
||||
|
||||
for (auto name : gStdAttributes)
|
||||
{
|
||||
getAttributeLocation(name.c_str());
|
||||
}
|
||||
for (auto name : gStdUniforms)
|
||||
{
|
||||
getUniformLocation(name.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -93,38 +72,63 @@ void GlProgram::unload()
|
|||
|
||||
int32_t GlProgram::getAttributeLocation(const char* name)
|
||||
{
|
||||
if (mAttributeBuffer.find(name) != mAttributeBuffer.end())
|
||||
{
|
||||
return mAttributeBuffer[name];
|
||||
}
|
||||
GL_CHECK(int32_t location = glGetAttribLocation(mCurrentProgram, name));
|
||||
if (location != -1)
|
||||
{
|
||||
mAttributeBuffer[name] = location;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
int32_t GlProgram::getUniformLocation(const char* name)
|
||||
{
|
||||
if (mUniformBuffer.find(name) != mUniformBuffer.end())
|
||||
{
|
||||
return mUniformBuffer[name];
|
||||
}
|
||||
GL_CHECK(int32_t location = glGetUniformLocation(mCurrentProgram, name));
|
||||
if (location != -1)
|
||||
{
|
||||
mUniformBuffer[name] = location;
|
||||
}
|
||||
return location;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniformValue(int32_t location, float r, float g, float b, float a)
|
||||
void GlProgram::setUniform1Value(int32_t location, int count, const int* values)
|
||||
{
|
||||
glUniform4f(location, r, g, b, a);
|
||||
GL_CHECK(glUniform1iv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform2Value(int32_t location, int count, const int* values)
|
||||
{
|
||||
GL_CHECK(glUniform2iv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform3Value(int32_t location, int count, const int* values)
|
||||
{
|
||||
GL_CHECK(glUniform3iv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform4Value(int32_t location, int count, const int* values)
|
||||
{
|
||||
GL_CHECK(glUniform4iv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform1Value(int32_t location, int count, const float* values)
|
||||
{
|
||||
GL_CHECK(glUniform1fv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform2Value(int32_t location, int count, const float* values)
|
||||
{
|
||||
GL_CHECK(glUniform2fv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform3Value(int32_t location, int count, const float* values)
|
||||
{
|
||||
GL_CHECK(glUniform3fv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
void GlProgram::setUniform4Value(int32_t location, int count, const float* values)
|
||||
{
|
||||
GL_CHECK(glUniform4fv(location, count, values));
|
||||
}
|
||||
|
||||
|
||||
|
|
13
src/lib/gl_engine/tvgGlProgram.h
Normal file → Executable file
13
src/lib/gl_engine/tvgGlProgram.h
Normal file → Executable file
|
@ -36,10 +36,17 @@ public:
|
|||
~GlProgram();
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
static void unload();
|
||||
int32_t getAttributeLocation(const char* name);
|
||||
int32_t getUniformLocation(const char* name);
|
||||
void setUniformValue(int32_t location, float r, float g, float b, float a);
|
||||
void setUniform1Value(int32_t location, int count, const int* values);
|
||||
void setUniform2Value(int32_t location, int count, const int* values);
|
||||
void setUniform3Value(int32_t location, int count, const int* values);
|
||||
void setUniform4Value(int32_t location, int count, const int* values);
|
||||
void setUniform1Value(int32_t location, int count, const float* values);
|
||||
void setUniform2Value(int32_t location, int count, const float* values);
|
||||
void setUniform3Value(int32_t location, int count, const float* values);
|
||||
void setUniform4Value(int32_t location, int count, const float* values);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -47,8 +54,6 @@ private:
|
|||
uint32_t mProgramObj;
|
||||
static uint32_t mCurrentProgram;
|
||||
|
||||
static std::map<string, int32_t> mAttributeBuffer;
|
||||
static std::map<string, int32_t> mUniformBuffer;
|
||||
};
|
||||
|
||||
#endif /* _TVG_GL_PROGRAM_H_ */
|
||||
|
|
83
src/lib/gl_engine/tvgGlPropertyInterface.cpp
Executable file
83
src/lib/gl_engine/tvgGlPropertyInterface.cpp
Executable file
|
@ -0,0 +1,83 @@
|
|||
#include "tvgGlPropertyInterface.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
VertexProperty PropertyInterface::mEmptyProperty;
|
||||
|
||||
VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>* vertexProperty = nullptr;
|
||||
int32_t id;
|
||||
switch (propType) {
|
||||
case VertexProperty::PropertyType::ATTRIBUTE: {
|
||||
id = prog->getAttributeLocation(name.c_str());
|
||||
vertexProperty = &rTask->getAttributeVertexProperty();
|
||||
break;
|
||||
}
|
||||
case VertexProperty::PropertyType::UNIFORM: {
|
||||
id = prog->getUniformLocation(name.c_str());
|
||||
vertexProperty = &rTask->getUniformVertexProperty();
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
if (id != -1)
|
||||
{
|
||||
VertexProperty property = { id, name, propType, VertexProperty::DataType::FLOAT };
|
||||
property.propertyValues.setStride(propFormatSize);
|
||||
if (vertexProperty)
|
||||
{
|
||||
(*vertexProperty)[id] = property;
|
||||
return (*vertexProperty)[id];
|
||||
}
|
||||
}
|
||||
return mEmptyProperty;
|
||||
}
|
||||
|
||||
|
||||
int32_t PropertyInterface::getPropertyId(GlRenderTask* rTask, std::string name)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>& vertexProperty = rTask->getUniformVertexProperty();
|
||||
for (auto& property : vertexProperty)
|
||||
{
|
||||
if (property.second.propertyName == name)
|
||||
{
|
||||
return property.second.propertyId;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
VertexProperty& PropertyInterface::getProperty(GlRenderTask* rTask, std::string name)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>& vertexProperty = rTask->getUniformVertexProperty();
|
||||
for (auto& property : vertexProperty)
|
||||
{
|
||||
if (property.second.propertyName == name)
|
||||
{
|
||||
return property.second;
|
||||
}
|
||||
}
|
||||
return mEmptyProperty;
|
||||
}
|
||||
|
||||
|
||||
VertexProperty& PropertyInterface::getProperty(GlRenderTask* rTask, int32_t propId)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>& vertexProperty = rTask->getUniformVertexProperty();
|
||||
if (vertexProperty.find(propId) != vertexProperty.end())
|
||||
{
|
||||
return vertexProperty[propId];
|
||||
}
|
||||
return mEmptyProperty;
|
||||
}
|
||||
|
||||
|
||||
void PropertyInterface::clearData(GlRenderTask* rTask)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>& vertexProperty = rTask->getUniformVertexProperty();
|
||||
for (auto& prop : vertexProperty)
|
||||
{
|
||||
prop.second.propertyValues.clear();
|
||||
}
|
||||
}
|
64
src/lib/gl_engine/tvgGlPropertyInterface.h
Executable file
64
src/lib/gl_engine/tvgGlPropertyInterface.h
Executable file
|
@ -0,0 +1,64 @@
|
|||
#ifndef _TVG_GL_PROPERTY_INTERFACE_H_
|
||||
#define _TVG_GL_PROPERTY_INTERFACE_H_
|
||||
|
||||
#include "tvgGlRendererProperties.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#define ADD_ATTRIBUTE_PROPERTY(var, rtask, prog, varName, formatSize, location) \
|
||||
var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::ATTRIBUTE); \
|
||||
if (var->propertyId != -1) \
|
||||
location = var->propertyId
|
||||
|
||||
#define ADD_UNIFORM_PROPERTY(var, rtask, prog, varName, formatSize, location) \
|
||||
var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::UNIFORM); \
|
||||
if (var->propertyId != -1) \
|
||||
location = var->propertyId
|
||||
|
||||
#define FORMAT_SIZE_FLOAT 1
|
||||
#define FORMAT_SIZE_VEC_2 2
|
||||
#define FORMAT_SIZE_VEC_3 3
|
||||
#define FORMAT_SIZE_VEC_4 4
|
||||
|
||||
class PropertyInterface
|
||||
{
|
||||
public:
|
||||
static VertexProperty& addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType);
|
||||
template<typename... Args>
|
||||
static void setProperty(GlRenderTask* rTask, std::string name, float first, Args... args)
|
||||
{
|
||||
VertexProperty& prop = getProperty(rTask, name);
|
||||
if (prop.propertyId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
setProperty(prop.propertyId, first, args...);
|
||||
}
|
||||
template<typename... Args>
|
||||
static void setProperty(GlRenderTask* rTask, int32_t propId, float first, Args... args)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>::iterator itr = rTask->getUniformVertexProperty().find(propId);
|
||||
if (itr->second.propertyId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VertexProperty& prop = itr->second;
|
||||
|
||||
prop.dataType = VertexProperty::DataType::FLOAT;
|
||||
prop.propertyValues.set(first, args...);
|
||||
}
|
||||
static int32_t getPropertyId(GlRenderTask* rTask, std::string name);
|
||||
static VertexProperty& getProperty(GlRenderTask* rTask, std::string name);
|
||||
static VertexProperty& getProperty(GlRenderTask* rTask, int32_t propId);
|
||||
static void clearData(GlRenderTask* rTask);
|
||||
|
||||
private:
|
||||
PropertyInterface() {}
|
||||
static VertexProperty mEmptyProperty;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TVG_GL_PROPERTY_INTERFACE_H_ */
|
267
src/lib/gl_engine/tvgGlRenderTask.cpp
Executable file
267
src/lib/gl_engine/tvgGlRenderTask.cpp
Executable file
|
@ -0,0 +1,267 @@
|
|||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlShaderSrc.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
#include "tvgGlPropertyInterface.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
|
||||
GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr<GlShader> shader)
|
||||
{
|
||||
mRenderType = renderType;
|
||||
mProgram = GlProgram::gen(shader);
|
||||
load();
|
||||
|
||||
VertexProperty* prop = nullptr;
|
||||
ADD_ATTRIBUTE_PROPERTY(prop, this, mProgram, "aLocation", FORMAT_SIZE_VEC_4, mLocVertexAttribute);
|
||||
}
|
||||
|
||||
|
||||
GlRenderTask::RenderTypes GlRenderTask::getRenderType()
|
||||
{
|
||||
return mRenderType;
|
||||
}
|
||||
|
||||
|
||||
void GlRenderTask::load()
|
||||
{
|
||||
mProgram->load();
|
||||
}
|
||||
|
||||
|
||||
void GlRenderTask::unload()
|
||||
{
|
||||
GlProgram::unload();
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<GlProgram> GlRenderTask::getProgram()
|
||||
{
|
||||
return mProgram;
|
||||
}
|
||||
|
||||
|
||||
std::map<int32_t, VertexProperty>& GlRenderTask::getAttributeVertexProperty()
|
||||
{
|
||||
return mAttributePropertyBuffer;
|
||||
}
|
||||
|
||||
|
||||
std::map<int32_t, VertexProperty>& GlRenderTask::getUniformVertexProperty()
|
||||
{
|
||||
return mUniformPropertyBuffer;
|
||||
}
|
||||
|
||||
|
||||
int32_t GlRenderTask::getLocationPropertyId() const
|
||||
{
|
||||
return mLocVertexAttribute;
|
||||
}
|
||||
|
||||
|
||||
void GlRenderTask::uploadValues()
|
||||
{
|
||||
for (auto& property : mUniformPropertyBuffer)
|
||||
{
|
||||
PropertyValue& propertyVal = property.second.propertyValues;
|
||||
switch (property.second.dataType) {
|
||||
case VertexProperty::DataType::INT: {
|
||||
switch (propertyVal.getStride()) {
|
||||
case 1:
|
||||
mProgram->setUniform1Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
||||
break;
|
||||
case 2:
|
||||
mProgram->setUniform2Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
||||
break;
|
||||
case 3:
|
||||
mProgram->setUniform3Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
||||
break;
|
||||
case 4:
|
||||
mProgram->setUniform4Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VertexProperty::DataType::FLOAT: {
|
||||
switch (propertyVal.getStride()) {
|
||||
case 1:
|
||||
mProgram->setUniform1Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
|
||||
break;
|
||||
case 2:
|
||||
mProgram->setUniform2Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
|
||||
break;
|
||||
case 3:
|
||||
mProgram->setUniform3Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
|
||||
break;
|
||||
case 4:
|
||||
mProgram->setUniform4Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<GlColorRenderTask> GlColorRenderTask::gen()
|
||||
{
|
||||
return std::make_shared<GlColorRenderTask>();
|
||||
}
|
||||
|
||||
|
||||
GlColorRenderTask::GlColorRenderTask()
|
||||
:GlRenderTask(GlRenderTask::RenderTypes::RT_Color, GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER))
|
||||
{
|
||||
VertexProperty* prop = nullptr;
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "uColor", FORMAT_SIZE_VEC_4, mLocColor);
|
||||
}
|
||||
|
||||
|
||||
void GlColorRenderTask::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (mLocColor != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocColor, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GlGradientRenderTask::GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr<GlShader> shader)
|
||||
:GlRenderTask(renderType, shader)
|
||||
{
|
||||
VertexProperty* prop = nullptr;
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "uSize", FORMAT_SIZE_VEC_2, mLocPrimitiveSize);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "uCanvasSize", FORMAT_SIZE_VEC_2, mLocCanvasSize);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "noise_level", FORMAT_SIZE_FLOAT, mLocNoise);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "nStops", FORMAT_SIZE_FLOAT, mLocStopCnt);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stopPoints", FORMAT_SIZE_FLOAT, mLocStops);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stopColors", FORMAT_SIZE_VEC_4, mLocStopColors);
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setPrimitveSize(float width, float height)
|
||||
{
|
||||
if (mLocPrimitiveSize != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocPrimitiveSize, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setCanvasSize(float width, float height)
|
||||
{
|
||||
if (mLocCanvasSize != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocCanvasSize, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setNoise(float noise)
|
||||
{
|
||||
if (mLocNoise != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocNoise, noise);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setStopCount(int32_t count)
|
||||
{
|
||||
if (mLocStopCnt != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocStopCnt, (float)count);
|
||||
}
|
||||
}
|
||||
|
||||
void GlGradientRenderTask::setStopColor(int index, float stopVal, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
if (index < MAX_GRADIENT_STOPS && mLocStops != -1 && mLocStopColors != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocStops, stopVal);
|
||||
PropertyInterface::setProperty(this, mLocStopColors, r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<GlLinearGradientRenderTask> GlLinearGradientRenderTask::gen()
|
||||
{
|
||||
return std::make_shared<GlLinearGradientRenderTask>();
|
||||
}
|
||||
|
||||
|
||||
GlLinearGradientRenderTask::GlLinearGradientRenderTask()
|
||||
:GlGradientRenderTask(GlRenderTask::RenderTypes::RT_LinGradient, GlShader::gen(GRADIENT_VERT_SHADER, LINEAR_GRADIENT_FRAG_SHADER))
|
||||
{
|
||||
VertexProperty* prop = nullptr;
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradStartPos", FORMAT_SIZE_VEC_2, mLocStartPos);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradEndPos", FORMAT_SIZE_VEC_2, mLocEndPos);
|
||||
}
|
||||
|
||||
|
||||
void GlLinearGradientRenderTask::setStartPosition(float posX, float posY)
|
||||
{
|
||||
if (mLocStartPos != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocStartPos, posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlLinearGradientRenderTask::setEndPosition(float posX, float posY)
|
||||
{
|
||||
if (mLocEndPos != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocEndPos, posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<GlRadialGradientRenderTask> GlRadialGradientRenderTask::gen()
|
||||
{
|
||||
return std::make_shared<GlRadialGradientRenderTask>();
|
||||
}
|
||||
|
||||
|
||||
GlRadialGradientRenderTask::GlRadialGradientRenderTask()
|
||||
:GlGradientRenderTask(GlRenderTask::RenderTypes::RT_RadGradient, GlShader::gen(GRADIENT_VERT_SHADER, RADIAL_GRADIENT_FRAG_SHADER))
|
||||
{
|
||||
VertexProperty* prop = nullptr;
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "gradStartPos", FORMAT_SIZE_VEC_2, mLocStartPos);
|
||||
ADD_UNIFORM_PROPERTY(prop, this, getProgram(), "stRadius", FORMAT_SIZE_FLOAT, mLocStRadius);
|
||||
}
|
||||
|
||||
|
||||
GlRadialGradientRenderTask::~GlRadialGradientRenderTask()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GlRadialGradientRenderTask::setStartPosition(float posX, float posY)
|
||||
{
|
||||
if (mLocStartPos != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocStartPos, posX, posY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlRadialGradientRenderTask::setStartRadius(float radius)
|
||||
{
|
||||
if (mLocStRadius != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocStRadius, radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GlRadialGradientRenderTask::setEndRadius(float radius)
|
||||
{
|
||||
if (mLocEdRadius != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocEdRadius, radius);
|
||||
}
|
||||
}
|
108
src/lib/gl_engine/tvgGlRenderTask.h
Executable file
108
src/lib/gl_engine/tvgGlRenderTask.h
Executable file
|
@ -0,0 +1,108 @@
|
|||
#ifndef _TVG_GL_RENDER_TASK_H_
|
||||
#define _TVG_GL_RENDER_TASK_H_
|
||||
|
||||
#include "tvgGlShader.h"
|
||||
#include "tvgGlProgram.h"
|
||||
#include "tvgGlRendererProperties.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#define MAX_GRADIENT_STOPS 4
|
||||
|
||||
class GlRenderTask
|
||||
{
|
||||
public:
|
||||
enum RenderTypes
|
||||
{
|
||||
RT_Color = 0,
|
||||
RT_LinGradient,
|
||||
RT_RadGradient,
|
||||
|
||||
RT_None,
|
||||
};
|
||||
|
||||
GlRenderTask(RenderTypes renderType, std::shared_ptr<GlShader> shader);
|
||||
RenderTypes getRenderType();
|
||||
|
||||
void load();
|
||||
static void unload();
|
||||
std::shared_ptr<GlProgram> getProgram();
|
||||
std::map<int32_t, VertexProperty>& getAttributeVertexProperty();
|
||||
std::map<int32_t, VertexProperty>& getUniformVertexProperty();
|
||||
int32_t getLocationPropertyId() const;
|
||||
void uploadValues();
|
||||
|
||||
private:
|
||||
RenderTypes mRenderType;
|
||||
|
||||
uint32_t propertyFormatSize;
|
||||
std::shared_ptr<GlProgram> mProgram;
|
||||
std::map<int32_t, VertexProperty> mAttributePropertyBuffer;
|
||||
std::map<int32_t, VertexProperty> mUniformPropertyBuffer;
|
||||
|
||||
int32_t mLocVertexAttribute;
|
||||
};
|
||||
|
||||
class GlColorRenderTask : public GlRenderTask
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<GlColorRenderTask> gen();
|
||||
GlColorRenderTask();
|
||||
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
|
||||
private:
|
||||
int32_t mLocColor = -1;
|
||||
};
|
||||
|
||||
class GlGradientRenderTask : public GlRenderTask
|
||||
{
|
||||
public:
|
||||
GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr<GlShader> shader);
|
||||
void setPrimitveSize(float width, float height);
|
||||
void setCanvasSize(float width, float height);
|
||||
void setNoise(float noise);
|
||||
void setStopCount(int32_t count);
|
||||
void setStopColor(int index, float stopVal, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
|
||||
private:
|
||||
int32_t mLocPrimitiveSize = -1;
|
||||
int32_t mLocCanvasSize = -1;
|
||||
int32_t mLocNoise = -1;
|
||||
int32_t mLocStopCnt = -1;
|
||||
int32_t mLocStops;
|
||||
int32_t mLocStopColors;
|
||||
};
|
||||
|
||||
class GlLinearGradientRenderTask : public GlGradientRenderTask
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<GlLinearGradientRenderTask> gen();
|
||||
GlLinearGradientRenderTask();
|
||||
void setStartPosition(float posX, float posY);
|
||||
void setEndPosition(float posX, float posY);
|
||||
|
||||
private:
|
||||
int32_t mLocStartPos = -1;
|
||||
int32_t mLocEndPos = -1;
|
||||
};
|
||||
|
||||
class GlRadialGradientRenderTask : public GlGradientRenderTask
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<GlRadialGradientRenderTask> gen();
|
||||
GlRadialGradientRenderTask();
|
||||
~GlRadialGradientRenderTask();
|
||||
void setStartPosition(float posX, float posY);
|
||||
void setStartRadius(float radius);
|
||||
void setEndRadius(float radius);
|
||||
|
||||
private:
|
||||
int32_t mLocStartPos = -1;
|
||||
int32_t mLocStRadius = -1;
|
||||
int32_t mLocEdRadius = -1;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TVG_GL_RENDER_TASK_H_ */
|
138
src/lib/gl_engine/tvgGlRenderer.cpp
Normal file → Executable file
138
src/lib/gl_engine/tvgGlRenderer.cpp
Normal file → Executable file
|
@ -24,6 +24,7 @@
|
|||
#include "tvgGlGeometry.h"
|
||||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlRenderer.h"
|
||||
#include "tvgGlPropertyInterface.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
|
@ -42,6 +43,8 @@ static void _termEngine()
|
|||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
#define NOISE_LEVEL 0.5f
|
||||
|
||||
bool GlRenderer::clear()
|
||||
{
|
||||
//TODO: (Request) to clear target
|
||||
|
@ -65,16 +68,21 @@ bool GlRenderer::target(TVG_UNUSED uint32_t* buffer, uint32_t stride, uint32_t w
|
|||
bool GlRenderer::flush()
|
||||
{
|
||||
GL_CHECK(glFinish());
|
||||
mColorProgram->unload();
|
||||
|
||||
GlRenderTask::unload();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GlRenderer::preRender()
|
||||
{
|
||||
// Blend function for pre multiplied alpha
|
||||
GL_CHECK(glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
if (mRenderTasks.size() == 0)
|
||||
{
|
||||
initShaders();
|
||||
}
|
||||
GlRenderTask::unload();
|
||||
|
||||
// Blend function for straight alpha
|
||||
GL_CHECK(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
GL_CHECK(glEnable(GL_BLEND));
|
||||
return true;
|
||||
}
|
||||
|
@ -98,19 +106,23 @@ bool GlRenderer::render(const Shape& shape, void *data)
|
|||
|
||||
GL_CHECK(glViewport(0, 0, sdata->viewWd, sdata->viewHt));
|
||||
|
||||
uint32_t geometryCnt = sdata->geometry->getPrimitiveCount();
|
||||
for (uint32_t i = 0; i < geometryCnt; ++i)
|
||||
uint32_t primitiveCount = sdata->geometry->getPrimitiveCount();
|
||||
for (uint32_t i = 0; i < primitiveCount; ++i)
|
||||
{
|
||||
mColorProgram->load();
|
||||
if (flags & RenderUpdateFlag::Color)
|
||||
if (flags & RenderUpdateFlag::Gradient)
|
||||
{
|
||||
const Fill* gradient = shape.fill();
|
||||
drawPrimitive(*sdata, gradient, i, RenderUpdateFlag::Gradient);
|
||||
}
|
||||
else if (flags & RenderUpdateFlag::Color)
|
||||
{
|
||||
shape.fill(&r, &g, &b, &a);
|
||||
drawPrimitive(*(sdata->geometry), (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, i, RenderUpdateFlag::Color);
|
||||
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Color);
|
||||
}
|
||||
if (flags & RenderUpdateFlag::Stroke)
|
||||
{
|
||||
shape.strokeColor(&r, &g, &b, &a);
|
||||
drawPrimitive(*(sdata->geometry), (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, i, RenderUpdateFlag::Stroke);
|
||||
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Stroke);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,8 +155,6 @@ void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const Rende
|
|||
|
||||
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
|
||||
|
||||
initShaders();
|
||||
|
||||
sdata->geometry = make_unique<GlGeometry>();
|
||||
|
||||
//invisible?
|
||||
|
@ -153,9 +163,14 @@ void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const Rende
|
|||
shape.strokeColor(nullptr, nullptr, nullptr, &alphaS);
|
||||
auto strokeWd = shape.strokeWidth();
|
||||
|
||||
if (alphaF == 0 && alphaS == 0) return sdata;
|
||||
if ( ((sdata->updateFlag & RenderUpdateFlag::Gradient) == 0) &&
|
||||
((sdata->updateFlag & RenderUpdateFlag::Color) && alphaF == 0) &&
|
||||
((sdata->updateFlag & RenderUpdateFlag::Stroke) && alphaS == 0) )
|
||||
{
|
||||
return sdata;
|
||||
}
|
||||
|
||||
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke) )
|
||||
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient) )
|
||||
{
|
||||
if (!sdata->geometry->decomposeOutline(shape)) return sdata;
|
||||
if (!sdata->geometry->generateAAPoints(shape, static_cast<float>(strokeWd), sdata->updateFlag)) return sdata;
|
||||
|
@ -198,10 +213,7 @@ GlRenderer* GlRenderer::gen()
|
|||
|
||||
GlRenderer::~GlRenderer()
|
||||
{
|
||||
if (mColorProgram.get())
|
||||
{
|
||||
mColorProgram.reset(nullptr);
|
||||
}
|
||||
mRenderTasks.clear();
|
||||
|
||||
--rendererCnt;
|
||||
if (!initEngine) _termEngine();
|
||||
|
@ -210,21 +222,85 @@ GlRenderer::~GlRenderer()
|
|||
|
||||
void GlRenderer::initShaders()
|
||||
{
|
||||
if (!mColorProgram.get())
|
||||
{
|
||||
shared_ptr<GlShader> shader = GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER);
|
||||
mColorProgram = GlProgram::gen(shader);
|
||||
}
|
||||
mColorProgram->load();
|
||||
mColorUniformLoc = mColorProgram->getUniformLocation("uColor");
|
||||
mVertexAttrLoc = mColorProgram->getAttributeLocation("aLocation");
|
||||
// Solid Color Renderer
|
||||
mRenderTasks.push_back(GlColorRenderTask::gen());
|
||||
|
||||
// Linear Gradient Renderer
|
||||
mRenderTasks.push_back(GlLinearGradientRenderTask::gen());
|
||||
|
||||
// Radial Gradient Renderer
|
||||
mRenderTasks.push_back(GlRadialGradientRenderTask::gen());
|
||||
}
|
||||
|
||||
|
||||
void GlRenderer::drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag)
|
||||
void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint32_t primitiveIndex, RenderUpdateFlag flag)
|
||||
{
|
||||
mColorProgram->setUniformValue(mColorUniformLoc, r, g, b, a);
|
||||
geometry.draw(mVertexAttrLoc, primitiveIndex, flag);
|
||||
geometry.disableVertex(mVertexAttrLoc);
|
||||
GlColorRenderTask* renderTask = static_cast<GlColorRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_Color].get());
|
||||
assert(renderTask);
|
||||
renderTask->load();
|
||||
PropertyInterface::clearData(renderTask);
|
||||
renderTask->setColor(r, g, b, a);
|
||||
int32_t vertexLoc = renderTask->getLocationPropertyId();
|
||||
renderTask->uploadValues();
|
||||
sdata.geometry->draw(vertexLoc, primitiveIndex, flag);
|
||||
sdata.geometry->disableVertex(vertexLoc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primitiveIndex, RenderUpdateFlag flag)
|
||||
{
|
||||
const Fill::ColorStop* stops = nullptr;
|
||||
auto stopCnt = fill->colorStops(&stops);
|
||||
if (stopCnt < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
GlGradientRenderTask* rTask = nullptr;
|
||||
GlSize size = sdata.geometry->getPrimitiveSize(primitiveIndex);
|
||||
switch (fill->id()) {
|
||||
case FILL_ID_LINEAR: {
|
||||
float x1, y1, x2, y2;
|
||||
GlLinearGradientRenderTask *renderTask = static_cast<GlLinearGradientRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_LinGradient].get());
|
||||
assert(renderTask);
|
||||
rTask = renderTask;
|
||||
renderTask->load();
|
||||
PropertyInterface::clearData(renderTask);
|
||||
const LinearGradient* grad = static_cast<const LinearGradient*>(fill);
|
||||
grad->linear(&x1, &y1, &x2, &y2);
|
||||
renderTask->setStartPosition(x1, y1);
|
||||
renderTask->setEndPosition(x2, y2);
|
||||
break;
|
||||
}
|
||||
case FILL_ID_RADIAL: {
|
||||
float x1, y1, r1;
|
||||
GlRadialGradientRenderTask *renderTask = static_cast<GlRadialGradientRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_RadGradient].get());
|
||||
assert(renderTask);
|
||||
rTask = renderTask;
|
||||
renderTask->load();
|
||||
PropertyInterface::clearData(renderTask);
|
||||
const RadialGradient* grad = static_cast<const RadialGradient*>(fill);
|
||||
grad->radial(&x1, &y1, &r1);
|
||||
renderTask->setStartPosition(x1, y1);
|
||||
renderTask->setStartRadius(r1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rTask)
|
||||
{
|
||||
int32_t vertexLoc = rTask->getLocationPropertyId();
|
||||
rTask->setPrimitveSize(size.x, size.y);
|
||||
rTask->setCanvasSize(sdata.viewWd, sdata.viewHt);
|
||||
rTask->setNoise(NOISE_LEVEL);
|
||||
rTask->setStopCount((int)stopCnt);
|
||||
for (uint32_t i = 0; i < stopCnt; ++i)
|
||||
{
|
||||
rTask->setStopColor(i, stops[i].offset, stops[i].r, stops[i].g, stops[i].b, stops[i].a);
|
||||
}
|
||||
|
||||
rTask->uploadValues();
|
||||
sdata.geometry->draw(vertexLoc, primitiveIndex, flag);
|
||||
sdata.geometry->disableVertex(vertexLoc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
9
src/lib/gl_engine/tvgGlRenderer.h
Normal file → Executable file
9
src/lib/gl_engine/tvgGlRenderer.h
Normal file → Executable file
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
class GlRenderer : public RenderMethod
|
||||
{
|
||||
|
@ -50,11 +50,10 @@ private:
|
|||
~GlRenderer();
|
||||
|
||||
void initShaders();
|
||||
void drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||
void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||
void drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||
|
||||
unique_ptr<GlProgram> mColorProgram = nullptr;
|
||||
int32_t mColorUniformLoc = 0;
|
||||
uint32_t mVertexAttrLoc = 0;
|
||||
vector<shared_ptr<GlRenderTask>> mRenderTasks;
|
||||
};
|
||||
|
||||
#endif /* _TVG_GL_RENDERER_H_ */
|
||||
|
|
92
src/lib/gl_engine/tvgGlRendererProperties.h
Executable file
92
src/lib/gl_engine/tvgGlRendererProperties.h
Executable file
|
@ -0,0 +1,92 @@
|
|||
#ifndef _TVG_GL_RENDER_PROPERTIES_H_
|
||||
#define _TVG_GL_RENDER_PROPERTIES_H_
|
||||
|
||||
#include "tvgGlShader.h"
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class PropertyValue
|
||||
{
|
||||
public:
|
||||
void setStride(uint32_t s)
|
||||
{
|
||||
stride = s;
|
||||
if (values.capacity() == values.size())
|
||||
{
|
||||
values.reserve(values.size() + stride);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getStride() const
|
||||
{
|
||||
return stride;
|
||||
}
|
||||
|
||||
uint32_t getSize() const
|
||||
{
|
||||
return values.size();
|
||||
}
|
||||
|
||||
uint32_t getCount() const
|
||||
{
|
||||
return (values.size() / stride);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
values.clear();
|
||||
}
|
||||
|
||||
const float* getData()
|
||||
{
|
||||
return values.data();
|
||||
}
|
||||
|
||||
void set(float v)
|
||||
{
|
||||
values.push_back(v);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void set(float first, Args... args)
|
||||
{
|
||||
if (values.capacity() == values.size())
|
||||
{
|
||||
values.reserve(values.size() + stride);
|
||||
}
|
||||
set(first);
|
||||
set(args...);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<float> values;
|
||||
uint32_t stride = 0;
|
||||
};
|
||||
|
||||
struct VertexProperty
|
||||
{
|
||||
public:
|
||||
enum class DataType
|
||||
{
|
||||
INT = 0,
|
||||
FLOAT
|
||||
};
|
||||
enum class PropertyType
|
||||
{
|
||||
ATTRIBUTE = 0,
|
||||
UNIFORM
|
||||
};
|
||||
|
||||
int32_t propertyId = -1;
|
||||
std::string propertyName = "";
|
||||
PropertyType propType = PropertyType::UNIFORM;
|
||||
DataType dataType = DataType::FLOAT;
|
||||
PropertyValue propertyValues;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TVG_GL_RENDER_PROPERTIES_H_ */
|
174
src/lib/gl_engine/tvgGlShaderSrc.cpp
Normal file → Executable file
174
src/lib/gl_engine/tvgGlShaderSrc.cpp
Normal file → Executable file
|
@ -22,23 +22,161 @@
|
|||
|
||||
#include "tvgGlShaderSrc.h"
|
||||
|
||||
const char* COLOR_VERT_SHADER =
|
||||
"attribute highp vec4 aLocation; \n"
|
||||
"uniform highp vec4 uColor; \n"
|
||||
"varying highp vec4 vcolor; \n"
|
||||
"varying highp float vOpacity; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n"
|
||||
" vcolor = uColor; \n"
|
||||
" vOpacity = aLocation.z; \n"
|
||||
"} \n";
|
||||
#include <string>
|
||||
|
||||
const char* COLOR_FRAG_SHADER =
|
||||
"varying highp vec4 vcolor; \n"
|
||||
"varying highp float vOpacity; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_FragColor = vec4(vcolor.xyz, vcolor.w*vOpacity); \n"
|
||||
"} \n";
|
||||
#define TVG_COMPOSE_SHADER(shader) #shader
|
||||
|
||||
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||
attribute mediump vec4 aLocation; \n
|
||||
varying highp float vOpacity; \n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
vOpacity = aLocation.z; \n
|
||||
});
|
||||
|
||||
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||
uniform highp vec4 uColor; \n
|
||||
varying highp float vOpacity; \n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_FragColor = vec4(uColor.xyz, uColor.w*vOpacity); \n
|
||||
});
|
||||
|
||||
const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||
attribute highp vec4 aLocation; \n
|
||||
varying highp float vOpacity; \n
|
||||
varying highp vec2 vPos; \n
|
||||
\n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
vOpacity = aLocation.z; \n
|
||||
vPos = vec2((aLocation.x + 1.0) / 2.0, ((-1.0 * aLocation.y) +1.0) / 2.0); \n
|
||||
});
|
||||
|
||||
|
||||
std::string STR_GRADIENT_FRAG_COMMON_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
precision highp float; \n
|
||||
const int MAX_STOP_COUNT = 4; \n
|
||||
uniform highp vec2 uSize; \n
|
||||
uniform highp vec2 uCanvasSize; \n
|
||||
uniform float nStops; \n
|
||||
uniform float noise_level; \n
|
||||
uniform float stopPoints[MAX_STOP_COUNT]; \n
|
||||
uniform vec4 stopColors[MAX_STOP_COUNT]; \n
|
||||
varying highp vec2 vPos; \n
|
||||
varying highp float vOpacity; \n
|
||||
);
|
||||
|
||||
std::string STR_GRADIENT_FRAG_COMMON_FUNCTIONS = TVG_COMPOSE_SHADER(
|
||||
float gradientStep(float edge0, float edge1, float x) \n
|
||||
{ \n
|
||||
// linear \n
|
||||
x = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); \n
|
||||
return x; \n
|
||||
} \n
|
||||
\n
|
||||
vec4 gradient(float t) \n
|
||||
{ \n
|
||||
vec4 col = vec4(0.0); \n
|
||||
int i = 0; \n
|
||||
int count = int(nStops); \n
|
||||
if (t <= stopPoints[0]) \n
|
||||
{ \n
|
||||
col += stopColors[0]; \n
|
||||
} \n
|
||||
else if (t >= stopPoints[count - 1]) \n
|
||||
{ \n
|
||||
col += stopColors[count - 1]; \n
|
||||
} \n
|
||||
else \n
|
||||
{ \n
|
||||
for (i = 0; i < count - 1; ++i) \n
|
||||
{ \n
|
||||
if (t > stopPoints[i] && t < stopPoints[i + 1]) \n
|
||||
{ \n
|
||||
col += (stopColors[i] * (1. - gradientStep(stopPoints[i], stopPoints[i + 1], t))); \n
|
||||
col += (stopColors[i + 1] * gradientStep(stopPoints[i], stopPoints[i + 1], t)); \n
|
||||
break; \n
|
||||
} \n
|
||||
} \n
|
||||
} \n
|
||||
\n
|
||||
return col; \n
|
||||
} \n
|
||||
\n
|
||||
highp vec3 ScreenSpaceDither(vec2 vScreenPos) \n
|
||||
{ \n
|
||||
highp vec3 vDither = vec3(dot(vec2(171.0, 231.0), vScreenPos.xy)); \n
|
||||
vDither.rgb = fract(vDither.rgb / vec3(103.0, 71.0, 97.0)); \n
|
||||
return vDither.rgb / 255.0; \n
|
||||
});
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
uniform highp vec2 gradStartPos; \n
|
||||
uniform highp vec2 gradEndPos; \n
|
||||
);
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||
void main() \n
|
||||
{ \n
|
||||
highp vec2 pos = vec2(vPos.x * uCanvasSize.x, vPos.y * uCanvasSize.y); \n
|
||||
highp vec2 spos = vec2(pos.x / uSize.x, pos.y / uSize.y); \n
|
||||
highp vec2 st = gradStartPos / (uSize.xy); \n
|
||||
highp vec2 ed = gradEndPos / (uSize.xy); \n
|
||||
\n
|
||||
highp vec2 ba = ed - st; \n
|
||||
\n
|
||||
highp float t = dot(spos - st, ba) / dot(ba, ba); \n
|
||||
\n
|
||||
//t = smoothstep(0.0, 1.0, clamp(t, 0.0, 1.0)); \n
|
||||
t = clamp(t, 0.0, 1.0); \n
|
||||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
highp vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
gl_FragColor = vec4(finalCol.xyz, finalCol.w* vOpacity); \n
|
||||
});
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
uniform highp vec2 gradStartPos; \n
|
||||
uniform highp float stRadius; \n
|
||||
);
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||
void main() \n
|
||||
{ \n
|
||||
highp vec2 pos = vec2(vPos.x * uCanvasSize.x, vPos.y * uCanvasSize.y); \n
|
||||
highp vec2 spos = vec2(pos.x / uSize.x, pos.y / uSize.y); \n
|
||||
\n
|
||||
highp float ba = stRadius; \n
|
||||
highp float d = distance(gradStartPos, pos); \n
|
||||
d = (d / ba); \n
|
||||
\n
|
||||
//float t = smoothstep(0.0, 1.0, clamp(d, 0.0, 1.0)); \n
|
||||
float t = clamp(d, 0.0, 1.0); \n
|
||||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
highp vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
gl_FragColor = vec4(finalCol.xyz, finalCol.w * vOpacity); \n
|
||||
});
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_FRAG_SHADER =
|
||||
STR_GRADIENT_FRAG_COMMON_VARIABLES +
|
||||
STR_LINEAR_GRADIENT_VARIABLES +
|
||||
STR_GRADIENT_FRAG_COMMON_FUNCTIONS +
|
||||
STR_LINEAR_GRADIENT_MAIN;
|
||||
|
||||
const char* LINEAR_GRADIENT_FRAG_SHADER = STR_LINEAR_GRADIENT_FRAG_SHADER.c_str();
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_FRAG_SHADER =
|
||||
STR_GRADIENT_FRAG_COMMON_VARIABLES +
|
||||
STR_RADIAL_GRADIENT_VARIABLES +
|
||||
STR_GRADIENT_FRAG_COMMON_FUNCTIONS +
|
||||
STR_RADIAL_GRADIENT_MAIN;
|
||||
|
||||
const char* RADIAL_GRADIENT_FRAG_SHADER = STR_RADIAL_GRADIENT_FRAG_SHADER.c_str();
|
||||
|
|
3
src/lib/gl_engine/tvgGlShaderSrc.h
Normal file → Executable file
3
src/lib/gl_engine/tvgGlShaderSrc.h
Normal file → Executable file
|
@ -25,5 +25,8 @@
|
|||
|
||||
extern const char* COLOR_VERT_SHADER;
|
||||
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;
|
||||
|
||||
#endif /* _TVG_GL_SHADERSRC_H_ */
|
||||
|
|
2
src/lib/tvgGlCanvas.cpp
Normal file → Executable file
2
src/lib/tvgGlCanvas.cpp
Normal file → Executable file
|
@ -67,7 +67,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
auto renderer = static_cast<GlRenderer*>(Canvas::pImpl.get()->renderer);
|
||||
if (!renderer) return Result::MemoryCorruption;
|
||||
|
||||
if (!renderer->target(buffer, stride, w, h, 0)) return Result::Unknown;
|
||||
if (!renderer->target(buffer, stride, w, h)) return Result::Unknown;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue