author | František Kučera <franta-hg@frantovo.cz> |
Tue, 28 Nov 2023 22:45:33 +0100 | |
branch | v_0 |
changeset 1 | fb65455622b9 |
parent 0 | bb715a82a8f1 |
child 2 | 3faef2f5128e |
AllocatedBuffer.h | file | annotate | diff | comparison | revisions | |
ImageLoader.cpp | file | annotate | diff | comparison | revisions | |
ImageLoader.h | file | annotate | diff | comparison | revisions | |
Makefile | file | annotate | diff | comparison | revisions | |
Shark.cpp | file | annotate | diff | comparison | revisions | |
Shark.h | file | annotate | diff | comparison | revisions | |
nbproject/configurations.xml | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AllocatedBuffer.h Tue Nov 28 22:45:33 2023 +0100 @@ -0,0 +1,38 @@ +/** + * ShaderShark + * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <stdlib.h> +#include <stdexcept> + +#include "Buffer.h" + +class AllocatedBuffer : public Buffer { +public: + + AllocatedBuffer(size_t size) { + this->size = size; + data = (char*) malloc(size); + if (!data) throw std::invalid_argument("unable to allocate buffer"); + } + + virtual ~AllocatedBuffer() { + free(data); + } + +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ImageLoader.cpp Tue Nov 28 22:45:33 2023 +0100 @@ -0,0 +1,43 @@ +/** + * ShaderShark + * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <iostream> + +#include <Magick++.h> + +#include "ImageLoader.h" +#include "AllocatedBuffer.h" + +ImageLoader::ImageBuffer* ImageLoader::loadImage(const Buffer& input) { + Magick::Blob inputBlob(input.getData(), input.getSize()); + Magick::Image image(inputBlob); + + // Magick::PixelPacket* parsedPixels = parsedImage.getPixels( + // 0, 0, parsedImage.size().width(), parsedImage.size().height()); + + Magick::Blob outputBlob; + image.magick("RGBA"); + image.write(&outputBlob); + + ImageBuffer* outputBuffer = new ImageBuffer( + (void*) outputBlob.data(), + outputBlob.length(), + image.size().width(), + image.size().height()); + + return outputBuffer; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ImageLoader.h Tue Nov 28 22:45:33 2023 +0100 @@ -0,0 +1,44 @@ +/** + * ShaderShark + * Copyright © 2023 František Kučera (Frantovo.cz, GlobalCode.info) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <string.h> + +#include "Buffer.h" +#include "AllocatedBuffer.h" + +class ImageLoader { +public: + + class ImageBuffer : public AllocatedBuffer { + public: + int width; + int height; + + ImageBuffer(void* buffer, const size_t size, + const int width, const int height) : + AllocatedBuffer(width * height * 4), + width(width), height(height) { + if (size == width * height * 4) memcpy(data, buffer, size); + else throw std::invalid_argument("invalid image size"); + } + + }; + + ImageBuffer* loadImage(const Buffer& inputBuffer); +};
--- a/Makefile Sun Nov 26 16:27:50 2023 +0100 +++ b/Makefile Tue Nov 28 22:45:33 2023 +0100 @@ -20,18 +20,22 @@ clean: rm -rf build -run: build/shader-shark build/jazz.rgba - $(<) --texture build/jazz.rgba +run: build/shader-shark build/jazz.png + $(<) --texture build/jazz.png build: mkdir -p $(@) -SRC=Shark.cpp shader-shark.cpp +SRC=Shark.cpp shader-shark.cpp ImageLoader.cpp build/shader-shark: $(SRC) build *.h $(CXX) -std=c++20 -g -o $(@) $(SRC) $$(pkg-config --cflags --libs \ - epoxy x11 glu glm) + epoxy x11 glu glm Magick++) +build/jazz.png: textures/jazz.png + mkdir -p build + cp --reflink=auto $(<) $(@) + build/jazz.rgba: textures/jazz.png mkdir -p build convert -format rgba $(<) $(@)
--- a/Shark.cpp Sun Nov 26 16:27:50 2023 +0100 +++ b/Shark.cpp Tue Nov 28 22:45:33 2023 +0100 @@ -15,6 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <memory> + #include "Shark.h" Shark::Shark(const Configuration& configuration) : @@ -65,8 +67,8 @@ // Load GLSL shaders: GLuint shaderProgram = loadShaders(); + loadTextures(shaderProgram); loadVertices(); - loadTextures(shaderProgram); auto toggleFullscreen = [&]() { full = setFullscreen(dpy, win, !full); @@ -267,77 +269,82 @@ } void Shark::loadVertices() { - const std::vector<GLfloat> vertices = { - // Vertex XYZ Texture XY - -0.80f * TEX.ratio, +0.80f, +0.0, /**/ 0.0, 0.0, - +0.80f * TEX.ratio, +0.80f, +0.0, /**/ 1.0, 0.0, - -0.80f * TEX.ratio, -0.80f, +0.0, /**/ 0.0, 1.0, + for (int i = 0; i < textures.size(); i++) { + const Texture& tex = textures[i]; + GLfloat ratio = tex.getRatio(); + const std::vector<GLfloat> vertices = { + // Vertex XYZ Texture XY + -0.80f * ratio, +0.80f, +0.0, /**/ 0.0, 0.0, + +0.80f * ratio, +0.80f, +0.0, /**/ 1.0, 0.0, + -0.80f * ratio, -0.80f, +0.0, /**/ 0.0, 1.0, - -0.80f * TEX.ratio, -0.80f, +0.0, /**/ 0.0, 1.0, - +0.80f * TEX.ratio, -0.80f, +0.0, /**/ 1.0, 1.0, - +0.80f * TEX.ratio, +0.80f, +0.0, /**/ 1.0, 0.0, + -0.80f * ratio, -0.80f, +0.0, /**/ 0.0, 1.0, + +0.80f * ratio, -0.80f, +0.0, /**/ 1.0, 1.0, + +0.80f * ratio, +0.80f, +0.0, /**/ 1.0, 0.0, - // viz glDrawArrays(), kde vybereme počátek a počet hodnot - }; + // viz glDrawArrays(), kde vybereme počátek a počet hodnot + }; - // Vertex data: - glVertexAttribPointer(ProgAttr.vertexXYZ, 3, // vertex items - GL_FLOAT, GL_FALSE, 5 * sizeof (float), - (void*) 0); - glEnableVertexAttribArray(ProgAttr.vertexXYZ); + // Vertex data: + glVertexAttribPointer(ProgAttr.vertexXYZ, 3, // vertex items + GL_FLOAT, GL_FALSE, 5 * sizeof (float), + (void*) 0); + glEnableVertexAttribArray(ProgAttr.vertexXYZ); - // Texture positions: - glVertexAttribPointer(ProgAttr.textureXY, 2, // texture items - GL_FLOAT, GL_FALSE, 5 * sizeof (float), - (void*) (3 * sizeof (float))); - glEnableVertexAttribArray(ProgAttr.textureXY); + // Texture positions: + glVertexAttribPointer(ProgAttr.textureXY, 2, // texture items + GL_FLOAT, GL_FALSE, 5 * sizeof (float), + (void*) (3 * sizeof (float))); + glEnableVertexAttribArray(ProgAttr.textureXY); - glBufferData(GL_ARRAY_BUFFER, - vertices.size() * sizeof (vertices[0]), - vertices.data(), - GL_STATIC_DRAW); - // GL_STATIC_DRAW: - // The vertex data will be uploaded once - // and drawn many times(e.g. the world). - // GL_DYNAMIC_DRAW: - // The vertex data will be created once, changed from - // time to time, but drawn many times more than that. - // GL_STREAM_DRAW: - // The vertex data will be uploaded once and drawn once. + glBufferData(GL_ARRAY_BUFFER, + vertices.size() * sizeof (vertices[0]), + vertices.data(), + GL_STATIC_DRAW); + // GL_STATIC_DRAW: + // The vertex data will be uploaded once + // and drawn many times(e.g. the world). + // GL_DYNAMIC_DRAW: + // The vertex data will be created once, changed from + // time to time, but drawn many times more than that. + // GL_STREAM_DRAW: + // The vertex data will be uploaded once and drawn once. - // see also glBindBuffer(GL_ARRAY_BUFFER, vbo); where we set current VBO + // see also glBindBuffer(GL_ARRAY_BUFFER, vbo); where we set current VBO + } } -GLuint Shark::loadTexture(const std::string& fileName, int width, int height) { - MappedFile file(fileName); - if (file.getSize() == width * height * 4) { - GLuint textureID; - glGenTextures(1, &textureID); - glBindTexture(GL_TEXTURE_2D, textureID); - auto GLT2D = GL_TEXTURE_2D; - glTexImage2D(GLT2D, 0, GL_RGBA, - width, height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, - file.getData()); - glTexParameteri(GLT2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GLT2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GLT2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GLT2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glGenerateMipmap(GLT2D); - std::cerr << "loadTexture(\"" << fileName.c_str() << "\", " - << width << ", " << height << ") = " << textureID << std::endl; - checkError(&std::cerr); - return textureID; - } else { - throw std::invalid_argument("wrong texture file size"); - } +Shark::Texture Shark::loadTexture(const std::string& fileName) { + Texture tex; + tex.fileName = fileName; + MappedFile file(tex.fileName); + + std::shared_ptr<ImageLoader::ImageBuffer> img(imageLoader.loadImage(file)); + + tex.width = img->width; + tex.height = img->height; + + glGenTextures(1, &tex.id); + glBindTexture(GL_TEXTURE_2D, tex.id); + auto GLT2D = GL_TEXTURE_2D; + glTexImage2D(GLT2D, 0, GL_RGBA, + tex.width, tex.height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, + img->getData()); + glTexParameteri(GLT2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GLT2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GLT2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GLT2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glGenerateMipmap(GLT2D); + std::cerr << "loadTexture(\"" << fileName.c_str() << "\", " + << tex.width << ", " << tex.height << ") = " << tex.id << std::endl; + checkError(&std::cerr); + return tex; } void Shark::loadTextures(GLuint shaderProgram) { for (const Configuration::Texture& tex : cfg.textures) { - GLuint jazz = loadTexture(tex.fileName, TEX.width, TEX.height); - // FIXME: decode PNG, JPEG etc. formats - // FIXME: read width and height from the file + textures.push_back(loadTexture(tex.fileName)); // TODO: review texture loading and binding // works even without this - default texture // glUniform1i(ProgAttr.jazz, jazz);
--- a/Shark.h Sun Nov 26 16:27:50 2023 +0100 +++ b/Shark.h Tue Nov 28 22:45:33 2023 +0100 @@ -34,6 +34,7 @@ #include "EPoll.h" #include "Logger.h" #include "MappedFile.h" +#include "ImageLoader.h" class Shark { private: @@ -155,11 +156,21 @@ } initialCtx, ctx; - const struct { - int width = 640; - int height = 398; - GLfloat ratio = (GLfloat) width / (GLfloat) height; - } TEX; + class Texture { + public: + GLuint id; + std::string fileName; + int width; + int height; + + GLfloat getRatio() const { + return (GLfloat) width / (GLfloat) height; + } + }; + + ImageLoader imageLoader; + + std::vector<Texture> textures; Configuration cfg; std::ostream& logOutput = std::cerr; @@ -170,7 +181,7 @@ void log(LogLevel level, std::string message); int setNonBlocking(int fd); void loadVertices(); - GLuint loadTexture(const std::string& fileName, int width, int height); + Texture loadTexture(const std::string& fileName); void loadTextures(GLuint shaderProgram); GLuint loadShaders(); public:
--- a/nbproject/configurations.xml Sun Nov 26 16:27:50 2023 +0100 +++ b/nbproject/configurations.xml Tue Nov 28 22:45:33 2023 +0100 @@ -2,6 +2,7 @@ <configurationDescriptor version="100"> <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT"> <df root="." name="0"> + <in>ImageLoader.cpp</in> <in>Shark.cpp</in> <in>shader-shark.cpp</in> </df> @@ -25,6 +26,9 @@ <dependencyChecking>false</dependencyChecking> <rebuildPropChanged>false</rebuildPropChanged> </toolsSet> + <flagsDictionary> + <element flagsID="0" commonFlags="-std=c++20 -fopenmp -fopenmp -fopenmp"/> + </flagsDictionary> <codeAssistance> </codeAssistance> <makefileType> @@ -33,15 +37,33 @@ <buildCommand>${MAKE} -f Makefile</buildCommand> <cleanCommand>${MAKE} -f Makefile clean</cleanCommand> <executablePath>build/shader-shark</executablePath> + <ccTool> + <incDir> + <pElem>/usr/include/x86_64-linux-gnu/ImageMagick-6</pElem> + <pElem>/usr/include/ImageMagick-6</pElem> + </incDir> + <preprocessorList> + <Elem>MAGICKCORE_HDRI_ENABLE=0</Elem> + <Elem>MAGICKCORE_QUANTUM_DEPTH=16</Elem> + </preprocessorList> + </ccTool> </makeTool> <preBuild> <preBuildCommandWorkingDir>.</preBuildCommandWorkingDir> <preBuildCommand></preBuildCommand> </preBuild> </makefileType> + <item path="ImageLoader.cpp" ex="false" tool="1" flavor2="0"> + <ccTool flags="0"> + </ccTool> + </item> <item path="Shark.cpp" ex="false" tool="1" flavor2="0"> + <ccTool flags="0"> + </ccTool> </item> <item path="shader-shark.cpp" ex="false" tool="1" flavor2="0"> + <ccTool flags="0"> + </ccTool> </item> </conf> </confs>