Getting GL rendering to work.
diff --git a/.gitignore b/.gitignore index 7e9ac38..b1c96d3 100644 --- a/.gitignore +++ b/.gitignore
@@ -73,3 +73,4 @@ /skia/viewer/imgui.ini /diligent/viewer/build/bin/debug/rive_diligent_viewer /build/obj +/renderer/viewer/build/bin/debug/rive_low_level_viewer
diff --git a/include/math/mat2d.hpp b/include/math/mat2d.hpp index cf6db22..81920eb 100644 --- a/include/math/mat2d.hpp +++ b/include/math/mat2d.hpp
@@ -2,6 +2,7 @@ #define _RIVE_MAT2D_HPP_ #include <cstddef> +#include <stdio.h> namespace rive { @@ -47,6 +48,13 @@ float yy() const { return m_Buffer[3]; } float tx() const { return m_Buffer[4]; } float ty() const { return m_Buffer[5]; } + + void print() const + { + printf("X: %f %f\n", m_Buffer[0], m_Buffer[1]); + printf("Y: %f %f\n", m_Buffer[2], m_Buffer[3]); + printf("T: %f %f\n", m_Buffer[4], m_Buffer[5]); + } }; inline Mat2D operator*(const Mat2D& a, const Mat2D& b) @@ -61,5 +69,6 @@ return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3] && a[4] == b[4] && a[5] == b[5]; } + } // namespace rive #endif \ No newline at end of file
diff --git a/renderer/library/include/low_level/low_level_renderer.hpp b/renderer/library/include/low_level/low_level_renderer.hpp index 0d339de..6f5dbfb 100644 --- a/renderer/library/include/low_level/low_level_renderer.hpp +++ b/renderer/library/include/low_level/low_level_renderer.hpp
@@ -27,7 +27,7 @@ /// OpenGL, Vulkan, D3D, etc. class LowLevelRenderer : public Renderer { - private: + protected: float m_ModelViewProjection[16] = {0.0f}; std::list<RenderState> m_Stack;
diff --git a/renderer/library/include/opengl/opengl.h b/renderer/library/include/opengl/opengl.h index 79a1327..629bc12 100644 --- a/renderer/library/include/opengl/opengl.h +++ b/renderer/library/include/opengl/opengl.h
@@ -8,7 +8,7 @@ #include <OpenGLES/ES2/gl.h> #include <OpenGLES/ES2/glext.h> #else -#include <OpenGL/gl.h> +#include <OpenGL/gl3.h> #include <OpenGL/glu.h> #include <OpenGL/glext.h> #endif
diff --git a/renderer/library/include/opengl/opengl_render_path.hpp b/renderer/library/include/opengl/opengl_render_path.hpp index 0ceb001..c704fce 100644 --- a/renderer/library/include/opengl/opengl_render_path.hpp +++ b/renderer/library/include/opengl/opengl_render_path.hpp
@@ -2,6 +2,7 @@ #define _RIVE_OPENGL_RENDER_PATH_HPP_ #include "contour_render_path.hpp" +#include "opengl.h" namespace rive {
diff --git a/renderer/library/include/opengl/opengl_renderer.hpp b/renderer/library/include/opengl/opengl_renderer.hpp index 3f16727..2304d3d 100644 --- a/renderer/library/include/opengl/opengl_renderer.hpp +++ b/renderer/library/include/opengl/opengl_renderer.hpp
@@ -15,6 +15,8 @@ GLuint m_VertexShader = 0, m_FragmentShader = 0; GLuint m_Program = 0; GLuint m_IndexBuffer = 0; + GLint m_ProjectionUniformIndex = -1; + GLint m_TransformUniformIndex = -1; std::vector<unsigned short> m_Indices; public: @@ -34,6 +36,10 @@ bool initialize(void* data) override; void updateIndexBuffer(std::size_t contourLength); + + GLint transformUniformIndex() const { return m_TransformUniformIndex; } + GLuint program() const { return m_Program; } + virtual const char* shaderHeader() const { return nullptr; }; }; } // namespace rive
diff --git a/renderer/library/src/low_level_renderer/low_level_renderer.cpp b/renderer/library/src/low_level_renderer/low_level_renderer.cpp index 9783827..fdfad07 100644 --- a/renderer/library/src/low_level_renderer/low_level_renderer.cpp +++ b/renderer/library/src/low_level_renderer/low_level_renderer.cpp
@@ -49,6 +49,7 @@ void LowLevelRenderer::transform(const Mat2D& transform) { - Mat2D::copy(m_Stack.back().transform, transform); + Mat2D& stackMat = m_Stack.back().transform; + Mat2D::multiply(stackMat, stackMat, transform); } const Mat2D& LowLevelRenderer::transform() { return m_Stack.back().transform; } \ 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 04eb48e..1286f6b 100644 --- a/renderer/library/src/opengl/opengl_render_path.cpp +++ b/renderer/library/src/opengl/opengl_render_path.cpp
@@ -1,22 +1,97 @@ #include "opengl/opengl_render_path.hpp" +#include "opengl/opengl_renderer.hpp" +#include "opengl/opengl.h" using namespace rive; OpenGLRenderPath::OpenGLRenderPath() { glGenBuffers(1, &m_ContourBuffer); } + OpenGLRenderPath::~OpenGLRenderPath() { glDeleteBuffers(1, &m_ContourBuffer); } void OpenGLRenderPath::fillRule(FillRule value) { m_FillRule = value; } void OpenGLRenderPath::stencil(OpenGLRenderer* renderer, const Mat2D& transform) { + if (isContainer()) + { + for (auto& subPath : m_SubPaths) + { + Mat2D subPathTransform; + Mat2D::multiply(subPathTransform, transform, subPath.transform()); + reinterpret_cast<OpenGLRenderPath*>(subPath.path()) + ->stencil(renderer, subPathTransform); + } + return; + } + + glUseProgram(renderer->program()); + std::size_t vertexCount; + if (isDirty()) { computeContour(); + vertexCount = m_ContourVertices.size(); + renderer->updateIndexBuffer(vertexCount); glBindBuffer(GL_ARRAY_BUFFER, m_ContourBuffer); - auto length = m_ContourVertices.size(); glBufferData(GL_ARRAY_BUFFER, - length * sizeof(float), - &m_ContourVertices[0], + vertexCount * 2 * sizeof(float), + &m_ContourVertices[0][0], GL_DYNAMIC_DRAW); } + else + { + glBindBuffer(GL_ARRAY_BUFFER, m_ContourBuffer); + vertexCount = m_ContourVertices.size(); + } + + if (vertexCount < 2) + { + return; + } + + auto triangleCount = vertexCount - 2; + // printf("VCOUNT: %i E: %i\n", vertexCount, triangleCount); + // printf("X: %f %f\n", transform[0], transform[1]); + // printf("Y: %f %f\n", transform[2], transform[3]); + // printf("T: %f %f\n", transform[4], transform[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}; + + glUniformMatrix4fv(renderer->transformUniformIndex(), 1, GL_FALSE, m4); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * 4, (void*)0); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, renderer->indexBuffer()); + glDrawElements( + GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_SHORT, (void*)(0)); + GLenum err; + while ((err = glGetError()) != GL_NO_ERROR) + { + // Process/log the error. + fprintf(stderr, "ERRR:: %i\n", err); + } + // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + // static unsigned short indices[3] = {0, 2, 2}; + // glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, &indices[0]); } \ No newline at end of file
diff --git a/renderer/library/src/opengl/opengl_renderer.cpp b/renderer/library/src/opengl/opengl_renderer.cpp index 0b894f6..9313548 100644 --- a/renderer/library/src/opengl/opengl_renderer.cpp +++ b/renderer/library/src/opengl/opengl_renderer.cpp
@@ -19,12 +19,14 @@ bool OpenGLRenderer::initialize(void* data) { + fprintf(stderr, "init opengl\n"); assert(m_VertexShader == 0 && m_FragmentShader == 0 && m_Program == 0); m_VertexShader = createAndCompileShader(GL_VERTEX_SHADER, vertexShaderSource); if (m_VertexShader == 0) { + fprintf(stderr, "init opengl no 1"); return false; } @@ -32,6 +34,7 @@ createAndCompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource); if (m_FragmentShader == 0) { + fprintf(stderr, "init opengl no 2"); return false; } @@ -55,6 +58,21 @@ // Create index buffer which we'll grow and populate as necessary. glGenBuffers(1, &m_IndexBuffer); + // TODO: CLEANUP + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + printf("VAO: %i\n", vao); + glUseProgram(m_Program); + + m_ProjectionUniformIndex = glGetUniformLocation(m_Program, "projection"); + m_TransformUniformIndex = glGetUniformLocation(m_Program, "transform"); + GLint position = glGetAttribLocation(m_Program, "position"); + fprintf(stderr, "POSITION: %i\n", position); + float projection[16] = {0.0f}; + orthographicProjection(projection, 0.0f, 800, 800, 0.0f, 0.0f, 1.0f); + modelViewProjection(projection); + return true; } @@ -65,6 +83,7 @@ { return; } + auto glPath = static_cast<OpenGLRenderPath*>(path); glPath->stencil(this, transform()); } @@ -73,8 +92,12 @@ void OpenGLRenderer::startFrame() { - glClearColor(0.0f, 0.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + // glClearColor(0.0f, 1.0f, 1.0f, 1.0f); + // glClear(GL_COLOR_BUFFER_BIT); + glUseProgram(m_Program); + glEnableVertexAttribArray(0); + glUniformMatrix4fv( + m_ProjectionUniformIndex, 1, GL_FALSE, m_ModelViewProjection); } void OpenGLRenderer::endFrame() {} @@ -95,6 +118,7 @@ auto targetEdgeCount = contourLength - 2; if (edgeCount < targetEdgeCount) { + while (edgeCount < targetEdgeCount) { m_Indices.push_back(0);
diff --git a/renderer/library/src/opengl/opengl_shaders.cpp b/renderer/library/src/opengl/opengl_shaders.cpp index 39d57c7..5e593f4 100644 --- a/renderer/library/src/opengl/opengl_shaders.cpp +++ b/renderer/library/src/opengl/opengl_shaders.cpp
@@ -1,10 +1,14 @@ const char* vertexShaderSource = R"""( -attribute vec2 position; +#version 330 core + +layout (location = 0) in vec2 position; + +out vec2 pos; + uniform mat4 projection; uniform mat4 transform; uniform mat4 localTransform; -varying vec2 pos; void main(void) { @@ -14,6 +18,8 @@ )"""; const char* fragmentShaderSource = R"""( +#version 330 core + #ifdef GL_ES precision highp float; #endif @@ -25,53 +31,57 @@ uniform vec4 colors[16]; uniform float stops[16]; uniform int fillType; -varying vec2 pos; +in vec2 pos; +out vec4 fragColor; + void main() { - 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); - } + fragColor = vec4(0.3, 0.3, 0.3, 0.3); + + // 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); + // } } )"""; \ No newline at end of file
diff --git a/renderer/viewer/assets/triangle.riv b/renderer/viewer/assets/triangle.riv new file mode 100644 index 0000000..42c0d0e --- /dev/null +++ b/renderer/viewer/assets/triangle.riv Binary files differ
diff --git a/renderer/viewer/src/viewer.cpp b/renderer/viewer/src/viewer.cpp index d5610f7..dcca39c 100644 --- a/renderer/viewer/src/viewer.cpp +++ b/renderer/viewer/src/viewer.cpp
@@ -12,7 +12,7 @@ #include "graphics_api.hpp" // Make sure gl3w is included before glfw3 -#include "GL/gl3w.h" +// #include "GL/gl3w.h" #include "GLFW/glfw3.h" #include "GLFW/glfw3native.h" @@ -60,9 +60,9 @@ if (graphicsApi == rive::GraphicsApi::opengl) { glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); - // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); } else { @@ -107,6 +107,7 @@ unsigned int fileBytesLength = 0; std::string filename = "assets/polygon_party.riv"; + // std::string filename = "assets/triangle.riv"; FILE* fp = fopen(filename.c_str(), "r"); fseek(fp, 0, SEEK_END); fileBytesLength = ftell(fp); @@ -150,6 +151,7 @@ { int width = 0, height = 0; glfwGetFramebufferSize(window, &width, &height); + if (lastWidth != width || lastHeight != height) { lastWidth = width;
diff --git a/src/contour_render_path_recursive.cpp b/src/contour_render_path_recursive.cpp index c70ce45..560e512 100644 --- a/src/contour_render_path_recursive.cpp +++ b/src/contour_render_path_recursive.cpp
@@ -62,6 +62,7 @@ } m_IsPenDown = true; Vec2D::copy(m_PenDown, m_Pen); + addVertex(m_PenDown); } inline void close() @@ -72,6 +73,10 @@ } Vec2D::copy(m_Pen, m_PenDown); m_IsPenDown = false; + + // TODO: Can we optimize and not dupe this point if it's the last point + // already in the list? For example: a procedural triangle closes itself + // with a lineTo the first point. addVertex(m_PenDown); } @@ -103,7 +108,7 @@ addVertex(Vec2D(CubicUtilities::cubicAt( t2, from[0], fromOut[0], toIn[0], to[0]), CubicUtilities::cubicAt( - t2, from[1], fromOut[1], toIn[1], to[0]))); + t2, from[1], fromOut[1], toIn[1], to[1]))); } } } @@ -136,6 +141,7 @@ command.point(), 0.0f, 1.0f); + // segmenter.addVertex(command.point()); segmenter.pen(command.point()); break; case PathCommandType::close: @@ -149,7 +155,6 @@ // TODO: consider if there's a case with no points. Vec2D& first = m_ContourVertices[0]; - AABB::copy(m_ContourBounds, segmenter.bounds()); first[0] = m_ContourBounds.minX; first[1] = m_ContourBounds.minY;