gl_engine: gradient implementation

Change-Id: If2413328437847d52ba1badc3b5c510fdd47ccd3
This commit is contained in:
Pranay Kumar Samanta 2020-09-04 10:26:28 +05:30 committed by Hermet Park
parent 5f100b8cff
commit af190033bb
16 changed files with 1028 additions and 132 deletions

5
src/lib/gl_engine/meson.build Normal file → Executable file
View 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
View 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
View 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
View 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
View 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
View 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_ */

View 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();
}
}

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

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

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

View 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
View 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
View 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
View 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