From ccb06324c3c0f903033bb8185f6b05fce4a105dd Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 21 Oct 2026 21:48:07 -0400 Subject: [PATCH] Can now load an image but it needs some work. --- assets/test.jpg | Bin 0 -> 26826 bytes lua/builder_test.lua | 14 +++---- meson.build | 1 + shaders/image.frag.glsl | 12 ++++++ shaders/image.vert.glsl | 11 ++++++ src/image.cpp | 83 ++++++++++++++++++++++++++++++++++++++++ src/image.hpp | 25 ++++++++++++ src/render.cpp | 20 ++++++++-- src/screen.cpp | 6 ++- 9 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 assets/test.jpg create mode 100644 shaders/image.frag.glsl create mode 100644 shaders/image.vert.glsl create mode 100644 src/image.cpp create mode 100644 src/image.hpp diff --git a/assets/test.jpg b/assets/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2f9ce86be5680f162d7252062fd9dccb25177b7 GIT binary patch literal 26826 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˜c{03m;n+hG6;k&29hgo1{hfW3-aXJI5Ox8MP{ zxi&FuL;wKxAO%1dU{54uUcNggfxoe)j+C_}(!cO1LCDrxpD#`6!x#FW zbCy|rN56-MQ@=k-oYZ6T^!DZVFqDMd667(%OU=~U8zJljN>=FYCZ8{plVsj}8M#>H zBRAYy^GI#kEznsl@^ZDJZpC28ZrO`eH^>UW%AJTTEC3LPb_3i506WMba4;AkKv34h z6^_as;7Nl75Z1*aN=Bj^6WA{-S7@Qw;>fYAlVeN3n13lIg;)_~A^{AWA0-+;(-uP? z@)39~qF&TYSyJ4NPIua$hAyTLz_~J^(?WJ8D{BTqYRG85uIQIf!HTTkkr!9khL>h@ zQe=&xWWZTK*jo$$lMHf#gg|4+W5^1Luwu6iR^kf51IKX3aRpw%PaW8u1z7k3ZFURB z$ZcRm3AO{^R75IB2TT&MBq*xx=vJ4K0=pn_?n{&6kh-jFRi(B?Z=cv!#rGz`bT4t= zfe-*HDJ&2rfWU450@Q#j_~1_<1VONXL<~0oU;+RD3jhGI z0H}aKHX%R&A|L<&005vqjUu9~Nfwdzq!kovrwe4lHgrZbsU7gel|@pdQtX7VG<9nb zX{Q?|Ft>wSQB;mr{71ioi}|wjzNHw_GqP^Uawa&ta`hYV8@5AZZv#uw#Zna$)t$sPF4F9UYr7`sSCVX1_C&cp;uVu&wkrUm zAhat0*ahwgHv|D=p^FQDzz48AZZ4<5y})gV0*DX*h#MB$1!Py)fzXDKfIWl&L;^vu z0CE5X0J#8I0385;Ob22B6@U-`01yZOfB*mr3jqQ2@kY>zFpZnVDEps(3|TluMOP+^ z9^y)uc0G>hX%z^z#itu)t*EMBc4I5}diZ#yo!NRe)KwxI6J*&YF1(!E@NJQJux{BC zmj?YjS!ZoGD<(}_v_W=+!?!XdntqMM>@8{|yNl!>cA#F>j!)4-la zp9188ETUNGQrOK3$zywx%&J=QA-CXO%)pThO<>IkD#C?ER0wQ90bn8_pc7z#06@C{ z>?}c&0sg`ms89)o41oxAI`BauMN;Md3ADCAG`I{de*$g2*noESBsLw8AQKA!3jsPH z00M{><3JZc0&E)*5POJX01bdd57=1X5YPx=eS`ol&}=>|1-LdKAOHX$00IJp761T( zzyLr1eS}v}xuR8`Ns8s}TJF!%Nakw=!Y)pd6k^*owFuOH>{|43aqsTS(YF{zqxm7c z3dwS|Ok=MvFW|_Ogyl$!w`|v^j@wk_NX@Z1U9udg#mG4_ShqqsTF`8pu{jaHCM{E9 zY;DpY&8lbw1PuddHX_I#z$*&@g@yJKAY&5>02&Y!I|RjHp5Rg%@<`Uj3`x+e0HiWg z9_4}ZRp6DlH@S9)V6sJ&wh%Gh5-|k=6Tpfbn1O&5uo9T}0{BSHl=vZv7_S0Y739bn z9F#{UYO47YV6rR0HVeq_b-6YMcBJ1=PaW4!wnixgbr7>hOtjVQ5@z zHVPG>u@F1%!~sMFu?3_Apb!B71EB!x0t>+`2H1x75fA_efDjIZ00LPJut33x05=a| zIshGrKtKQh000mG9>NF!0000$002Suaml1rna2jv!aq$tCK&FiK9x&yLGCAn$s@K| z{7+CyU5LCkOrB^`+->K!+qzPA$#TU9EQiU9L3kmtvQBojAaAg&R!i8zix9a6VMBIJ zfS%@U4#r9cu-I*rz;FcEEMnv=0d6o56ocHAxXKt<3xEr-_7M3XW3g}vngGOxfNNoi z0^G1Wq$cnt@B?9?@JRRo*_R#&EnzaiH<1GpW!f8dO^;*Hf zUg5|+#6ZLx0RdnEzz6^c3kwDu05l+50ss|0M4g8O0|0vn2Y3(&fr%Aa6T=z`fmZ;S zkppZ%Cx%2Z0ssww00cAwTYv=wumB+N#>7B!F$e;{1<3#d1_A&80SrVy0006QZ~!0z J01yKM|JfM3i{=0T literal 0 HcmV?d00001 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); }