'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',
]
#define _TVG_GL_COMMON_H_\r
\r
#include "tvgCommon.h"\r
+#include <assert.h>\r
\r
\r
#define GL_CHECK(x) \\r
}
+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;
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:
+ case PathCommand::MoveTo: {
+ if (curPrimitive)
+ {
+ 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:
- {
+ }
+ __attribute__ ((fallthrough));
+ case PathCommand::LineTo: {
if (curPrimitive)
{
- addPoint(*curPrimitive, pts[0]);
+ 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;
}
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)
{
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);
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)
{
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()));
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));
}
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;
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);
}
}
};
+typedef GlPoint GlSize;
+
struct SmoothPoint
{
GlPoint orgPt;
vector<SmoothPoint> mAAPoints;
VertexDataArray mFill;
VertexDataArray mStroke;
+ GlPoint mTopLeft;
+ GlPoint mBottomRight;
+ bool mIsClosed = false;
};
class GlGpuBuffer;
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);
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;
#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)
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());
- }
-
}
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::setUniform1Value(int32_t location, int count, const int* values)
+{
+ 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::setUniformValue(int32_t location, float r, float g, float b, float a)
+void GlProgram::setUniform4Value(int32_t location, int count, const float* values)
{
- glUniform4f(location, r, g, b, a);
+ GL_CHECK(glUniform4fv(location, count, values));
}
~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:
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_ */
--- /dev/null
+#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();
+ }
+}
--- /dev/null
+#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_ */
--- /dev/null
+#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);
+ }
+}
--- /dev/null
+#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_ */
#include "tvgGlGeometry.h"
#include "tvgGlCommon.h"
#include "tvgGlRenderer.h"
+#include "tvgGlPropertyInterface.h"
/************************************************************************/
/* Internal Class Implementation */
/* External Class Implementation */
/************************************************************************/
+#define NOISE_LEVEL 0.5f
+
bool GlRenderer::clear()
{
//TODO: (Request) to clear target
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;
}
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);
}
}
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
- initShaders();
-
sdata->geometry = make_unique<GlGeometry>();
//invisible?
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;
GlRenderer::~GlRenderer()
{
- if (mColorProgram.get())
- {
- mColorProgram.reset(nullptr);
- }
+ mRenderTasks.clear();
--rendererCnt;
if (!initEngine) _termEngine();
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);
+ }
+}
-}
\ No newline at end of file
#include "tvgGlCommon.h"
#include "tvgGlProgram.h"
-
+#include "tvgGlRenderTask.h"
class GlRenderer : public RenderMethod
{
~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_ */
--- /dev/null
+#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_ */
#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";
-
-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";
+#include <string>
+#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();
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_ */
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