diff --git a/assets/test.jpg b/assets/test.jpg new file mode 100644 index 0000000..d2f9ce8 Binary files /dev/null and b/assets/test.jpg differ diff --git a/lua/builder_test.lua b/lua/builder_test.lua index 71da81c..5376677 100644 --- a/lua/builder_test.lua +++ b/lua/builder_test.lua @@ -7,6 +7,13 @@ config{ font_color=rgba{255, 0, 0, 255}, } +slide{ + h1 "Here's Mine", + image{ + src="test.jpg" + } +} + slide{ layout="no_title", font_size=200, @@ -48,13 +55,6 @@ slide{ ul "No need for phantom power.", } -slide{ - h1 "Here's Mine", - image{ - src="p100101.jpg" - } -} - slide{ layout="no_title", font_size=150, diff --git a/meson.build b/meson.build index dddbce6..60b3aab 100644 --- a/meson.build +++ b/meson.build @@ -40,6 +40,7 @@ sources = [ 'src/framebuffer.cpp', 'src/screen.cpp', 'src/render.cpp', + 'src/image.cpp', ] tests = [ diff --git a/shaders/image.frag.glsl b/shaders/image.frag.glsl new file mode 100644 index 0000000..54f2132 --- /dev/null +++ b/shaders/image.frag.glsl @@ -0,0 +1,12 @@ +#version 330 core +out vec4 FragColor; + +in vec2 TexCoord; + +// texture sampler +uniform sampler2D texture1; + +void main() +{ + FragColor = texture(texture1, TexCoord); +} diff --git a/shaders/image.vert.glsl b/shaders/image.vert.glsl new file mode 100644 index 0000000..acd8ef1 --- /dev/null +++ b/shaders/image.vert.glsl @@ -0,0 +1,11 @@ +#version 330 core +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; + +out vec2 TexCoord; + +void main() +{ + gl_Position = vec4(aPos, 1.0); + TexCoord = aTexCoord; +} diff --git a/src/image.cpp b/src/image.cpp new file mode 100644 index 0000000..cb42c94 --- /dev/null +++ b/src/image.cpp @@ -0,0 +1,83 @@ +#include "image.hpp" +#include + +unsigned int image_to_texture(unsigned char *data, int width, int height, int nrComponents) { + unsigned int textureID; + glGenTextures(1, &textureID); + + GLenum format = GL_RGB; + + switch(nrComponents) { + case 1: + format = GL_RED; + break; + case 3: + format = GL_RGB; + break; + case 4: + format = GL_RGBA; + break; + default: + dbc::sentinel($F("Impossible nrComponents={} when loading image", nrComponents)); + } + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + return textureID; +} + +void Image::load(Node& node) { + dbc::check(node.type == NodeType::IMAGE, "That's not an image idiot."); + + if(!node.config.contains("_image_data")) { + dbc::check(node.config.contains("src"), "Node doesn't have an image src."); + std::string filename = std::any_cast(node.config.at("src")); + + int width = 0; + int height = 0; + int nrComponents = 0; + stbi_set_flip_vertically_on_load(true); + unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0); + dbc::check(data != NULL, "Failed to stb_load image."); + + unsigned int texture_id = image_to_texture(data, width, height, nrComponents); + + node.config.try_emplace("_image_data", texture_id); + + stbi_image_free(data); + } +} + +void Image::render(Node& node, float xpos, float ypos, float w, float h) { + dbc::check(node.config.contains("_image_data"), "Node isn't configured for images, did you Image::load?"); + + unsigned int texture_id = std::any_cast(node.config.at("_image_data")); + + shader.use(); + shader.setInt("texture1", texture_id); + glBindVertexArray(image_vao); + glBindTexture(GL_TEXTURE_2D, texture_id); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + +Image::Image() { + glGenVertexArrays(1, &image_vao); + glGenBuffers(1, &image_vbo); + + glBindVertexArray(image_vao); + glBindBuffer(GL_ARRAY_BUFFER, image_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + + // position attrib + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + + // color attribute + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + glEnableVertexAttribArray(1); +} diff --git a/src/image.hpp b/src/image.hpp new file mode 100644 index 0000000..89c71f0 --- /dev/null +++ b/src/image.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "document.hpp" +#include "shader.hpp" + +struct Image { + Shader shader{{"shaders/image.vert.glsl", "shaders/image.frag.glsl", ""}}; + unsigned int image_vao = UINT_MAX; + unsigned int image_vbo = UINT_MAX; + + float vertices[24] = { + // positions // texCoords + -0.5f, 0.5f, 0.0f, 1.0f, // top left + -0.5f, -0.5f, 0.0f, 0.0f, // bottom left + 0.5f, -0.5f, 1.0f, 0.0f, // bottom right + + -0.5f, 0.5f, 0.0f, 1.0f, // top left + 0.5f, -0.5f, 1.0f, 0.0f, // bottom right + 0.5f, 0.5f, 1.0f, 1.0f, // top right + }; + + Image(); + void load(Node& node); + void render(Node& node, float xpos, float ypos, float w, float h); +}; diff --git a/src/render.cpp b/src/render.cpp index 5b1b315..65919e1 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -1,6 +1,11 @@ #include "render.hpp" #include "config.hpp" #include +#include "dbc.hpp" +#include +#include +#include +#include "image.hpp" Engine::Engine(Deck &deck) : deck(deck) @@ -20,11 +25,18 @@ void Engine::render() { float line = 0; for(auto& node : slide.content) { + line++; + float y = (text.font_size + 20) * line; + if(node.type == NodeType::TEXT || node.type == NodeType::H1 || node.type == NodeType::UL) { - line++; - float y = (text.font_size + 20) * line; - text.render(node.content, 25.0f, SCR_HEIGHT - y, 1.0f, - glm::vec3(1.0f, 1.0f, 1.0f)); + text.render(node.content, 25.0f, SCR_HEIGHT - y, 1.0f, glm::vec3(1.0f, 1.0f, 1.0f)); + } else if(node.type == NodeType::IMAGE) { + Image img; + img.load(node); + img.render(node, -1.0f, -1.0f, 1.0f, 1.0f); + // it's an image, skip it + } else { + dbc::sentinel("Unknown NodeType"); } } diff --git a/src/screen.cpp b/src/screen.cpp index f103dcc..c8405aa 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -11,8 +11,10 @@ void Screen::init() { glBindVertexArray(target_VAO); glBindBuffer(GL_ARRAY_BUFFER, target_VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0); - glEnableVertexAttribArray(1); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); + glEnableVertexAttribArray(1); }