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',
|
'tvgGlGeometry.h',
|
||||||
'tvgGlGpuBuffer.h',
|
'tvgGlGpuBuffer.h',
|
||||||
'tvgGlProgram.h',
|
'tvgGlProgram.h',
|
||||||
'tvgGlPropertyInterface.h',
|
|
||||||
'tvgGlRenderer.h',
|
'tvgGlRenderer.h',
|
||||||
'tvgGlRendererProperties.h',
|
|
||||||
'tvgGlRenderTask.h',
|
'tvgGlRenderTask.h',
|
||||||
'tvgGlShader.h',
|
'tvgGlShader.h',
|
||||||
'tvgGlShaderSrc.h',
|
'tvgGlShaderSrc.h',
|
||||||
'tvgGlGeometry.cpp',
|
'tvgGlGeometry.cpp',
|
||||||
'tvgGlGpuBuffer.cpp',
|
'tvgGlGpuBuffer.cpp',
|
||||||
'tvgGlProgram.cpp',
|
'tvgGlProgram.cpp',
|
||||||
'tvgGlPropertyInterface.cpp',
|
|
||||||
'tvgGlRenderer.cpp',
|
'tvgGlRenderer.cpp',
|
||||||
'tvgGlRenderTask.cpp',
|
'tvgGlRenderTask.cpp',
|
||||||
'tvgGlShader.cpp',
|
'tvgGlShader.cpp',
|
||||||
|
|
|
@ -61,5 +61,25 @@ struct GlShape
|
||||||
unique_ptr<GlGeometry> geometry;
|
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_ */
|
#endif /* _TVG_GL_COMMON_H_ */
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
#include "tvgGlGeometry.h"
|
#include "tvgGlGeometry.h"
|
||||||
#include "tvgGlTessellator.h"
|
#include "tvgGlTessellator.h"
|
||||||
|
#include "tvgGlRenderTask.h"
|
||||||
|
|
||||||
#define NORMALIZED_TOP_3D 1.0f
|
#define NORMALIZED_TOP_3D 1.0f
|
||||||
#define NORMALIZED_BOTTOM_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)) {
|
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform)) {
|
||||||
Array<float> vertex;
|
fillVertex.clear();
|
||||||
Array<uint32_t> index;
|
fillIndex.clear();
|
||||||
|
|
||||||
tvg::Tessellator tess{&vertex, &index};
|
Tessellator tess{&fillVertex, &fillIndex};
|
||||||
tess.tessellate(&rshape, true);
|
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)) {
|
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
|
||||||
Array<float> vertex;
|
strokeVertex.clear();
|
||||||
Array<uint32_t> index;
|
strokeIndex.clear();
|
||||||
|
|
||||||
tvg::Stroker stroke{&vertex, &index};
|
Stroker stroke{&strokeVertex, &strokeIndex};
|
||||||
stroke.stroke(&rshape);
|
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;
|
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) {
|
if (flag == RenderUpdateFlag::None) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<float>* vertexBuffer = nullptr;
|
||||||
|
Array<uint32_t>* indexBuffer = nullptr;
|
||||||
|
|
||||||
uint32_t vertexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeVertexOffset : mFillVertexOffset;
|
if (flag & RenderUpdateFlag::Stroke) {
|
||||||
uint32_t indexOffset = (flag == RenderUpdateFlag::Stroke) ? mStrokeIndexOffset : mFillIndexOffset;
|
vertexBuffer = &strokeVertex;
|
||||||
uint32_t count = (flag == RenderUpdateFlag::Stroke) ? mStrokeCount : mFillCount;
|
indexBuffer = &strokeIndex;
|
||||||
|
} else {
|
||||||
|
vertexBuffer = &fillVertex;
|
||||||
|
indexBuffer = &fillIndex;
|
||||||
|
}
|
||||||
|
|
||||||
GL_CHECK(glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), reinterpret_cast<void*>(vertexOffset)));
|
if (indexBuffer->count == 0) return false;
|
||||||
GL_CHECK(glEnableVertexAttribArray(location));
|
|
||||||
|
|
||||||
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 GlStageBuffer;
|
||||||
|
class GlRenderTask;
|
||||||
|
|
||||||
class GlGeometry
|
class GlGeometry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
GlGeometry() = default;
|
||||||
~GlGeometry();
|
~GlGeometry();
|
||||||
|
|
||||||
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag, GlStageBuffer* gpuBuffer);
|
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
|
||||||
void disableVertex(uint32_t location);
|
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);
|
void updateTransform(const RenderTransform* transform, float w, float h);
|
||||||
float* getTransforMatrix();
|
float* getTransforMatrix();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t mFillVertexOffset;
|
Array<float> fillVertex = {};
|
||||||
uint32_t mFillIndexOffset;
|
Array<float> strokeVertex = {};
|
||||||
uint32_t mFillCount;
|
Array<uint32_t> fillIndex = {};
|
||||||
uint32_t mStrokeVertexOffset;
|
Array<uint32_t> strokeIndex = {};
|
||||||
uint32_t mStrokeIndexOffset;
|
|
||||||
uint32_t mStrokeCount;
|
|
||||||
float mTransform[16];
|
float mTransform[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,18 @@
|
||||||
/* Internal Class Implementation */
|
/* 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()
|
GlGpuBuffer::GlGpuBuffer()
|
||||||
{
|
{
|
||||||
GL_CHECK(glGenBuffers(1, &mGlBufferId));
|
GL_CHECK(glGenBuffers(1, &mGlBufferId));
|
||||||
|
@ -60,6 +72,11 @@ void GlGpuBuffer::unbind(Target target)
|
||||||
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
|
GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlStageBuffer::GlStageBuffer() : mVao(0), mGpuBuffer(new GlGpuBuffer)
|
||||||
|
{
|
||||||
|
GL_CHECK(glGenVertexArrays(1, &mVao));
|
||||||
|
}
|
||||||
|
|
||||||
GlStageBuffer::~GlStageBuffer()
|
GlStageBuffer::~GlStageBuffer()
|
||||||
{
|
{
|
||||||
if (mVao) {
|
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;
|
uint32_t offset = mStageBuffer.count;
|
||||||
|
|
||||||
if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) {
|
if (this->mStageBuffer.reserved - this->mStageBuffer.count < size) {
|
||||||
|
@ -87,14 +106,12 @@ void GlStageBuffer::flushToGPU()
|
||||||
{
|
{
|
||||||
if (mStageBuffer.empty()) return;
|
if (mStageBuffer.empty()) return;
|
||||||
|
|
||||||
if (!mGpuBuffer) {
|
|
||||||
mGpuBuffer.reset(new GlGpuBuffer);
|
|
||||||
GL_CHECK(glGenVertexArrays(1, &mVao));
|
|
||||||
}
|
|
||||||
|
|
||||||
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||||
mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
|
mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, mStageBuffer.count, mStageBuffer.data);
|
||||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||||
|
|
||||||
|
mStageBuffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlStageBuffer::bind()
|
void GlStageBuffer::bind()
|
||||||
|
@ -102,6 +119,7 @@ void GlStageBuffer::bind()
|
||||||
glBindVertexArray(mVao);
|
glBindVertexArray(mVao);
|
||||||
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
mGpuBuffer->bind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||||
mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
|
mGpuBuffer->bind(GlGpuBuffer::Target::ELEMENT_ARRAY_BUFFER);
|
||||||
|
mGpuBuffer->bind(GlGpuBuffer::Target::UNIFORM_BUFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlStageBuffer::unbind()
|
void GlStageBuffer::unbind()
|
||||||
|
@ -109,4 +127,27 @@ void GlStageBuffer::unbind()
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
|
||||||
mGpuBuffer->unbind(GlGpuBuffer::Target::ELEMENT_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,
|
ARRAY_BUFFER = GL_ARRAY_BUFFER,
|
||||||
ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER,
|
ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
UNIFORM_BUFFER = GL_UNIFORM_BUFFER,
|
||||||
};
|
};
|
||||||
|
|
||||||
GlGpuBuffer();
|
GlGpuBuffer();
|
||||||
|
@ -41,6 +42,8 @@ public:
|
||||||
void updateBufferData(Target target, uint32_t size, const void* data);
|
void updateBufferData(Target target, uint32_t size, const void* data);
|
||||||
void bind(Target target);
|
void bind(Target target);
|
||||||
void unbind(Target target);
|
void unbind(Target target);
|
||||||
|
|
||||||
|
uint32_t getBufferId() { return mGlBufferId; }
|
||||||
private:
|
private:
|
||||||
uint32_t mGlBufferId = 0;
|
uint32_t mGlBufferId = 0;
|
||||||
|
|
||||||
|
@ -48,10 +51,10 @@ private:
|
||||||
|
|
||||||
class GlStageBuffer {
|
class GlStageBuffer {
|
||||||
public:
|
public:
|
||||||
GlStageBuffer() = default;
|
GlStageBuffer();
|
||||||
~GlStageBuffer();
|
~GlStageBuffer();
|
||||||
|
|
||||||
uint32_t push(void* data, uint32_t size);
|
uint32_t push(void* data, uint32_t size, bool alignGpuOffset = false);
|
||||||
|
|
||||||
void flushToGPU();
|
void flushToGPU();
|
||||||
|
|
||||||
|
@ -59,6 +62,9 @@ public:
|
||||||
|
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
||||||
|
GLuint getBufferId();
|
||||||
|
private:
|
||||||
|
void alignOffset();
|
||||||
private:
|
private:
|
||||||
GLuint mVao = 0;
|
GLuint mVao = 0;
|
||||||
unique_ptr<GlGpuBuffer> mGpuBuffer = {};
|
unique_ptr<GlGpuBuffer> mGpuBuffer = {};
|
||||||
|
|
|
@ -87,6 +87,16 @@ int32_t GlProgram::getUniformLocation(const char* name)
|
||||||
return location;
|
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)
|
void GlProgram::setUniform1Value(int32_t location, int count, const int* values)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#ifndef _TVG_GL_PROGRAM_H_
|
#ifndef _TVG_GL_PROGRAM_H_
|
||||||
#define _TVG_GL_PROGRAM_H_
|
#define _TVG_GL_PROGRAM_H_
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "tvgGlShader.h"
|
#include "tvgGlShader.h"
|
||||||
|
|
||||||
class GlProgram
|
class GlProgram
|
||||||
|
@ -37,6 +36,8 @@ public:
|
||||||
static void unload();
|
static void unload();
|
||||||
int32_t getAttributeLocation(const char* name);
|
int32_t getAttributeLocation(const char* name);
|
||||||
int32_t getUniformLocation(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 setUniform1Value(int32_t location, int count, const int* values);
|
||||||
void setUniform2Value(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 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 "tvgGlRenderTask.h"
|
||||||
#include "tvgGlShaderSrc.h"
|
#include "tvgGlProgram.h"
|
||||||
#include "tvgGlPropertyInterface.h"
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr<GlShader> shader)
|
void GlRenderTask::run()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
|
// bind shader
|
||||||
mProgram->load();
|
mProgram->load();
|
||||||
}
|
// setup attribute layout
|
||||||
|
for (uint32_t i = 0; i < mVertexLayout.count; i++) {
|
||||||
|
const auto &layout = mVertexLayout[i];
|
||||||
void GlRenderTask::unload()
|
GL_CHECK(glEnableVertexAttribArray(layout.index));
|
||||||
{
|
GL_CHECK(glVertexAttribPointer(layout.index, layout.size, GL_FLOAT,
|
||||||
GlProgram::unload();
|
GL_FALSE, layout.stride,
|
||||||
}
|
reinterpret_cast<void *>(layout.offset)));
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void GlRenderTask::uploadValues()
|
// binding uniforms
|
||||||
{
|
for (uint32_t i = 0; i < mBindingResources.count; i++) {
|
||||||
for (auto& property : mUniformPropertyBuffer)
|
const auto& binding = mBindingResources[i];
|
||||||
{
|
if (binding.type == GlBindingType::kTexture) {
|
||||||
PropertyValue& propertyVal = property.second.propertyValues;
|
GL_CHECK(glActiveTexture(GL_TEXTURE0 + binding.bindPoint));
|
||||||
switch (property.second.dataType) {
|
GL_CHECK(glBindTexture(GL_TEXTURE_2D, binding.gBufferId));
|
||||||
case VertexProperty::DataType::INT: {
|
|
||||||
switch (propertyVal.getStride()) {
|
mProgram->setUniform1Value(binding.location, 1, (int32_t*)&binding.bindPoint);
|
||||||
case 1:
|
} else if (binding.type == GlBindingType::kUniformBuffer) {
|
||||||
mProgram->setUniform1Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
|
||||||
break;
|
GL_CHECK(glUniformBlockBinding(mProgram->getProgramId(), binding.location, binding.bindPoint));
|
||||||
case 2:
|
GL_CHECK(glBindBufferRange(GL_UNIFORM_BUFFER, binding.bindPoint, binding.gBufferId,
|
||||||
mProgram->setUniform2Value(property.second.propertyId, propertyVal.getCount(), (const int*)propertyVal.getData());
|
binding.bufferOffset, binding.bufferRange));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
GL_CHECK(glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_INT, reinterpret_cast<void*>(mIndexOffset)));
|
||||||
|
|
||||||
std::shared_ptr<GlColorRenderTask> GlColorRenderTask::gen()
|
// setup attribute layout
|
||||||
{
|
for (uint32_t i = 0; i < mVertexLayout.count; i++) {
|
||||||
return std::make_shared<GlColorRenderTask>();
|
const auto &layout = mVertexLayout[i];
|
||||||
}
|
GL_CHECK(glDisableVertexAttribArray(layout.index));
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlRenderTask::addVertexLayout(const GlVertexLayout &layout)
|
||||||
GlGradientRenderTask::GlGradientRenderTask(GlRenderTask::RenderTypes renderType, std::shared_ptr<GlShader> shader)
|
|
||||||
:GlRenderTask(renderType, shader)
|
|
||||||
{
|
{
|
||||||
VertexProperty* prop = nullptr;
|
mVertexLayout.push(layout);
|
||||||
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 GlRenderTask::addBindResource(const GlBindingResource &binding)
|
||||||
void GlGradientRenderTask::setNoise(float noise)
|
|
||||||
{
|
{
|
||||||
if (mLocNoise != -1)
|
mBindingResources.push(binding);
|
||||||
{
|
|
||||||
PropertyInterface::setProperty(this, mLocNoise, noise);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlRenderTask::setDrawRange(uint32_t offset, uint32_t count)
|
||||||
void GlGradientRenderTask::setStopCount(int32_t count)
|
|
||||||
{
|
{
|
||||||
if (mLocStopCnt != -1)
|
mIndexOffset = offset;
|
||||||
{
|
mIndexCount = count;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,102 +23,72 @@
|
||||||
#ifndef _TVG_GL_RENDER_TASK_H_
|
#ifndef _TVG_GL_RENDER_TASK_H_
|
||||||
#define _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
|
class GlRenderTask
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum RenderTypes
|
GlRenderTask(GlProgram* program): mProgram(program) {}
|
||||||
{
|
~GlRenderTask() = default;
|
||||||
RT_Color = 0,
|
|
||||||
RT_LinGradient,
|
|
||||||
RT_RadGradient,
|
|
||||||
|
|
||||||
RT_None,
|
void run();
|
||||||
};
|
|
||||||
|
|
||||||
GlRenderTask(RenderTypes renderType, std::shared_ptr<GlShader> shader);
|
void addVertexLayout(const GlVertexLayout& layout);
|
||||||
RenderTypes getRenderType();
|
void addBindResource(const GlBindingResource& binding);
|
||||||
|
void setDrawRange(uint32_t offset, uint32_t count);
|
||||||
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();
|
|
||||||
|
|
||||||
|
GlProgram* getProgram() { return mProgram; }
|
||||||
private:
|
private:
|
||||||
RenderTypes mRenderType;
|
GlProgram* mProgram;
|
||||||
|
uint32_t mIndexOffset = {};
|
||||||
std::shared_ptr<GlProgram> mProgram;
|
uint32_t mIndexCount = {};
|
||||||
std::map<int32_t, VertexProperty> mAttributePropertyBuffer;
|
Array<GlVertexLayout> mVertexLayout = {};
|
||||||
std::map<int32_t, VertexProperty> mUniformPropertyBuffer;
|
Array<GlBindingResource> mBindingResources = {};
|
||||||
|
|
||||||
int32_t mLocVertexAttribute = -1;
|
|
||||||
int32_t mLocTransform = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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_ */
|
#endif /* _TVG_GL_RENDER_TASK_H_ */
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
#include "tvgGlRenderer.h"
|
#include "tvgGlRenderer.h"
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
#include "tvgGlGeometry.h"
|
#include "tvgGlGeometry.h"
|
||||||
#include "tvgGlPropertyInterface.h"
|
#include "tvgGlRenderTask.h"
|
||||||
|
#include "tvgGlProgram.h"
|
||||||
|
#include "tvgGlShaderSrc.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
|
@ -67,8 +69,22 @@ bool GlRenderer::target(TVG_UNUSED uint32_t* buffer, uint32_t stride, uint32_t w
|
||||||
|
|
||||||
bool GlRenderer::sync()
|
bool GlRenderer::sync()
|
||||||
{
|
{
|
||||||
GL_CHECK(glFinish());
|
mGpuBuffer->flushToGPU();
|
||||||
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));
|
||||||
|
|
||||||
|
mGpuBuffer->bind();
|
||||||
|
|
||||||
|
for(auto& task: mRenderTasks) {
|
||||||
|
task->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
mGpuBuffer->unbind();
|
||||||
|
|
||||||
|
mRenderTasks.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,19 +97,10 @@ RenderRegion GlRenderer::region(TVG_UNUSED RenderData data)
|
||||||
|
|
||||||
bool GlRenderer::preRender()
|
bool GlRenderer::preRender()
|
||||||
{
|
{
|
||||||
if (mRenderTasks.size() == 0)
|
if (mPrograms.size() == 0)
|
||||||
{
|
{
|
||||||
initShaders();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -101,8 +108,6 @@ bool GlRenderer::preRender()
|
||||||
|
|
||||||
bool GlRenderer::postRender()
|
bool GlRenderer::postRender()
|
||||||
{
|
{
|
||||||
mGpuBuffer->unbind();
|
|
||||||
|
|
||||||
return true;
|
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->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;
|
return sdata;
|
||||||
}
|
}
|
||||||
|
@ -295,6 +300,9 @@ GlRenderer* GlRenderer::gen()
|
||||||
return new GlRenderer();
|
return new GlRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GlRenderer::GlRenderer() :mGpuBuffer(new GlStageBuffer), mPrograms(), mRenderTasks()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GlRenderer::~GlRenderer()
|
GlRenderer::~GlRenderer()
|
||||||
{
|
{
|
||||||
|
@ -309,30 +317,51 @@ GlRenderer::~GlRenderer()
|
||||||
void GlRenderer::initShaders()
|
void GlRenderer::initShaders()
|
||||||
{
|
{
|
||||||
// Solid Color Renderer
|
// 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
|
// 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
|
// 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)
|
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());
|
auto task = make_unique<GlRenderTask>(mPrograms[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);
|
|
||||||
|
|
||||||
|
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);
|
auto stopCnt = fill->colorStops(&stops);
|
||||||
if (stopCnt < 2) return;
|
if (stopCnt < 2) return;
|
||||||
|
|
||||||
GlGradientRenderTask* rTask = nullptr;
|
unique_ptr<GlRenderTask> task;
|
||||||
auto matrix = sdata.geometry->getTransforMatrix();
|
|
||||||
|
|
||||||
switch (fill->identifier()) {
|
if (fill->identifier() == TVG_CLASS_ID_LINEAR) {
|
||||||
case TVG_CLASS_ID_LINEAR: {
|
task = make_unique<GlRenderTask>(mPrograms[RT_LinGradient].get());
|
||||||
float x1, y1, x2, y2;
|
} else if (fill->identifier() == TVG_CLASS_ID_RADIAL) {
|
||||||
GlLinearGradientRenderTask *renderTask = static_cast<GlLinearGradientRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_LinGradient].get());
|
task = make_unique<GlRenderTask>(mPrograms[RT_RadGradient].get());
|
||||||
assert(renderTask);
|
} else {
|
||||||
rTask = renderTask;
|
return;
|
||||||
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 (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) {
|
if (!sdata.geometry->draw(task.get(), mGpuBuffer.get(), flag)) return;
|
||||||
rTask->setStopColor(i, stops[i].offset, stops[i].r, stops[i].g, stops[i].b, stops[i].a);
|
|
||||||
|
// 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();
|
task->addBindResource(gradientBinding);
|
||||||
sdata.geometry->draw(vertexLoc, flag);
|
|
||||||
sdata.geometry->disableVertex(vertexLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mRenderTasks.emplace_back(std::move(task));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,23 @@
|
||||||
#ifndef _TVG_GL_RENDERER_H_
|
#ifndef _TVG_GL_RENDERER_H_
|
||||||
#define _TVG_GL_RENDERER_H_
|
#define _TVG_GL_RENDERER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "tvgGlRenderTask.h"
|
#include "tvgGlRenderTask.h"
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlGpuBuffer.h"
|
||||||
|
|
||||||
class GlRenderer : public RenderMethod
|
class GlRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum RenderTypes
|
||||||
|
{
|
||||||
|
RT_Color = 0,
|
||||||
|
RT_LinGradient,
|
||||||
|
RT_RadGradient,
|
||||||
|
|
||||||
|
RT_None,
|
||||||
|
};
|
||||||
|
|
||||||
Surface surface = {nullptr, 0, 0, 0, ColorSpace::Unsupported, true};
|
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;
|
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();
|
static int term();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GlRenderer(): mGpuBuffer(new GlStageBuffer) {};
|
GlRenderer();
|
||||||
~GlRenderer();
|
~GlRenderer();
|
||||||
|
|
||||||
void initShaders();
|
void initShaders();
|
||||||
void drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b, uint8_t a, RenderUpdateFlag flag);
|
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);
|
void drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag);
|
||||||
|
|
||||||
vector<shared_ptr<GlRenderTask>> mRenderTasks;
|
|
||||||
std::unique_ptr<GlStageBuffer> mGpuBuffer;
|
std::unique_ptr<GlStageBuffer> mGpuBuffer;
|
||||||
|
vector<std::unique_ptr<GlProgram>> mPrograms;
|
||||||
|
vector<std::unique_ptr<GlRenderTask>> mRenderTasks;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _TVG_GL_RENDERER_H_ */
|
#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(
|
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
|
||||||
layout(location = 0) in vec3 aLocation; \n
|
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
|
out float vOpacity; \n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \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
|
vOpacity = aLocation.z; \n
|
||||||
});
|
});
|
||||||
|
|
||||||
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
|
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
|
in float vOpacity; \n
|
||||||
out vec4 FragColor; \n
|
out vec4 FragColor; \n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
|
vec4 uColor = uColorInfo.solidColor; \n
|
||||||
FragColor = vec4(uColor.xyz, uColor.w*vOpacity); \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
|
layout(location = 0) in vec3 aLocation; \n
|
||||||
out float vOpacity; \n
|
out float vOpacity; \n
|
||||||
out vec2 vPos; \n
|
out vec2 vPos; \n
|
||||||
uniform mat4 uTransform; \n
|
layout(std140) uniform Matrix { \n
|
||||||
|
mat4 transform; \n
|
||||||
|
} uMatrix; \n
|
||||||
\n
|
\n
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \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
|
vOpacity = aLocation.z; \n
|
||||||
vPos = aLocation.xy; \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
|
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 vec2 vPos; \n
|
||||||
in float vOpacity; \n
|
in float vOpacity; \n
|
||||||
);
|
);
|
||||||
|
@ -80,23 +84,26 @@ vec4 gradient(float t)
|
||||||
{ \n
|
{ \n
|
||||||
vec4 col = vec4(0.0); \n
|
vec4 col = vec4(0.0); \n
|
||||||
int i = 0; \n
|
int i = 0; \n
|
||||||
int count = int(nStops); \n
|
int count = int(uGradientInfo.nStops[0]); \n
|
||||||
if (t <= stopPoints[0]) \n
|
if (t <= uGradientInfo.stopPoints[0]) \n
|
||||||
{ \n
|
{ \n
|
||||||
col += stopColors[0]; \n
|
col += uGradientInfo.stopColors[0]; \n
|
||||||
} \n
|
} \n
|
||||||
else if (t >= stopPoints[count - 1]) \n
|
else if (t >= uGradientInfo.stopPoints[count - 1]) \n
|
||||||
{ \n
|
{ \n
|
||||||
col += stopColors[count - 1]; \n
|
col += uGradientInfo.stopColors[count - 1]; \n
|
||||||
} \n
|
} \n
|
||||||
else \n
|
else \n
|
||||||
{ \n
|
{ \n
|
||||||
for (i = 0; i < count - 1; ++i) \n
|
for (i = 0; i < count - 1; ++i) \n
|
||||||
{ \n
|
{ \n
|
||||||
if (t > stopPoints[i] && t < stopPoints[i + 1]) \n
|
if (t > uGradientInfo.stopPoints[i] && t < uGradientInfo.stopPoints[i + 1]) \n
|
||||||
{ \n
|
{ \n
|
||||||
col += (stopColors[i] * (1. - gradientStep(stopPoints[i], stopPoints[i + 1], t))); \n
|
col += (uGradientInfo.stopColors[i] * \n
|
||||||
col += (stopColors[i + 1] * gradientStep(stopPoints[i], stopPoints[i + 1], t)); \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
|
break; \n
|
||||||
} \n
|
} \n
|
||||||
} \n
|
} \n
|
||||||
|
@ -113,8 +120,13 @@ vec3 ScreenSpaceDither(vec2 vScreenPos)
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string STR_LINEAR_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
std::string STR_LINEAR_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||||
uniform vec2 gradStartPos; \n
|
layout(std140) uniform GradientInfo { \n
|
||||||
uniform vec2 gradEndPos; \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(
|
std::string STR_LINEAR_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||||
|
@ -122,8 +134,8 @@ out vec4 FragColor;
|
||||||
void main() \n
|
void main() \n
|
||||||
{ \n
|
{ \n
|
||||||
vec2 pos = vPos; \n
|
vec2 pos = vPos; \n
|
||||||
vec2 st = gradStartPos; \n
|
vec2 st = uGradientInfo.gradStartPos; \n
|
||||||
vec2 ed = gradEndPos; \n
|
vec2 ed = uGradientInfo.gradEndPos; \n
|
||||||
\n
|
\n
|
||||||
vec2 ba = ed - st; \n
|
vec2 ba = ed - st; \n
|
||||||
\n
|
\n
|
||||||
|
@ -134,14 +146,19 @@ void main()
|
||||||
\n
|
\n
|
||||||
vec4 color = gradient(t); \n
|
vec4 color = gradient(t); \n
|
||||||
\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
|
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||||
FragColor = vec4(finalCol.xyz, finalCol.w* vOpacity); \n
|
FragColor = vec4(finalCol.xyz, finalCol.w* vOpacity); \n
|
||||||
});
|
});
|
||||||
|
|
||||||
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
std::string STR_RADIAL_GRADIENT_VARIABLES = TVG_COMPOSE_SHADER(
|
||||||
uniform vec2 gradStartPos; \n
|
layout(std140) uniform GradientInfo { \n
|
||||||
uniform float stRadius; \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(
|
std::string STR_RADIAL_GRADIENT_MAIN = TVG_COMPOSE_SHADER(
|
||||||
|
@ -150,8 +167,8 @@ void main()
|
||||||
{ \n
|
{ \n
|
||||||
vec2 pos = vPos; \n
|
vec2 pos = vPos; \n
|
||||||
\n
|
\n
|
||||||
float ba = stRadius; \n
|
float ba = uGradientInfo.radius.x; \n
|
||||||
float d = distance(gradStartPos, pos); \n
|
float d = distance(uGradientInfo.centerPos, pos); \n
|
||||||
d = (d / ba); \n
|
d = (d / ba); \n
|
||||||
\n
|
\n
|
||||||
//float t = smoothstep(0.0, 1.0, clamp(d, 0.0, 1.0)); \n
|
//float t = smoothstep(0.0, 1.0, clamp(d, 0.0, 1.0)); \n
|
||||||
|
@ -159,7 +176,7 @@ void main()
|
||||||
\n
|
\n
|
||||||
vec4 color = gradient(t); \n
|
vec4 color = gradient(t); \n
|
||||||
\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
|
vec4 finalCol = vec4(color.xyz + noise, color.w); \n
|
||||||
FragColor = vec4(finalCol.xyz, finalCol.w * vOpacity); \n
|
FragColor = vec4(finalCol.xyz, finalCol.w * vOpacity); \n
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue