diff --git a/src/lib/gl_engine/meson.build b/src/lib/gl_engine/meson.build old mode 100644 new mode 100755 index 63c7ee89..5efb7b14 --- a/src/lib/gl_engine/meson.build +++ b/src/lib/gl_engine/meson.build @@ -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', ] diff --git a/src/lib/gl_engine/tvgGlCommon.h b/src/lib/gl_engine/tvgGlCommon.h old mode 100644 new mode 100755 index db137f22..11a71817 --- a/src/lib/gl_engine/tvgGlCommon.h +++ b/src/lib/gl_engine/tvgGlCommon.h @@ -24,6 +24,7 @@ #define _TVG_GL_COMMON_H_ #include "tvgCommon.h" +#include #define GL_CHECK(x) \ diff --git a/src/lib/gl_engine/tvgGlGeometry.cpp b/src/lib/gl_engine/tvgGlGeometry.cpp old mode 100644 new mode 100755 index e89077d7..0d6245c7 --- a/src/lib/gl_engine/tvgGlGeometry.cpp +++ b/src/lib/gl_engine/tvgGlGeometry.cpp @@ -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); } diff --git a/src/lib/gl_engine/tvgGlGeometry.h b/src/lib/gl_engine/tvgGlGeometry.h old mode 100644 new mode 100755 index e5f1b033..68dc99d4 --- a/src/lib/gl_engine/tvgGlGeometry.h +++ b/src/lib/gl_engine/tvgGlGeometry.h @@ -128,6 +128,8 @@ public: } }; +typedef GlPoint GlSize; + struct SmoothPoint { GlPoint orgPt; @@ -174,6 +176,9 @@ struct GlPrimitive vector 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 &indices); void addQuadIndices(uint32_t &curPt, vector &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 mGpuBuffer; diff --git a/src/lib/gl_engine/tvgGlProgram.cpp b/src/lib/gl_engine/tvgGlProgram.cpp old mode 100644 new mode 100755 index 9d03849b..38ed3e1b --- a/src/lib/gl_engine/tvgGlProgram.cpp +++ b/src/lib/gl_engine/tvgGlProgram.cpp @@ -26,17 +26,7 @@ #include -static std::vector gStdAttributes = { - "aLocation" -}; - -static std::vector gStdUniforms = { - "uColor" -}; - uint32_t GlProgram::mCurrentProgram = 0; -map GlProgram::mAttributeBuffer; -map GlProgram::mUniformBuffer; unique_ptr GlProgram::gen(std::shared_ptr shader) @@ -48,17 +38,6 @@ unique_ptr GlProgram::gen(std::shared_ptr shader) GlProgram::GlProgram(std::shared_ptr 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)); } diff --git a/src/lib/gl_engine/tvgGlProgram.h b/src/lib/gl_engine/tvgGlProgram.h old mode 100644 new mode 100755 index ccdb258c..730274f6 --- a/src/lib/gl_engine/tvgGlProgram.h +++ b/src/lib/gl_engine/tvgGlProgram.h @@ -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 mAttributeBuffer; - static std::map mUniformBuffer; }; #endif /* _TVG_GL_PROGRAM_H_ */ diff --git a/src/lib/gl_engine/tvgGlPropertyInterface.cpp b/src/lib/gl_engine/tvgGlPropertyInterface.cpp new file mode 100755 index 00000000..ebb1c57b --- /dev/null +++ b/src/lib/gl_engine/tvgGlPropertyInterface.cpp @@ -0,0 +1,83 @@ +#include "tvgGlPropertyInterface.h" +#include "tvgGlRenderTask.h" + +VertexProperty PropertyInterface::mEmptyProperty; + +VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType) +{ + std::map* 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& 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& 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& vertexProperty = rTask->getUniformVertexProperty(); + if (vertexProperty.find(propId) != vertexProperty.end()) + { + return vertexProperty[propId]; + } + return mEmptyProperty; +} + + +void PropertyInterface::clearData(GlRenderTask* rTask) +{ + std::map& vertexProperty = rTask->getUniformVertexProperty(); + for (auto& prop : vertexProperty) + { + prop.second.propertyValues.clear(); + } +} diff --git a/src/lib/gl_engine/tvgGlPropertyInterface.h b/src/lib/gl_engine/tvgGlPropertyInterface.h new file mode 100755 index 00000000..c8f309ca --- /dev/null +++ b/src/lib/gl_engine/tvgGlPropertyInterface.h @@ -0,0 +1,64 @@ +#ifndef _TVG_GL_PROPERTY_INTERFACE_H_ +#define _TVG_GL_PROPERTY_INTERFACE_H_ + +#include "tvgGlRendererProperties.h" +#include "tvgGlRenderTask.h" + +#include +#include +#include + +#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 prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType); + template + 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 + static void setProperty(GlRenderTask* rTask, int32_t propId, float first, Args... args) + { + std::map::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_ */ diff --git a/src/lib/gl_engine/tvgGlRenderTask.cpp b/src/lib/gl_engine/tvgGlRenderTask.cpp new file mode 100755 index 00000000..accb957e --- /dev/null +++ b/src/lib/gl_engine/tvgGlRenderTask.cpp @@ -0,0 +1,267 @@ +#include "tvgGlCommon.h" +#include "tvgGlShaderSrc.h" +#include "tvgGlRenderTask.h" +#include "tvgGlPropertyInterface.h" + +#include +#include +#include + + +GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr 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 GlRenderTask::getProgram() +{ + return mProgram; +} + + +std::map& GlRenderTask::getAttributeVertexProperty() +{ + return mAttributePropertyBuffer; +} + + +std::map& 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::gen() +{ + return std::make_shared(); +} + + +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 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::gen() +{ + return std::make_shared(); +} + + +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::gen() +{ + return std::make_shared(); +} + + +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); + } +} diff --git a/src/lib/gl_engine/tvgGlRenderTask.h b/src/lib/gl_engine/tvgGlRenderTask.h new file mode 100755 index 00000000..d4b28e5e --- /dev/null +++ b/src/lib/gl_engine/tvgGlRenderTask.h @@ -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 +#include +#include + +#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 shader); + RenderTypes getRenderType(); + + void load(); + static void unload(); + std::shared_ptr getProgram(); + std::map& getAttributeVertexProperty(); + std::map& getUniformVertexProperty(); + int32_t getLocationPropertyId() const; + void uploadValues(); + +private: + RenderTypes mRenderType; + + uint32_t propertyFormatSize; + std::shared_ptr mProgram; + std::map mAttributePropertyBuffer; + std::map mUniformPropertyBuffer; + + int32_t mLocVertexAttribute; +}; + +class GlColorRenderTask : public GlRenderTask +{ +public: + static std::shared_ptr 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 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 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 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_ */ diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp old mode 100644 new mode 100755 index 9e9f8efc..266902a5 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -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(); //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(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 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(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(mRenderTasks[GlRenderTask::RenderTypes::RT_LinGradient].get()); + assert(renderTask); + rTask = renderTask; + renderTask->load(); + PropertyInterface::clearData(renderTask); + const LinearGradient* grad = static_cast(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(mRenderTasks[GlRenderTask::RenderTypes::RT_RadGradient].get()); + assert(renderTask); + rTask = renderTask; + renderTask->load(); + PropertyInterface::clearData(renderTask); + const RadialGradient* grad = static_cast(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 diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h old mode 100644 new mode 100755 index a0f57152..79addd64 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -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 mColorProgram = nullptr; - int32_t mColorUniformLoc = 0; - uint32_t mVertexAttrLoc = 0; + vector> mRenderTasks; }; #endif /* _TVG_GL_RENDERER_H_ */ diff --git a/src/lib/gl_engine/tvgGlRendererProperties.h b/src/lib/gl_engine/tvgGlRendererProperties.h new file mode 100755 index 00000000..dd009237 --- /dev/null +++ b/src/lib/gl_engine/tvgGlRendererProperties.h @@ -0,0 +1,92 @@ +#ifndef _TVG_GL_RENDER_PROPERTIES_H_ +#define _TVG_GL_RENDER_PROPERTIES_H_ + +#include "tvgGlShader.h" +#include "tvgGlProgram.h" + +#include +#include +#include +#include + +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 + void set(float first, Args... args) + { + if (values.capacity() == values.size()) + { + values.reserve(values.size() + stride); + } + set(first); + set(args...); + } + +private: + std::vector 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_ */ diff --git a/src/lib/gl_engine/tvgGlShaderSrc.cpp b/src/lib/gl_engine/tvgGlShaderSrc.cpp old mode 100644 new mode 100755 index 135ef435..91c31de0 --- a/src/lib/gl_engine/tvgGlShaderSrc.cpp +++ b/src/lib/gl_engine/tvgGlShaderSrc.cpp @@ -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 -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(); diff --git a/src/lib/gl_engine/tvgGlShaderSrc.h b/src/lib/gl_engine/tvgGlShaderSrc.h old mode 100644 new mode 100755 index 22993547..cc919102 --- a/src/lib/gl_engine/tvgGlShaderSrc.h +++ b/src/lib/gl_engine/tvgGlShaderSrc.h @@ -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_ */ diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp old mode 100644 new mode 100755 index 235bacbb..b425da0e --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -67,7 +67,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t auto renderer = static_cast(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