mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
gl_engine: make GlRenderTask generic with uniform block
* Use uniform block to pack all color informations * Move the actual gl draw call into GlRenderer::sync function, so all data is been uploaded into GPU * Make GlRenderTask simple and generic for direct gl draw
This commit is contained in:
parent
9e3b74bac5
commit
453cba7ddd
16 changed files with 412 additions and 793 deletions
|
@ -3,16 +3,13 @@ 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',
|
||||
|
|
|
@ -61,5 +61,25 @@ struct GlShape
|
|||
unique_ptr<GlGeometry> geometry;
|
||||
};
|
||||
|
||||
#define MAX_GRADIENT_STOPS 4
|
||||
|
||||
struct GlLinearGradientBlock
|
||||
{
|
||||
alignas(16) float nStops[4] = {};
|
||||
alignas(16) float startPos[2] = {};
|
||||
alignas(8) float stopPos[2] = {};
|
||||
alignas(8) float stopPoints[MAX_GRADIENT_STOPS] = {};
|
||||
alignas(16) float stopColors[4 * MAX_GRADIENT_STOPS] = {};
|
||||
};
|
||||
|
||||
struct GlRadialGradientBlock
|
||||
{
|
||||
alignas(16) float nStops[4] = {};
|
||||
alignas(16) float centerPos[2] = {};
|
||||
alignas(8) float radius[2] = {};
|
||||
alignas(8) float stopPoints[MAX_GRADIENT_STOPS] = {};
|
||||
alignas(16) float stopColors[4 * MAX_GRADIENT_STOPS] = {};
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TVG_GL_COMMON_H_ */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "tvgGlGpuBuffer.h"
|
||||
#include "tvgGlGeometry.h"
|
||||
#include "tvgGlTessellator.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
#define NORMALIZED_TOP_3D 1.0f
|
||||
#define NORMALIZED_BOTTOM_3D -1.0f
|
||||
|
@ -34,39 +35,22 @@ GlGeometry::~GlGeometry()
|
|||
{
|
||||
}
|
||||
|
||||
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer)
|
||||
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
|
||||
{
|
||||
mFillVertexOffset = 0;
|
||||
mStrokeVertexOffset = 0;
|
||||
mFillIndexOffset = 0;
|
||||
mStrokeIndexOffset = 0;
|
||||
mFillCount = 0;
|
||||
mStrokeCount = 0;
|
||||
|
||||
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
|
||||
Array<float> vertex;
|
||||
Array<uint32_t> index;
|
||||
fillVertex.clear();
|
||||
fillIndex.clear();
|
||||
|
||||
tvg::Tessellator tess{&vertex, &index};
|
||||
Tessellator tess{&fillVertex, &fillIndex};
|
||||
tess.tessellate(&rshape, true);
|
||||
|
||||
mFillCount = index.count;
|
||||
|
||||
mFillVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float));
|
||||
mFillIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
|
||||
Array<float> vertex;
|
||||
Array<uint32_t> index;
|
||||
strokeVertex.clear();
|
||||
strokeIndex.clear();
|
||||
|
||||
tvg::Stroker stroke{&vertex, &index};
|
||||
Stroker stroke{&strokeVertex, &strokeIndex};
|
||||
stroke.stroke(&rshape);
|
||||
|
||||
mStrokeCount = index.count;
|
||||
|
||||
mStrokeVertexOffset = gpuBuffer->push(vertex.data, vertex.count * sizeof(float));
|
||||
mStrokeIndexOffset = gpuBuffer->push(index.data, index.count * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -79,22 +63,34 @@ void GlGeometry::disableVertex(uint32_t location)
|
|||
}
|
||||
|
||||
|
||||
void GlGeometry::draw(const uint32_t location, RenderUpdateFlag flag)
|
||||
bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag)
|
||||
{
|
||||
|
||||
if (flag == RenderUpdateFlag::None) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Array<float>* vertexBuffer = nullptr;
|
||||
Array<uint32_t>* indexBuffer = nullptr;
|
||||
|
||||
uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset;
|
||||
uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset;
|
||||
uint32_t count = (flag == RenderUpdateFlag::Stroke) ? mStrokeCount : mFillCount;
|
||||
if (flag & RenderUpdateFlag::Stroke) {
|
||||
vertexBuffer = &strokeVertex;
|
||||
indexBuffer = &strokeIndex;
|
||||
} else {
|
||||
vertexBuffer = &fillVertex;
|
||||
indexBuffer = &fillIndex;
|
||||
}
|
||||
|
||||
GL_CHECK(glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), reinterpret_cast<void*>(vertexOffset)));
|
||||
GL_CHECK(glEnableVertexAttribArray(location));
|
||||
if (indexBuffer->count == 0) return false;
|
||||
|
||||
GL_CHECK(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, reinterpret_cast<void*>(indexOffset)));
|
||||
uint32_t vertexOffset = gpuBuffer->push(vertexBuffer->data, vertexBuffer->count * sizeof(float));
|
||||
uint32_t indexOffset = gpuBuffer->push(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
|
||||
|
||||
// vertex layout
|
||||
task->addVertexLayout(GlVertexLayout{0, 3, 3 * sizeof(float), vertexOffset});
|
||||
task->setDrawRange(indexOffset, indexBuffer->count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -180,26 +180,25 @@ public:
|
|||
};
|
||||
|
||||
class GlStageBuffer;
|
||||
class GlRenderTask;
|
||||
|
||||
class GlGeometry
|
||||
{
|
||||
public:
|
||||
|
||||
GlGeometry() = default;
|
||||
~GlGeometry();
|
||||
|
||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer);
|
||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
|
||||
void disableVertex(uint32_t location);
|
||||
void draw(const uint32_t location, RenderUpdateFlag flag);
|
||||
bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag);
|
||||
void updateTransform(const RenderTransform* transform, float w, float h);
|
||||
float* getTransforMatrix();
|
||||
|
||||
private:
|
||||
uint32_t mFillVertexOffset;
|
||||
uint32_t mFillIndexOffset;
|
||||
uint32_t mFillCount;
|
||||
uint32_t mStrokeVertexOffset;
|
||||
uint32_t mStrokeIndexOffset;
|
||||
uint32_t mStrokeCount;
|
||||
Array<float> fillVertex = {};
|
||||
Array<float> strokeVertex = {};
|
||||
Array<uint32_t> fillIndex = {};
|
||||
Array<uint32_t> strokeIndex = {};
|
||||
float mTransform[16];
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,18 @@
|
|||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
static GLint _getGpuBufferAlign()
|
||||
{
|
||||
static GLint offset = 0;
|
||||
|
||||
if (!offset)
|
||||
{
|
||||
GL_CHECK(glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &offset));
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
GlGpuBuffer::GlGpuBuffer()
|
||||
{
|
||||
GL_CHECK(glGenBuffers(1, &mGlBufferId));
|
||||
|
@ -60,6 +72,11 @@ void GlGpuBuffer::unbind(Target target)
|
|||
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
|
||||
}
|
||||
|
||||
GlStageBuffer::GlStageBuffer() : mVao(0), mGpuBuffer(new GlGpuBuffer)
|
||||
{
|
||||
GL_CHECK(glGenVertexArrays(1, &mVao));
|
||||
}
|
||||
|
||||
GlStageBuffer::~GlStageBuffer()
|
||||
{
|
||||
if (mVao) {
|
||||
|
@ -68,8 +85,10 @@ GlStageBuffer::~GlStageBuffer()
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t GlStageBuffer::push(void *data, uint32_t size)
|
||||
uint32_t GlStageBuffer::push(void *data, uint32_t size, bool alignGpuOffset)
|
||||
{
|
||||
if (alignGpuOffset) alignOffset();
|
||||
|
||||
uint32_t offset = mStageBuffer.count;
|
||||
|
||||
if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) {
|
||||
|
@ -87,14 +106,12 @@ void GlStageBuffer::flushToGPU()
|
|||
{
|
||||
if (mStageBuffer.empty()) return;
|
||||
|
||||
if (!mGpuBuffer) {
|
||||
mGpuBuffer.reset(new GlGpuBuffer);
|
||||
GL_CHECK(glGenVertexArrays(1, &mVao));
|
||||
}
|
||||
|
||||
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||
mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
|
||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||
|
||||
mStageBuffer.clear();
|
||||
}
|
||||
|
||||
void GlStageBuffer::bind()
|
||||
|
@ -102,6 +119,7 @@ void GlStageBuffer::bind()
|
|||
glBindVertexArray(mVao);
|
||||
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||
mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
|
||||
mGpuBuffer->bind(GlGpuBuffer::Target::UNIFORM_BUFFER);
|
||||
}
|
||||
|
||||
void GlStageBuffer::unbind()
|
||||
|
@ -109,4 +127,27 @@ void GlStageBuffer::unbind()
|
|||
glBindVertexArray(0);
|
||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
|
||||
mGpuBuffer->unbind(GlGpuBuffer::Target::UNIFORM_BUFFER);
|
||||
}
|
||||
|
||||
GLuint GlStageBuffer::getBufferId()
|
||||
{
|
||||
return mGpuBuffer->getBufferId();
|
||||
}
|
||||
|
||||
void GlStageBuffer::alignOffset()
|
||||
{
|
||||
|
||||
uint32_t alignment = _getGpuBufferAlign();
|
||||
|
||||
if (mStageBuffer.count % alignment == 0) return;
|
||||
|
||||
|
||||
uint32_t offset = alignment - mStageBuffer.count % alignment;
|
||||
|
||||
if (mStageBuffer.count + offset > mStageBuffer.reserved) {
|
||||
mStageBuffer.grow(max(alignment, mStageBuffer.reserved));
|
||||
}
|
||||
|
||||
mStageBuffer.count += offset;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
{
|
||||
ARRAY_BUFFER = GL_ARRAY_BUFFER,
|
||||
ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER,
|
||||
UNIFORM_BUFFER = GL_UNIFORM_BUFFER,
|
||||
};
|
||||
|
||||
GlGpuBuffer();
|
||||
|
@ -41,6 +42,8 @@ public:
|
|||
void updateBufferData(Target target, uint32_t size, const void* data);
|
||||
void bind(Target target);
|
||||
void unbind(Target target);
|
||||
|
||||
uint32_t getBufferId() { return mGlBufferId; }
|
||||
private:
|
||||
uint32_t mGlBufferId = 0;
|
||||
|
||||
|
@ -48,10 +51,10 @@ private:
|
|||
|
||||
class GlStageBuffer {
|
||||
public:
|
||||
GlStageBuffer() = default;
|
||||
GlStageBuffer();
|
||||
~GlStageBuffer();
|
||||
|
||||
uint32_t push(void* data, uint32_t size);
|
||||
uint32_t push(void* data, uint32_t size, bool alignGpuOffset = false);
|
||||
|
||||
void flushToGPU();
|
||||
|
||||
|
@ -59,6 +62,9 @@ public:
|
|||
|
||||
void unbind();
|
||||
|
||||
GLuint getBufferId();
|
||||
private:
|
||||
void alignOffset();
|
||||
private:
|
||||
GLuint mVao = 0;
|
||||
unique_ptr<GlGpuBuffer> mGpuBuffer = {};
|
||||
|
|
|
@ -87,6 +87,16 @@ int32_t GlProgram::getUniformLocation(const char* name)
|
|||
return location;
|
||||
}
|
||||
|
||||
int32_t GlProgram::getUniformBlockIndex(const char* name)
|
||||
{
|
||||
GL_CHECK(int32_t index = glGetUniformBlockIndex(mProgramObj, name));
|
||||
return index;
|
||||
}
|
||||
|
||||
uint32_t GlProgram::getProgramId()
|
||||
{
|
||||
return mProgramObj;
|
||||
}
|
||||
|
||||
void GlProgram::setUniform1Value(int32_t location, int count, const int* values)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#ifndef _TVG_GL_PROGRAM_H_
|
||||
#define _TVG_GL_PROGRAM_H_
|
||||
|
||||
#include <map>
|
||||
#include "tvgGlShader.h"
|
||||
|
||||
class GlProgram
|
||||
|
@ -37,6 +36,8 @@ public:
|
|||
static void unload();
|
||||
int32_t getAttributeLocation(const char* name);
|
||||
int32_t getUniformLocation(const char* name);
|
||||
int32_t getUniformBlockIndex(const char* name);
|
||||
uint32_t getProgramId();
|
||||
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);
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tvgGlPropertyInterface.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
VertexProperty PropertyInterface::mEmptyProperty;
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType)
|
||||
{
|
||||
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, dataType };
|
||||
property.propertyValues.setStride(propFormatSize);
|
||||
if (vertexProperty)
|
||||
{
|
||||
(*vertexProperty)[id] = property;
|
||||
return (*vertexProperty)[id];
|
||||
}
|
||||
}
|
||||
return mEmptyProperty;
|
||||
}
|
||||
|
||||
|
||||
void PropertyInterface::setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data)
|
||||
{
|
||||
std::map<int32_t, VertexProperty>::iterator itr = rTask->getUniformVertexProperty().find(propId);
|
||||
if (itr->second.propertyId == -1) return;
|
||||
|
||||
VertexProperty& prop = itr->second;
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
prop.propertyValues.set(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _TVG_GL_PROPERTY_INTERFACE_H_
|
||||
#define _TVG_GL_PROPERTY_INTERFACE_H_
|
||||
|
||||
#include "tvgGlRenderTask.h"
|
||||
|
||||
|
||||
#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 ADD_UNIFORM_PROPERTY_2(var, rtask, prog, varName, formatSize, location, datatype) \
|
||||
var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::UNIFORM, datatype); \
|
||||
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
|
||||
#define FORMAT_SIZE_MAT_4x4 16
|
||||
|
||||
class PropertyInterface
|
||||
{
|
||||
public:
|
||||
static VertexProperty& addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType = VertexProperty::DataType::FLOAT);
|
||||
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.propertyValues.set(first, args...);
|
||||
}
|
||||
|
||||
static void setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data);
|
||||
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_ */
|
|
@ -21,268 +21,62 @@
|
|||
*/
|
||||
|
||||
#include "tvgGlRenderTask.h"
|
||||
#include "tvgGlShaderSrc.h"
|
||||
#include "tvgGlPropertyInterface.h"
|
||||
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* External Class Implementation */
|
||||
/************************************************************************/
|
||||
|
||||
GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr<GlShader> shader)
|
||||
{
|
||||
mRenderType = renderType;
|
||||
mProgram = GlProgram::gen(shader);
|
||||
load();
|
||||
|
||||
VertexProperty* prop = nullptr;
|
||||
// now location is specified directly in shader
|
||||
mLocVertexAttribute = 0;
|
||||
ADD_UNIFORM_PROPERTY_2(prop, this, mProgram, "uTransform", FORMAT_SIZE_MAT_4x4, mLocTransform, VertexProperty::DataType::MATRIX);
|
||||
}
|
||||
|
||||
|
||||
GlRenderTask::RenderTypes GlRenderTask::getRenderType()
|
||||
{
|
||||
return mRenderType;
|
||||
}
|
||||
|
||||
|
||||
void GlRenderTask::load()
|
||||
void GlRenderTask::run()
|
||||
{
|
||||
// bind shader
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int32_t GlRenderTask::getTransformLocationPropertyId() const
|
||||
{
|
||||
return mLocTransform;
|
||||
}
|
||||
|
||||
|
||||
void GlRenderTask::setTransform(int count, float* transform)
|
||||
{
|
||||
if (mLocTransform != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocTransform, count, transform);
|
||||
// setup attribute layout
|
||||
for (uint32_t i = 0; i < mVertexLayout.count; i++) {
|
||||
const auto &layout = mVertexLayout[i];
|
||||
GL_CHECK(glEnableVertexAttribArray(layout.index));
|
||||
GL_CHECK(glVertexAttribPointer(layout.index, layout.size, GL_FLOAT,
|
||||
GL_FALSE, layout.stride,
|
||||
reinterpret_cast<void *>(layout.offset)));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
case VertexProperty::DataType::MATRIX: {
|
||||
mProgram->setUniform4x4Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
|
||||
break;
|
||||
}
|
||||
// binding uniforms
|
||||
for (uint32_t i = 0; i < mBindingResources.count; i++) {
|
||||
const auto& binding = mBindingResources[i];
|
||||
if (binding.type == GlBindingType::kTexture) {
|
||||
GL_CHECK(glActiveTexture(GL_TEXTURE0 + binding.bindPoint));
|
||||
GL_CHECK(glBindTexture(GL_TEXTURE_2D, binding.gBufferId));
|
||||
|
||||
mProgram->setUniform1Value(binding.location, 1, (int32_t*)&binding.bindPoint);
|
||||
} else if (binding.type == GlBindingType::kUniformBuffer) {
|
||||
|
||||
GL_CHECK(glUniformBlockBinding(mProgram->getProgramId(), binding.location, binding.bindPoint));
|
||||
GL_CHECK(glBindBufferRange(GL_UNIFORM_BUFFER, binding.bindPoint, binding.gBufferId,
|
||||
binding.bufferOffset, binding.bufferRange));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL_CHECK(glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, reinterpret_cast<void*>(mIndexOffset)));
|
||||
|
||||
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);
|
||||
// setup attribute layout
|
||||
for (uint32_t i = 0; i < mVertexLayout.count; i++) {
|
||||
const auto &layout = mVertexLayout[i];
|
||||
GL_CHECK(glDisableVertexAttribArray(layout.index));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GlGradientRenderTask::GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr<GlShader> shader)
|
||||
:GlRenderTask(renderType, shader)
|
||||
void GlRenderTask::addVertexLayout(const GlVertexLayout &layout)
|
||||
{
|
||||
VertexProperty* prop = nullptr;
|
||||
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);
|
||||
mVertexLayout.push(layout);
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setNoise(float noise)
|
||||
void GlRenderTask::addBindResource(const GlBindingResource &binding)
|
||||
{
|
||||
if (mLocNoise != -1)
|
||||
{
|
||||
PropertyInterface::setProperty(this, mLocNoise, noise);
|
||||
}
|
||||
mBindingResources.push(binding);
|
||||
}
|
||||
|
||||
|
||||
void GlGradientRenderTask::setStopCount(int32_t count)
|
||||
void GlRenderTask::setDrawRange(uint32_t offset, uint32_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);
|
||||
}
|
||||
}
|
||||
mIndexOffset = offset;
|
||||
mIndexCount = count;
|
||||
}
|
|
@ -23,102 +23,72 @@
|
|||
#ifndef _TVG_GL_RENDER_TASK_H_
|
||||
#define _TVG_GL_RENDER_TASK_H_
|
||||
|
||||
#include "tvgGlRendererProperties.h"
|
||||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
|
||||
struct GlVertexLayout
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t size;
|
||||
uint32_t stride;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
enum class GlBindingType
|
||||
{
|
||||
kUniformBuffer,
|
||||
kTexture,
|
||||
};
|
||||
|
||||
|
||||
struct GlBindingResource
|
||||
{
|
||||
GlBindingType type;
|
||||
/**
|
||||
* Binding point index.
|
||||
* Can be a uniform location for a texture
|
||||
* Can be a uniform buffer binding index for a uniform block
|
||||
*/
|
||||
uint32_t bindPoint = {};
|
||||
uint32_t location = {};
|
||||
GLuint gBufferId = {};
|
||||
uint32_t bufferOffset = {};
|
||||
uint32_t bufferRange = {};
|
||||
|
||||
GlBindingResource() = default;
|
||||
|
||||
GlBindingResource(uint32_t index, uint32_t location, uint32_t bufferId, uint32_t offset, uint32_t range)
|
||||
: type(GlBindingType::kUniformBuffer), bindPoint(index), location(location), gBufferId(bufferId), bufferOffset(offset), bufferRange(range)
|
||||
{
|
||||
}
|
||||
|
||||
GlBindingResource(uint32_t bindPoint, uint32_t texId, uint32_t location)
|
||||
: type(GlBindingType::kTexture), bindPoint(bindPoint), location(location), gBufferId(texId)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#define MAX_GRADIENT_STOPS 4
|
||||
|
||||
class GlRenderTask
|
||||
{
|
||||
public:
|
||||
enum RenderTypes
|
||||
{
|
||||
RT_Color = 0,
|
||||
RT_LinGradient,
|
||||
RT_RadGradient,
|
||||
GlRenderTask(GlProgram* program): mProgram(program) {}
|
||||
~GlRenderTask() = default;
|
||||
|
||||
RT_None,
|
||||
};
|
||||
void run();
|
||||
|
||||
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;
|
||||
int32_t getTransformLocationPropertyId() const;
|
||||
void setTransform(int count, float* transform_matrix);
|
||||
void uploadValues();
|
||||
void addVertexLayout(const GlVertexLayout& layout);
|
||||
void addBindResource(const GlBindingResource& binding);
|
||||
void setDrawRange(uint32_t offset, uint32_t count);
|
||||
|
||||
GlProgram* getProgram() { return mProgram; }
|
||||
private:
|
||||
RenderTypes mRenderType;
|
||||
|
||||
std::shared_ptr<GlProgram> mProgram;
|
||||
std::map<int32_t, VertexProperty> mAttributePropertyBuffer;
|
||||
std::map<int32_t, VertexProperty> mUniformPropertyBuffer;
|
||||
|
||||
int32_t mLocVertexAttribute = -1;
|
||||
int32_t mLocTransform = -1;
|
||||
GlProgram* mProgram;
|
||||
uint32_t mIndexOffset = {};
|
||||
uint32_t mIndexCount = {};
|
||||
Array<GlVertexLayout> mVertexLayout = {};
|
||||
Array<GlBindingResource> mBindingResources = {};
|
||||
};
|
||||
|
||||
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);
|
||||
int32_t getTransformLocationPropertyId() const;
|
||||
private:
|
||||
int32_t mLocNoise = -1;
|
||||
int32_t mLocStopCnt = -1;
|
||||
int32_t mLocStops = -1;
|
||||
int32_t mLocStopColors = -1;
|
||||
};
|
||||
|
||||
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_ */
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
#include "tvgGlRenderer.h"
|
||||
#include "tvgGlGpuBuffer.h"
|
||||
#include "tvgGlGeometry.h"
|
||||
#include "tvgGlPropertyInterface.h"
|
||||
#include "tvgGlRenderTask.h"
|
||||
#include "tvgGlProgram.h"
|
||||
#include "tvgGlShaderSrc.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* Internal Class Implementation */
|
||||
|
@ -67,8 +69,22 @@ bool GlRenderer::target(TVG_UNUSED uint32_t* buffer, uint32_t stride, uint32_t w
|
|||
|
||||
bool GlRenderer::sync()
|
||||
{
|
||||
GL_CHECK(glFinish());
|
||||
GlRenderTask::unload();
|
||||
mGpuBuffer->flushToGPU();
|
||||
|
||||
// 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));
|
||||
|
||||
mGpuBuffer->bind();
|
||||
|
||||
for(auto& task: mRenderTasks) {
|
||||
task->run();
|
||||
}
|
||||
|
||||
mGpuBuffer->unbind();
|
||||
|
||||
mRenderTasks.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -81,19 +97,10 @@ RenderRegion GlRenderer::region(TVG_UNUSED RenderData data)
|
|||
|
||||
bool GlRenderer::preRender()
|
||||
{
|
||||
if (mRenderTasks.size() == 0)
|
||||
if (mPrograms.size() == 0)
|
||||
{
|
||||
initShaders();
|
||||
}
|
||||
GlRenderTask::unload();
|
||||
|
||||
mGpuBuffer->flushToGPU();
|
||||
|
||||
// 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));
|
||||
|
||||
mGpuBuffer->bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -101,8 +108,6 @@ bool GlRenderer::preRender()
|
|||
|
||||
bool GlRenderer::postRender()
|
||||
{
|
||||
mGpuBuffer->unbind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -243,7 +248,7 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
|||
|
||||
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) )
|
||||
{
|
||||
if (!sdata->geometry->tesselate(rshape, sdata->updateFlag, mGpuBuffer.get())) return sdata;
|
||||
if (!sdata->geometry->tesselate(rshape, sdata->updateFlag)) return sdata;
|
||||
}
|
||||
return sdata;
|
||||
}
|
||||
|
@ -295,6 +300,9 @@ GlRenderer* GlRenderer::gen()
|
|||
return new GlRenderer();
|
||||
}
|
||||
|
||||
GlRenderer::GlRenderer() :mGpuBuffer(new GlStageBuffer), mPrograms(), mRenderTasks()
|
||||
{
|
||||
}
|
||||
|
||||
GlRenderer::~GlRenderer()
|
||||
{
|
||||
|
@ -309,30 +317,51 @@ GlRenderer::~GlRenderer()
|
|||
void GlRenderer::initShaders()
|
||||
{
|
||||
// Solid Color Renderer
|
||||
mRenderTasks.push_back(GlColorRenderTask::gen());
|
||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER)));
|
||||
|
||||
// Linear Gradient Renderer
|
||||
mRenderTasks.push_back(GlLinearGradientRenderTask::gen());
|
||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(GRADIENT_VERT_SHADER, LINEAR_GRADIENT_FRAG_SHADER)));
|
||||
|
||||
// Radial Gradient Renderer
|
||||
mRenderTasks.push_back(GlRadialGradientRenderTask::gen());
|
||||
mPrograms.push_back(make_unique<GlProgram>(GlShader::gen(GRADIENT_VERT_SHADER, RADIAL_GRADIENT_FRAG_SHADER)));
|
||||
}
|
||||
|
||||
|
||||
void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag)
|
||||
{
|
||||
GlColorRenderTask* renderTask = static_cast<GlColorRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_Color].get());
|
||||
assert(renderTask);
|
||||
renderTask->load();
|
||||
float* matrix = sdata.geometry->getTransforMatrix();
|
||||
PropertyInterface::clearData(renderTask);
|
||||
renderTask->setColor(r, g, b, a);
|
||||
renderTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix);
|
||||
int32_t vertexLoc = renderTask->getLocationPropertyId();
|
||||
renderTask->uploadValues();
|
||||
sdata.geometry->draw(vertexLoc, flag);
|
||||
sdata.geometry->disableVertex(vertexLoc);
|
||||
auto task = make_unique<GlRenderTask>(mPrograms[RT_Color].get());
|
||||
|
||||
if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return;
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
auto matrix = sdata.geometry->getTransforMatrix();
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
// color
|
||||
{
|
||||
float color[4] = {r / 255.f, g / 255.f, b / 255.f, a / 255.f};
|
||||
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("ColorInfo");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(color, 4 * sizeof(float), true),
|
||||
4 * sizeof(float),
|
||||
});
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
}
|
||||
|
||||
|
||||
|
@ -342,50 +371,90 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
|
|||
auto stopCnt = fill->colorStops(&stops);
|
||||
if (stopCnt < 2) return;
|
||||
|
||||
GlGradientRenderTask* rTask = nullptr;
|
||||
auto matrix = sdata.geometry->getTransforMatrix();
|
||||
unique_ptr<GlRenderTask> task;
|
||||
|
||||
switch (fill->identifier()) {
|
||||
case TVG_CLASS_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 TVG_CLASS_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 (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
||||
task = make_unique<GlRenderTask>(mPrograms[RT_LinGradient].get());
|
||||
} else if (fill->identifier() == TVG_CLASS_ID_RADIAL) {
|
||||
task = make_unique<GlRenderTask>(mPrograms[RT_RadGradient].get());
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (rTask) {
|
||||
auto vertexLoc = rTask->getLocationPropertyId();
|
||||
rTask->setNoise(NOISE_LEVEL);
|
||||
rTask->setStopCount((int)stopCnt);
|
||||
rTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix);
|
||||
|
||||
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);
|
||||
if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return;
|
||||
|
||||
// matrix buffer
|
||||
{
|
||||
auto matrix = sdata.geometry->getTransforMatrix();
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("Matrix");
|
||||
|
||||
task->addBindResource(GlBindingResource{
|
||||
0,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(matrix, 16 * sizeof(float), true),
|
||||
16 * sizeof(float),
|
||||
});
|
||||
}
|
||||
|
||||
// gradient block
|
||||
{
|
||||
GlBindingResource gradientBinding{};
|
||||
uint32_t loc = task->getProgram()->getUniformBlockIndex("GradientInfo");
|
||||
|
||||
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
||||
auto linearFill = static_cast<const LinearGradient*>(fill);
|
||||
|
||||
GlLinearGradientBlock gradientBlock;
|
||||
|
||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||
gradientBlock.stopPoints[i] = stops[i].offset;
|
||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||
}
|
||||
|
||||
linearFill->linear(&gradientBlock.startPos[0], &gradientBlock.startPos[1], &gradientBlock.stopPos[0], &gradientBlock.stopPos[1]);
|
||||
|
||||
gradientBinding = GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(&gradientBlock, sizeof(GlLinearGradientBlock), true),
|
||||
sizeof(GlLinearGradientBlock),
|
||||
};
|
||||
} else {
|
||||
auto radialFill = static_cast<const RadialGradient*>(fill);
|
||||
|
||||
GlRadialGradientBlock gradientBlock;
|
||||
|
||||
gradientBlock.nStops[0] = stopCnt * 1.f;
|
||||
gradientBlock.nStops[1] = NOISE_LEVEL;
|
||||
for (uint32_t i = 0; i < stopCnt; ++i) {
|
||||
gradientBlock.stopPoints[i] = stops[i].offset;
|
||||
gradientBlock.stopColors[i * 4 + 0] = stops[i].r / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 1] = stops[i].g / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 2] = stops[i].b / 255.f;
|
||||
gradientBlock.stopColors[i * 4 + 3] = stops[i].a / 255.f;
|
||||
}
|
||||
|
||||
radialFill->radial(&gradientBlock.centerPos[0], &gradientBlock.centerPos[1], &gradientBlock.radius[0]);
|
||||
|
||||
gradientBinding = GlBindingResource{
|
||||
1,
|
||||
loc,
|
||||
mGpuBuffer->getBufferId(),
|
||||
mGpuBuffer->push(&gradientBlock, sizeof(GlRadialGradientBlock), true),
|
||||
sizeof(GlRadialGradientBlock),
|
||||
};
|
||||
}
|
||||
|
||||
rTask->uploadValues();
|
||||
sdata.geometry->draw(vertexLoc, flag);
|
||||
sdata.geometry->disableVertex(vertexLoc);
|
||||
task->addBindResource(gradientBinding);
|
||||
}
|
||||
|
||||
mRenderTasks.emplace_back(std::move(task));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,12 +23,23 @@
|
|||
#ifndef _TVG_GL_RENDERER_H_
|
||||
#define _TVG_GL_RENDERER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "tvgGlRenderTask.h"
|
||||
#include "tvgGlGpuBuffer.h"
|
||||
|
||||
class GlRenderer : public RenderMethod
|
||||
{
|
||||
public:
|
||||
enum RenderTypes
|
||||
{
|
||||
RT_Color = 0,
|
||||
RT_LinGradient,
|
||||
RT_RadGradient,
|
||||
|
||||
RT_None,
|
||||
};
|
||||
|
||||
Surface surface = {nullptr, 0, 0, 0, ColorSpace::Unsupported, true};
|
||||
|
||||
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) override;
|
||||
|
@ -59,15 +70,16 @@ public:
|
|||
static int term();
|
||||
|
||||
private:
|
||||
GlRenderer(): mGpuBuffer(new GlStageBuffer) {};
|
||||
GlRenderer();
|
||||
~GlRenderer();
|
||||
|
||||
void initShaders();
|
||||
void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag);
|
||||
void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag);
|
||||
|
||||
vector<shared_ptr<GlRenderTask>> mRenderTasks;
|
||||
std::unique_ptr<GlStageBuffer> mGpuBuffer;
|
||||
vector<std::unique_ptr<GlProgram>> mPrograms;
|
||||
vector<std::unique_ptr<GlRenderTask>> mRenderTasks;
|
||||
};
|
||||
|
||||
#endif /* _TVG_GL_RENDERER_H_ */
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _TVG_GL_RENDER_PROPERTIES_H_
|
||||
#define _TVG_GL_RENDER_PROPERTIES_H_
|
||||
|
||||
#include <vector>
|
||||
#include "tvgGlCommon.h"
|
||||
#include "tvgGlProgram.h"
|
||||
|
||||
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,
|
||||
MATRIX
|
||||
};
|
||||
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_ */
|
|
@ -27,20 +27,26 @@
|
|||
|
||||
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||
layout(location = 0) in vec3 aLocation; \n
|
||||
uniform mat4 uTransform; \n
|
||||
layout(std140) uniform Matrix { \n
|
||||
mat4 transform; \n
|
||||
} uMatrix; \n
|
||||
out float vOpacity; \n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
gl_Position = \n
|
||||
uMatrix.transform * vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
vOpacity = aLocation.z; \n
|
||||
});
|
||||
|
||||
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
||||
uniform vec4 uColor; \n
|
||||
layout(std140) uniform ColorInfo { \n
|
||||
vec4 solidColor; \n
|
||||
} uColorInfo; \n
|
||||
in float vOpacity; \n
|
||||
out vec4 FragColor; \n
|
||||
void main() \n
|
||||
{ \n
|
||||
vec4 uColor = uColorInfo.solidColor; \n
|
||||
FragColor = vec4(uColor.xyz, uColor.w*vOpacity); \n
|
||||
});
|
||||
|
||||
|
@ -48,22 +54,20 @@ const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER(
|
|||
layout(location = 0) in vec3 aLocation; \n
|
||||
out float vOpacity; \n
|
||||
out vec2 vPos; \n
|
||||
uniform mat4 uTransform; \n
|
||||
layout(std140) uniform Matrix { \n
|
||||
mat4 transform; \n
|
||||
} uMatrix; \n
|
||||
\n
|
||||
void main() \n
|
||||
{ \n
|
||||
gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
gl_Position = uMatrix.transform * vec4(aLocation.xy, 0.0, 1.0); \n
|
||||
vOpacity = aLocation.z; \n
|
||||
vPos = aLocation.xy; \n
|
||||
});
|
||||
|
||||
|
||||
std::string STR_GRADIENT_FRAG_COMMON_VARIABLES = TVG_COMPOSE_SHADER( \n
|
||||
std::string STR_GRADIENT_FRAG_COMMON_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
const int MAX_STOP_COUNT = 4; \n
|
||||
uniform float nStops; \n
|
||||
uniform float noise_level; \n
|
||||
uniform float stopPoints[MAX_STOP_COUNT]; \n
|
||||
uniform vec4 stopColors[MAX_STOP_COUNT]; \n
|
||||
in vec2 vPos; \n
|
||||
in float vOpacity; \n
|
||||
);
|
||||
|
@ -80,23 +84,26 @@ vec4 gradient(float t)
|
|||
{ \n
|
||||
vec4 col = vec4(0.0); \n
|
||||
int i = 0; \n
|
||||
int count = int(nStops); \n
|
||||
if (t <= stopPoints[0]) \n
|
||||
int count = int(uGradientInfo.nStops[0]); \n
|
||||
if (t <= uGradientInfo.stopPoints[0]) \n
|
||||
{ \n
|
||||
col += stopColors[0]; \n
|
||||
col += uGradientInfo.stopColors[0]; \n
|
||||
} \n
|
||||
else if (t >= stopPoints[count - 1]) \n
|
||||
else if (t >= uGradientInfo.stopPoints[count - 1]) \n
|
||||
{ \n
|
||||
col += stopColors[count - 1]; \n
|
||||
col += uGradientInfo.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
|
||||
if (t > uGradientInfo.stopPoints[i] && t < uGradientInfo.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
|
||||
col += (uGradientInfo.stopColors[i] * \n
|
||||
(1. - gradientStep(uGradientInfo.stopPoints[i], \n
|
||||
uGradientInfo.stopPoints[i + 1], t))); \n
|
||||
col += (uGradientInfo.stopColors[i + 1] * \n
|
||||
gradientStep(uGradientInfo.stopPoints[i], uGradientInfo.stopPoints[i + 1], t)); \n
|
||||
break; \n
|
||||
} \n
|
||||
} \n
|
||||
|
@ -113,8 +120,13 @@ vec3 ScreenSpaceDither(vec2 vScreenPos)
|
|||
});
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
uniform vec2 gradStartPos; \n
|
||||
uniform vec2 gradEndPos; \n
|
||||
layout(std140) uniform GradientInfo { \n
|
||||
vec4 nStops; \n
|
||||
vec2 gradStartPos; \n
|
||||
vec2 gradEndPos; \n
|
||||
vec4 stopPoints; \n
|
||||
vec4 stopColors[MAX_STOP_COUNT]; \n
|
||||
} uGradientInfo ; \n
|
||||
);
|
||||
|
||||
std::string STR_LINEAR_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||
|
@ -122,8 +134,8 @@ out vec4 FragColor;
|
|||
void main() \n
|
||||
{ \n
|
||||
vec2 pos = vPos; \n
|
||||
vec2 st = gradStartPos; \n
|
||||
vec2 ed = gradEndPos; \n
|
||||
vec2 st = uGradientInfo.gradStartPos; \n
|
||||
vec2 ed = uGradientInfo.gradEndPos; \n
|
||||
\n
|
||||
vec2 ba = ed - st; \n
|
||||
\n
|
||||
|
@ -134,14 +146,19 @@ void main()
|
|||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n
|
||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
FragColor = vec4(finalCol.xyz, finalCol.w* vOpacity); \n
|
||||
});
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||
uniform vec2 gradStartPos; \n
|
||||
uniform float stRadius; \n
|
||||
layout(std140) uniform GradientInfo { \n
|
||||
vec4 nStops; \n
|
||||
vec2 centerPos; \n
|
||||
vec2 radius; \n
|
||||
vec4 stopPoints; \n
|
||||
vec4 stopColors[MAX_STOP_COUNT]; \n
|
||||
} uGradientInfo ; \n
|
||||
);
|
||||
|
||||
std::string STR_RADIAL_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||
|
@ -150,8 +167,8 @@ void main()
|
|||
{ \n
|
||||
vec2 pos = vPos; \n
|
||||
\n
|
||||
float ba = stRadius; \n
|
||||
float d = distance(gradStartPos, pos); \n
|
||||
float ba = uGradientInfo.radius.x; \n
|
||||
float d = distance(uGradientInfo.centerPos, pos); \n
|
||||
d = (d / ba); \n
|
||||
\n
|
||||
//float t = smoothstep(0.0, 1.0, clamp(d, 0.0, 1.0)); \n
|
||||
|
@ -159,7 +176,7 @@ void main()
|
|||
\n
|
||||
vec4 color = gradient(t); \n
|
||||
\n
|
||||
vec3 noise = 8.0 * noise_level * ScreenSpaceDither(pos); \n
|
||||
vec3 noise = 8.0 * uGradientInfo.nStops[1] * ScreenSpaceDither(pos); \n
|
||||
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||
FragColor = vec4(finalCol.xyz, finalCol.w * vOpacity); \n
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue