Adding solid color and gradient support.
diff --git a/include/math/mat2d.hpp b/include/math/mat2d.hpp index 81920eb..20b5bd3 100644 --- a/include/math/mat2d.hpp +++ b/include/math/mat2d.hpp
@@ -32,6 +32,8 @@ result[5] = 0.0f; } + static const Mat2D& identity(); + static void fromRotation(Mat2D& result, float rad); static void scale(Mat2D& result, const Mat2D& mat, const Vec2D& vec); static void multiply(Mat2D& result, const Mat2D& a, const Mat2D& b);
diff --git a/renderer/library/include/opengl/opengl_render_paint.hpp b/renderer/library/include/opengl/opengl_render_paint.hpp index 0540de4..1d017e4 100644 --- a/renderer/library/include/opengl/opengl_render_paint.hpp +++ b/renderer/library/include/opengl/opengl_render_paint.hpp
@@ -2,13 +2,38 @@ #define _RIVE_OPENGL_RENDER_PAINT_HPP_ #include "renderer.hpp" +#include <vector> namespace rive { + class OpenGLRenderer; + class OpenGLRenderPaint; + class OpenGLRenderPath; + + class OpenGLGradient + { + friend class OpenGLRenderPaint; + + private: + float m_Position[4]; + int m_Type = 0; + std::vector<float> m_Colors; + std::vector<float> m_Stops; + bool m_IsVisible = false; + + public: + OpenGLGradient(int type); + void position(float sx, float sy, float ex, float ey); + void addStop(unsigned int color, float stop); + void bind(OpenGLRenderer* renderer); + }; + class OpenGLRenderPaint : public RenderPaint { private: RenderPaintStyle m_PaintStyle; + float m_Color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + OpenGLGradient* m_Gradient = nullptr; public: void style(RenderPaintStyle style) override; @@ -24,6 +49,11 @@ void addStop(unsigned int color, float stop) override; void completeGradient() override; ~OpenGLRenderPaint(); + + bool doesDraw() const; + void draw(OpenGLRenderer* renderer, + const Mat2D& transform, + OpenGLRenderPath* path); }; } // namespace rive #endif \ No newline at end of file
diff --git a/renderer/library/include/opengl/opengl_render_path.hpp b/renderer/library/include/opengl/opengl_render_path.hpp index 050a214..afd968f 100644 --- a/renderer/library/include/opengl/opengl_render_path.hpp +++ b/renderer/library/include/opengl/opengl_render_path.hpp
@@ -3,6 +3,7 @@ #include "contour_render_path.hpp" #include "opengl.h" +#include "math/mat2d.hpp" namespace rive { @@ -20,7 +21,9 @@ FillRule fillRule() const { return m_FillRule; } void stencil(OpenGLRenderer* renderer, const Mat2D& transform); - void cover(OpenGLRenderer* renderer, const Mat2D& transform); + void cover(OpenGLRenderer* renderer, + const Mat2D& transform, + const Mat2D& localTransform = Mat2D::identity()); }; } // namespace rive #endif \ No newline at end of file
diff --git a/renderer/library/include/opengl/opengl_renderer.hpp b/renderer/library/include/opengl/opengl_renderer.hpp index 4f389bd..149c0fc 100644 --- a/renderer/library/include/opengl/opengl_renderer.hpp +++ b/renderer/library/include/opengl/opengl_renderer.hpp
@@ -17,6 +17,13 @@ GLuint m_IndexBuffer = 0; GLint m_ProjectionUniformIndex = -1; GLint m_TransformUniformIndex = -1; + GLint m_FillTypeUniformIndex = -1; + GLint m_StopCountUniformIndex = -1; + GLint m_StopColorsUniformIndex = -1; + GLint m_ColorUniformIndex = -1; + GLint m_StopsUniformIndex = -1; + GLint m_GradientPositionUniformIndex = -1; + GLint m_ShapeTransformUniformIndex = -1; GLuint m_VertexArray = 0; /// Indices for the max sized contour, prepended with 2 triangles for @@ -42,6 +49,24 @@ void updateIndexBuffer(std::size_t contourLength); GLint transformUniformIndex() const { return m_TransformUniformIndex; } + + GLint fillTypeUniformIndex() const { return m_FillTypeUniformIndex; } + GLint stopCountUniformIndex() const { return m_StopCountUniformIndex; } + GLint stopColorsUniformIndex() const + { + return m_StopColorsUniformIndex; + } + GLint colorUniformIndex() const { return m_ColorUniformIndex; } + GLint stopsUniformIndex() const { return m_StopsUniformIndex; } + GLint shapeTransformUniformIndex() const + { + return m_ShapeTransformUniformIndex; + } + GLint gradientPositionUniformIndex() const + { + return m_GradientPositionUniformIndex; + } + GLuint program() const { return m_Program; } virtual const char* shaderHeader() const { return nullptr; }; };
diff --git a/renderer/library/src/opengl/opengl_render_paint.cpp b/renderer/library/src/opengl/opengl_render_paint.cpp index 9a21daa..f4d3260 100644 --- a/renderer/library/src/opengl/opengl_render_paint.cpp +++ b/renderer/library/src/opengl/opengl_render_paint.cpp
@@ -1,9 +1,24 @@ #include "opengl/opengl_render_paint.hpp" +#include "shapes/paint/color.hpp" +#include "opengl/opengl_renderer.hpp" +#include "opengl/opengl_render_path.hpp" + using namespace rive; +void fillColorBuffer(float* buffer, unsigned int value) +{ + buffer[0] = colorRed(value) / 255.0f; + buffer[1] = colorGreen(value) / 255.0f; + buffer[2] = colorBlue(value) / 255.0f; + buffer[3] = colorAlpha(value) / 255.0f; +} + void OpenGLRenderPaint::style(RenderPaintStyle style) { m_PaintStyle = style; } -void OpenGLRenderPaint::color(unsigned int value) {} +void OpenGLRenderPaint::color(unsigned int value) +{ + fillColorBuffer(m_Color, value); +} void OpenGLRenderPaint::thickness(float value) {} @@ -15,14 +30,88 @@ void OpenGLRenderPaint::linearGradient(float sx, float sy, float ex, float ey) { + if (m_Gradient == nullptr) + { + m_Gradient = new OpenGLGradient(1); + } + m_Gradient->position(sx, sy, ex, ey); } void OpenGLRenderPaint::radialGradient(float sx, float sy, float ex, float ey) { + if (m_Gradient == nullptr) + { + m_Gradient = new OpenGLGradient(2); + } + m_Gradient->position(sx, sy, ex, ey); } -void OpenGLRenderPaint::addStop(unsigned int color, float stop) {} +void OpenGLRenderPaint::addStop(unsigned int color, float stop) +{ + m_Gradient->addStop(color, stop); +} void OpenGLRenderPaint::completeGradient() {} -OpenGLRenderPaint::~OpenGLRenderPaint() {} \ No newline at end of file +OpenGLRenderPaint::~OpenGLRenderPaint() { delete m_Gradient; } + +bool OpenGLRenderPaint::doesDraw() const +{ + return true; + return m_Color[3] > 0.0f && + (m_Gradient == nullptr || m_Gradient->m_IsVisible); +} + +void OpenGLRenderPaint::draw(OpenGLRenderer* renderer, + const Mat2D& transform, + OpenGLRenderPath* path) +{ + uint32_t type = 0; + if (m_Gradient != nullptr) + { + type = m_Gradient->m_Type; + m_Gradient->bind(renderer); + } + + glUniform1i(renderer->fillTypeUniformIndex(), type); + glUniform4fv(renderer->colorUniformIndex(), 1, m_Color); + + path->cover(renderer, transform); +} + +OpenGLGradient::OpenGLGradient(int type) : m_Type(type) {} + +void OpenGLGradient::position(float sx, float sy, float ex, float ey) +{ + m_Colors.clear(); + m_Stops.clear(); + m_IsVisible = false; + m_Position[0] = sx; + m_Position[1] = sy; + m_Position[2] = ex; + m_Position[3] = ey; +} + +void OpenGLGradient::bind(OpenGLRenderer* renderer) +{ + auto numberOfStops = m_Stops.size(); + + glUniform1i(renderer->stopCountUniformIndex(), numberOfStops); + glUniform4fv( + renderer->stopColorsUniformIndex(), numberOfStops, &m_Colors[0]); + glUniform1fv(renderer->stopsUniformIndex(), numberOfStops, &m_Stops[0]); + glUniform4fv(renderer->gradientPositionUniformIndex(), 1, &m_Position[0]); +} + +void OpenGLGradient::addStop(unsigned int color, float stop) +{ + auto index = m_Colors.size(); + m_Colors.resize(index + 4); + + fillColorBuffer(&m_Colors[index], color); + if (m_Colors[index + 3] > 0.0f) + { + m_IsVisible = true; + } + m_Stops.push_back(stop); +} \ No newline at end of file
diff --git a/renderer/library/src/opengl/opengl_render_path.cpp b/renderer/library/src/opengl/opengl_render_path.cpp index 611cb40..1c13c01 100644 --- a/renderer/library/src/opengl/opengl_render_path.cpp +++ b/renderer/library/src/opengl/opengl_render_path.cpp
@@ -15,10 +15,10 @@ { for (auto& subPath : m_SubPaths) { - Mat2D subPathTransform; - Mat2D::multiply(subPathTransform, transform, subPath.transform()); + Mat2D pathTransform; + Mat2D::multiply(pathTransform, transform, subPath.transform()); reinterpret_cast<OpenGLRenderPath*>(subPath.path()) - ->stencil(renderer, subPathTransform); + ->stencil(renderer, pathTransform); } return; } @@ -108,16 +108,19 @@ // glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &indices[0]); } -void OpenGLRenderPath::cover(OpenGLRenderer* renderer, const Mat2D& transform) +void OpenGLRenderPath::cover(OpenGLRenderer* renderer, + const Mat2D& transform, + const Mat2D& localTransform) { if (isContainer()) { for (auto& subPath : m_SubPaths) { - Mat2D subPathTransform; - Mat2D::multiply(subPathTransform, transform, subPath.transform()); + const Mat2D& subPathTransform = subPath.transform(); + Mat2D pathTransform; + Mat2D::multiply(pathTransform, transform, subPathTransform); reinterpret_cast<OpenGLRenderPath*>(subPath.path()) - ->stencil(renderer, subPathTransform); + ->cover(renderer, pathTransform, subPathTransform); } return; } @@ -130,26 +133,47 @@ return; } - auto triangleCount = vertexCount - 5; + { + float m4[16] = {transform[0], + transform[1], + 0.0, + 0.0, + transform[2], + transform[3], + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + transform[4], + transform[5], + 0.0, + 1.0}; - float m4[16] = {transform[0], - transform[1], - 0.0, - 0.0, - transform[2], - transform[3], - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 0.0, - transform[4], - transform[5], - 0.0, - 1.0}; + glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4); + } + { + float m4[16] = {localTransform[0], + localTransform[1], + 0.0, + 0.0, + localTransform[2], + localTransform[3], + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + localTransform[4], + localTransform[5], + 0.0, + 1.0}; - glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4); + glUniformMatrix4fv( + renderer->shapeTransformUniformIndex(), 1, GL_FALSE, m4); + } glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * 4, (void*)0);
diff --git a/renderer/library/src/opengl/opengl_renderer.cpp b/renderer/library/src/opengl/opengl_renderer.cpp index fa0f741..30f0e08 100644 --- a/renderer/library/src/opengl/opengl_renderer.cpp +++ b/renderer/library/src/opengl/opengl_renderer.cpp
@@ -78,6 +78,16 @@ m_ProjectionUniformIndex = glGetUniformLocation(m_Program, "projection"); m_TransformUniformIndex = glGetUniformLocation(m_Program, "transform"); + m_FillTypeUniformIndex = glGetUniformLocation(m_Program, "fillType"); + m_StopCountUniformIndex = glGetUniformLocation(m_Program, "count"); + m_StopColorsUniformIndex = glGetUniformLocation(m_Program, "colors"); + m_StopsUniformIndex = glGetUniformLocation(m_Program, "stops"); + m_ColorUniformIndex = glGetUniformLocation(m_Program, "color"); + m_GradientPositionUniformIndex = + glGetUniformLocation(m_Program, "position"); + m_ShapeTransformUniformIndex = + glGetUniformLocation(m_Program, "localTransform"); + float projection[16] = {0.0f}; orthographicProjection(projection, 0.0f, 800, 800, 0.0f, 0.0f, 1.0f); modelViewProjection(projection); @@ -88,7 +98,7 @@ void OpenGLRenderer::drawPath(RenderPath* path, RenderPaint* paint) { auto glPaint = static_cast<OpenGLRenderPaint*>(paint); - if (glPaint->style() == RenderPaintStyle::stroke) + if (glPaint->style() == RenderPaintStyle::stroke || !glPaint->doesDraw()) { return; } @@ -108,7 +118,8 @@ glStencilFunc(GL_NOTEQUAL, 0, 0xFF); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - glPath->cover(this, transform()); + glPaint->draw(this, transform(), glPath); + // glPath->cover(this, transform()); } void OpenGLRenderer::clipPath(RenderPath* path) {}
diff --git a/renderer/library/src/opengl/opengl_shaders.cpp b/renderer/library/src/opengl/opengl_shaders.cpp index 8ada16f..9da09c9 100644 --- a/renderer/library/src/opengl/opengl_shaders.cpp +++ b/renderer/library/src/opengl/opengl_shaders.cpp
@@ -10,7 +10,7 @@ uniform mat4 transform; uniform mat4 localTransform; -void main(void) +void main() { gl_Position = projection*transform*vec4(position, 0.0, 1.0); pos = (localTransform*vec4(position, 0.0, 1.0)).xy; @@ -25,8 +25,7 @@ #endif uniform vec4 color; -uniform vec2 start; -uniform vec2 end; +uniform vec4 position; uniform int count; uniform vec4 colors[16]; uniform float stops[16]; @@ -36,52 +35,59 @@ void main() { - fragColor = vec4(0.0, 0.0, 0.0, 0.35); + if (fillType == 0) + { + // solid + fragColor = color;//vec4(color.rgb * color.a, color.a); + } + else if (fillType == 1) + { + // linear - // if (fillType == 0) - // { - // // solid - // gl_FragColor = vec4(color.rgb * color.a, color.a); - // } - // else if (fillType == 1) - // { - // // linear - // vec2 toEnd = end - start; - // float lengthSquared = toEnd.x * toEnd.x + toEnd.y * toEnd.y; - // float f = dot(pos - start, toEnd) / lengthSquared; - // gl_FragColor = - // mix(colors[0], colors[1], smoothstep(stops[0], stops[1], f)); - // for (int i = 1; i < 15; ++i) - // { - // if (i >= count - 1) - // { - // break; - // } - // gl_FragColor = mix(gl_FragColor, - // colors[i + 1], - // smoothstep(stops[i], stops[i + 1], f)); - // } - // float alpha = gl_FragColor.w; - // gl_FragColor = vec4(gl_FragColor.xyz * alpha, alpha); - // } - // else if (fillType == 2) - // { - // // radial - // float f = distance(start, pos) / distance(start, end); - // gl_FragColor = - // mix(colors[0], colors[1], smoothstep(stops[0], stops[1], f)); - // for (int i = 1; i < 15; ++i) - // { - // if (i >= count - 1) - // { - // break; - // } - // gl_FragColor = mix(gl_FragColor, - // colors[i + 1], - // smoothstep(stops[i], stops[i + 1], f)); - // } - // float alpha = gl_FragColor.w; - // gl_FragColor = vec4(gl_FragColor.xyz * alpha, alpha); - // } + vec2 start = position.xy; + vec2 end = position.zw; + + + vec2 toEnd = end - start; + float lengthSquared = toEnd.x * toEnd.x + toEnd.y * toEnd.y; + float f = dot(pos - start, toEnd) / lengthSquared; + fragColor = + mix(colors[0], colors[1], smoothstep(stops[0], stops[1], f)); + for (int i = 1; i < 15; ++i) + { + if (i >= count - 1) + { + break; + } + fragColor = mix(fragColor, + colors[i + 1], + smoothstep(stops[i], stops[i + 1], f)); + } + // float alpha = fragColor.w; + // fragColor = vec4(fragColor.xyz * alpha, alpha); + } + else if (fillType == 2) + { + // radial + + vec2 start = position.xy; + vec2 end = position.zw; + + float f = distance(start, pos) / distance(start, end); + fragColor = + mix(colors[0], colors[1], smoothstep(stops[0], stops[1], f)); + for (int i = 1; i < 15; ++i) + { + if (i >= count - 1) + { + break; + } + fragColor = mix(fragColor, + colors[i + 1], + smoothstep(stops[i], stops[i + 1], f)); + } + // float alpha = fragColor.w; + // fragColor = vec4(fragColor.xyz * alpha, alpha); + } } )"""; \ No newline at end of file
diff --git a/renderer/viewer/assets/car.riv b/renderer/viewer/assets/car.riv new file mode 100644 index 0000000..81202cb --- /dev/null +++ b/renderer/viewer/assets/car.riv Binary files differ
diff --git a/renderer/viewer/assets/gradient.riv b/renderer/viewer/assets/gradient.riv new file mode 100644 index 0000000..3e022a0 --- /dev/null +++ b/renderer/viewer/assets/gradient.riv Binary files differ
diff --git a/renderer/viewer/assets/juice.riv b/renderer/viewer/assets/juice.riv new file mode 100644 index 0000000..5df55e4 --- /dev/null +++ b/renderer/viewer/assets/juice.riv Binary files differ
diff --git a/renderer/viewer/src/viewer.cpp b/renderer/viewer/src/viewer.cpp index 79b3112..86dca8d 100644 --- a/renderer/viewer/src/viewer.cpp +++ b/renderer/viewer/src/viewer.cpp
@@ -105,8 +105,9 @@ uint8_t* fileBytes = nullptr; unsigned int fileBytesLength = 0; - std::string filename = "assets/polygon_party.riv"; + // std::string filename = "assets/polygon_party.riv"; // std::string filename = "assets/triangle.riv"; + std::string filename = "assets/juice.riv"; FILE* fp = fopen(filename.c_str(), "r"); fseek(fp, 0, SEEK_END); fileBytesLength = ftell(fp);
diff --git a/src/math/mat2d.cpp b/src/math/mat2d.cpp index bb6bf64..b8bd10d 100644 --- a/src/math/mat2d.cpp +++ b/src/math/mat2d.cpp
@@ -7,7 +7,10 @@ Mat2D::Mat2D() : m_Buffer{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f} {} -Mat2D::Mat2D(const Mat2D& copy) : m_Buffer{copy[0], copy[1], copy[2], copy[3], copy[4], copy[5]} {} +Mat2D::Mat2D(const Mat2D& copy) : + m_Buffer{copy[0], copy[1], copy[2], copy[3], copy[4], copy[5]} +{ +} void Mat2D::fromRotation(Mat2D& result, float rad) { @@ -34,8 +37,8 @@ void Mat2D::multiply(Mat2D& result, const Mat2D& a, const Mat2D& b) { - float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], - b5 = b[5]; + float a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4], a5 = a[5], + b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5]; result[0] = a0 * b0 + a2 * b1; result[1] = a1 * b0 + a3 * b1; result[2] = a0 * b2 + a2 * b3; @@ -124,4 +127,7 @@ result[1] *= sx; result[2] *= sy; result[3] *= sy; -} \ No newline at end of file +} + +static Mat2D s_Transform; +const Mat2D& Mat2D::identity() { return s_Transform; } \ No newline at end of file