diff --git a/src/awesomeface.png b/src/awesomeface.png new file mode 100644 index 0000000..9840caf Binary files /dev/null and b/src/awesomeface.png differ diff --git a/src/fragment.glsl b/src/fragment.glsl index f6d7b2e..9af658b 100644 --- a/src/fragment.glsl +++ b/src/fragment.glsl @@ -5,8 +5,9 @@ out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; -uniform sampler2D ourTexture; +uniform sampler2D texture1; +uniform sampler2D texture2; void main() { - FragColor = texture(ourTexture, TexCoord); + FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); } diff --git a/src/image.cc b/src/image.cc index 050d3b8..ceec35b 100644 --- a/src/image.cc +++ b/src/image.cc @@ -1,8 +1,9 @@ #include "image.hh" #include -Image::Image(const char* path) { - data = stbi_load(path, &width, &height, &nrChannels, 0); +Image::Image(std::string path) { + stbi_set_flip_vertically_on_load(true); + data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0); } Image::~Image() { diff --git a/src/image.hh b/src/image.hh index d0245a8..2de3a5e 100644 --- a/src/image.hh +++ b/src/image.hh @@ -1,11 +1,12 @@ #ifndef IMAGE_HH #define IMAGE_HH +#include #define STB_IMAGE_IMPLEMENTATION class Image { public: int width, height, nrChannels; unsigned char* data; - Image(const char* path); + Image(std::string path); ~Image(); }; #endif diff --git a/src/main.cc b/src/main.cc index f448494..96f78fa 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,6 +3,7 @@ #include #include +#include #include "shader.hh" #include "utilities.hh" @@ -134,6 +135,7 @@ GlRenderObjects* rectangle() { int main() { glfwInit(); +{ // Set OpenGL version to 3.3. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -162,29 +164,56 @@ int main() { std::string currentPath = utilities::getCurrentPath(); // Create a shader class. - Shader* shader = new Shader(std::format("{}/vertex.glsl", currentPath).c_str(), std::format("{}/fragment.glsl", currentPath).c_str()); + Shader shader(std::format("{}/vertex.glsl", currentPath).c_str(), std::format("{}/fragment.glsl", currentPath).c_str()); - GlRenderObjects* triangleRenderObjs = triangle(); - GlRenderObjects* rectangleRenderObjs = rectangle(); + std::unique_ptr triangleRenderObjs(triangle()); + std::unique_ptr rectangleRenderObjs(rectangle()); - unsigned int texture; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); + unsigned int texture1, texture2; + +{ + glGenTextures(1, &texture1); + glBindTexture(GL_TEXTURE_2D, texture1); 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_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - { - Image texture(std::format("{}/container.jpg", utilities::getCurrentPath()).c_str()); - if (texture.data) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width, texture.height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture.data); - glGenerateMipmap(GL_TEXTURE_2D); - } else { - std::cout << "Failed to load texture." << std::endl; - } + Image texture(utilities::getCurrentPath("container.jpg")); + if (texture.data) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture.width, texture.height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture.data); + glGenerateMipmap(GL_TEXTURE_2D); + } else { + std::cout << "Failed to load texture." << std::endl; } +} + +{ + glGenTextures(1, &texture2); + glBindTexture(GL_TEXTURE_2D, texture2); + + 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); + + Image texture(utilities::getCurrentPath("awesomeface.png")); + + if (texture.data) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.data); + glGenerateMipmap(GL_TEXTURE_2D); + } else { + std::cout << "Failed to load texture." << std::endl; + } +} + + // activate the shader + shader.activate(); + + // tell the shader what texture unit the textures are on + shader.setInt("texture1", 0); + shader.setInt("texture2", 1); // Create a render loop, which keeps the program open until glfw tells the loop that the window should close. while (!glfwWindowShouldClose(window)) { @@ -198,8 +227,12 @@ int main() { // Clear the screen and use the color from the state. glClear(GL_COLOR_BUFFER_BIT); - // activate the shader - shader->activate(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture1); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture2); + + shader.activate(); if (!rectangleToggled) { // Bind the state to use the vertexArrayObject object so OpenGL knows what to do with the verticies. @@ -219,11 +252,7 @@ int main() { // Check if any events are triggered. glfwPollEvents(); } - - // Clean up objects from memory. - delete triangleRenderObjs; - delete rectangleRenderObjs; - delete shader; +} glfwTerminate(); return 0; diff --git a/src/meson.build b/src/meson.build index 2b665cb..902cb98 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,6 +10,7 @@ copy = find_program('cp') fragment = custom_target('fragment', output: 'fragment.glsl', input: 'fragment.glsl', command: [copy, '@INPUT@', '@OUTPUT@']) vertex = custom_target('vertex', output: 'vertex.glsl', input: 'vertex.glsl', command: [copy, '@INPUT@', '@OUTPUT@']) container = custom_target('container', output: 'container.jpg', input: 'container.jpg', command: [copy, '@INPUT@', '@OUTPUT@']) +awesomeface = custom_target('awesomeface', output: 'awesomeface.png', input: 'awesomeface.png', command: [copy, '@INPUT@', '@OUTPUT@']) -executable('main', [sources] + [fragment, vertex, container], dependencies: [glfw, libepoxy]) +executable('main', [sources, fragment, vertex, container, awesomeface], dependencies: [glfw, libepoxy]) executable('fixedfunction', ['fixedfunction.cc'], dependencies: [glfw, libepoxy]) diff --git a/src/shader.cc b/src/shader.cc index 49db14f..a751cbc 100644 --- a/src/shader.cc +++ b/src/shader.cc @@ -94,12 +94,12 @@ void Shader::activate() { glUseProgram(id); } -void Shader::setBool(const std::string &name, bool value) const { - glUniform1f(glGetUniformLocation(id, name.c_str()), (int)value); +void Shader::setBool(const char* name, bool value) const { + glUniform1i(glGetUniformLocation(id, name), (int)value); } -void Shader::setInt(const std::string &name, int value) const { - glUniform1f(glGetUniformLocation(id, name.c_str()), value); +void Shader::setInt(const char* name, int value) { + glUniform1i(glGetUniformLocation(id, name), value); } -void Shader::setFloat(const std::string &name, float value) const { - glUniform1f(glGetUniformLocation(id, name.c_str()), value); +void Shader::setFloat(const char* name, float value) const { + glUniform1f(glGetUniformLocation(id, name), value); } diff --git a/src/shader.hh b/src/shader.hh index 6b747b1..e7877bd 100644 --- a/src/shader.hh +++ b/src/shader.hh @@ -14,9 +14,9 @@ class Shader { // activate the shader. void activate(); // utility uniform functions - void setBool(const std::string &name, bool value) const; - void setInt(const std::string &name, int value) const; - void setFloat(const std::string &name, float value) const; + void setBool(const char* name, bool value) const; + void setInt(const char* name, int value) ; + void setFloat(const char* name, float value) const; private: uint compileShader(std::string code, GLenum type, std::string shaderTypeName); uint compileVertexShader(std::string code); diff --git a/src/utilities.cc b/src/utilities.cc index cda6226..49e4f5a 100644 --- a/src/utilities.cc +++ b/src/utilities.cc @@ -4,6 +4,7 @@ #include #include #include +#include std::string utilities::getCurrentPath() { char result[PATH_MAX]; @@ -14,6 +15,10 @@ std::string utilities::getCurrentPath() { return utilities::combineString(stringVector, '/'); } +std::string utilities::getCurrentPath(std::string file) { + return std::format("{}/{}", getCurrentPath(), file); +} + std::vector utilities::splitString(std::string string, char delimiter) { size_t last = 0; size_t next = 0; diff --git a/src/utilities.hh b/src/utilities.hh index fb32785..7745cdc 100644 --- a/src/utilities.hh +++ b/src/utilities.hh @@ -5,6 +5,7 @@ namespace utilities { std::string getCurrentPath(); + std::string getCurrentPath(std::string file); std::vector splitString(std::string string, char delimiter); std::string combineString(std::vector stringVector, char delimiter); }