Get textures working

This commit is contained in:
Archie Hilton 2024-05-24 21:38:16 +01:00
parent 06ae06f0d9
commit 3584b4c861
12 changed files with 262 additions and 8156 deletions

View File

@ -3,8 +3,10 @@ cmake_minimum_required(VERSION 3.21)
project(Exponent CXX) project(Exponent CXX)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined -g") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined -g")
set(CMAKE_BUILD_TYPE Debug) #set(CMAKE_BUILD_TYPE Debug)
find_package(PNG REQUIRED)
add_subdirectory(glfw) add_subdirectory(glfw)
add_subdirectory(src) add_subdirectory(src)

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,18 @@
add_executable(Exponent add_executable(Exponent
main.cc main.cc
GLProgramLoader.cc GLProgramLoader.cc
stb_image.cc
Quad.cc Quad.cc
Mesh.cc Mesh.cc
) )
target_link_libraries(Exponent PUBLIC glfw glm::glm) target_link_libraries(Exponent PUBLIC glfw glm::glm ${PNG_LIBRARY})
target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include) target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include
${PNG_INCLUDE_DIR})
target_compile_definitions(Exponent PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>") target_compile_definitions(Exponent PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
target_compile_definitions(Exponent PRIVATE GLFW_INCLUDE_NONE) target_compile_definitions(Exponent PRIVATE GLFW_INCLUDE_NONE)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.frag" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/") file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.frag" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.vert" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/") file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/shaders/shader.vert" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/shaders/")
file(COPY "${CMAKE_SOURCE_DIR}/res/" DESTINATION
"${CMAKE_CURRENT_BINARY_DIR}/res")

View File

@ -1,20 +1,28 @@
#include "Mesh.hh" #include "Mesh.hh"
#include <glad/gl.h> #include <glad/gl.h>
#include <span>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <span>
Mesh::Mesh(std::span<glm::vec2> verts) { Mesh::Mesh(std::span<float> verts) {
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
glBindVertexArray(vao); glBindVertexArray(vao);
glGenBuffers(1, &vbo); glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(glm::vec2), verts.data(), GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * verts.size(), verts.data(),
GL_STATIC_DRAW);
// TODO: Handle if the buffer can't be allocated // TODO: Handle if the buffer can't be allocated
glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE, 0, NULL); glVertexAttribPointer(vertex_data_position, 2, GL_FLOAT, GL_FALSE,
7 * sizeof(float), NULL);
glEnableVertexAttribArray(vertex_data_position); glEnableVertexAttribArray(vertex_data_position);
glVertexAttribPointer(vertex_data_colour, 3, GL_FLOAT, GL_FALSE,
7 * sizeof(float), (void *)(2 * sizeof(float)));
glEnableVertexAttribArray(vertex_data_colour);
glVertexAttribPointer(vertex_data_texture_coords, 2, GL_FLOAT, GL_FALSE,
7 * sizeof(float), (void *)(5 * sizeof(float)));
glEnableVertexAttribArray(vertex_data_texture_coords);
} }
Mesh::~Mesh() { Mesh::~Mesh() {

View File

@ -1,25 +1,25 @@
#pragma once #pragma once
#include <glad/gl.h> #include <glad/gl.h>
#include <span>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <span>
class Mesh { class Mesh {
const static GLuint vertex_data_position = 0; const static GLuint vertex_data_position = 0;
const static GLuint vertex_data_colour = 1;
const static GLuint vertex_data_texture_coords = 2;
private: private:
// std::array<float, T> m_verts; // std::array<float, T> m_verts;
GLuint vbo; GLuint vbo;
GLuint vao; GLuint vao;
public: public:
Mesh(std::span<glm::vec2> verts); Mesh(std::span<float> verts);
~Mesh(); ~Mesh();
Mesh(Mesh &m) = delete; Mesh(Mesh &m) = delete;
void bindVAO() { void bindVAO() { glBindVertexArray(vao); }
glBindVertexArray(vao);
}
}; };

View File

@ -3,36 +3,105 @@
#include "glm/ext/matrix_transform.hpp" #include "glm/ext/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp" #include "glm/gtc/type_ptr.hpp"
#include "glm/trigonometric.hpp" #include "glm/trigonometric.hpp"
#include <exception>
#include <glm/ext.hpp>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/matrix.hpp> #include <glm/matrix.hpp>
#include <glm/ext.hpp>
#include <glad/gl.h> #include <png.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glad/gl.h>
#include <pngconf.h>
#include <string.h> #include <string.h>
Quad::Quad(std::span<glm::vec2> verts, const Uniform &uniform_data) #include <iostream>
: m_mesh(verts) {
memcpy(&m_uniform_data, &uniform_data, sizeof(Uniform)); Quad::Quad(std::span<float> verts, const Uniform &uniform_data)
: m_mesh(verts) {
memcpy(&m_uniform_data, &uniform_data, sizeof(Uniform));
color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
png_uint_32 width = 0, height = 0;
int interlace_type = 0, bit_depth = 0, color_type = 0;
FILE *fp = fopen("./res/tex/util/missing.png", "rb");
png_const_bytep header[8] = {0};
if (fp == NULL) {
std::cerr << "Couldn't find file!" << std::endl;
throw std::exception();
}
fread(header, 1, 8, fp);
png_structp png_ptr =
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
setjmp(png_jmpbuf(png_ptr));
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, 8);
png_read_png(png_ptr, info_ptr,
PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |
PNG_TRANSFORM_EXPAND,
NULL);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL);
setjmp(png_jmpbuf(png_ptr));
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
size_t data_length = rowbytes * height;
png_byte *data = (png_byte *)malloc(data_length);
png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);
for (int x = 0; x < height; x++) {
memcpy(data + (rowbytes * (height - x - 1)), row_pointers[x], rowbytes);
}
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
fclose(fp);
std::cout << color_type << std::endl;
glGenTextures(1, &tex_id);
glBindTexture(GL_TEXTURE_2D, tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} }
glm::vec2 Quad::get_position_vector() { glm::vec2 Quad::get_position_vector() { return glm::vec2(m_pos_x, m_pos_y); }
return glm::vec2(m_pos_x, m_pos_y);
} void Quad::draw(GLFWwindow *w) {
int width, height;
void Quad::draw(GLFWwindow *w){ glfwGetWindowSize(w, &width, &height);
int width, height;
glfwGetWindowSize(w, &width, &height); glm::mat4 translate =
glm::translate(glm::mat4(1.0f), glm::vec3(m_pos_x, m_pos_y, 0.0f));
glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(m_pos_x, m_pos_y, 0.0f)); glm::mat4 rotate =
glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), (float) glfwGetTime() * glm::radians(50.0f), glm::vec3(0.0f, 0.0f, 1.0f)); glm::rotate(glm::mat4(1.0f), (float)glfwGetTime() * glm::radians(50.0f),
glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f)); glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 model = translate * rotate * scale; glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(1.0f));
glm::mat4 view = glm::mat4(1.0f); glm::mat4 model = translate * rotate * scale;
glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f, static_cast<float>(height)); glm::mat4 view = glm::mat4(1.0f);
glm::mat4 mvp = projection * view * model; glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f,
glUniformMatrix4fv(m_uniform_data.mvp, 1, GL_FALSE, glm::value_ptr(mvp)); static_cast<float>(height));
glm::mat4 mvp = projection * view * model;
m_mesh.bindVAO();
glDrawArrays(GL_TRIANGLES, 0, 6); glUniformMatrix4fv(m_uniform_data.mvp, 1, GL_FALSE, glm::value_ptr(mvp));
glUniform4fv(m_uniform_data.color, 1, glm::value_ptr(color));
glBindTexture(GL_TEXTURE_2D, tex_id);
m_mesh.bindVAO();
glDrawArrays(GL_TRIANGLES, 0, 6);
} }

View File

@ -3,23 +3,27 @@
#include "Mesh.hh" #include "Mesh.hh"
#include "src/Uniform.hh" #include "src/Uniform.hh"
#include <GLFW/glfw3.h>
#include <glad/gl.h> #include <glad/gl.h>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <GLFW/glfw3.h>
class Quad { class Quad {
public: public:
Uniform m_uniform_data; Uniform m_uniform_data;
Mesh m_mesh; Mesh m_mesh;
float m_pos_x = 0; float m_pos_x = 0;
float m_pos_y = 0.0f; float m_pos_y = 0.0f;
float m_rotation = 0.0f; float m_rotation = 0.0f;
glm::vec4 color;
Quad(std::span<glm::vec2> verts, const Uniform &uniform_data); Quad(std::span<float> verts, const Uniform &uniform_data);
Quad(Quad &q) = delete; Quad(Quad &q) = delete;
glm::vec2 get_position_vector(); glm::vec2 get_position_vector();
void draw(GLFWwindow *w); void draw(GLFWwindow *w);
private:
GLuint tex_id;
}; };

View File

@ -4,4 +4,6 @@
struct Uniform { struct Uniform {
GLuint mvp; GLuint mvp;
GLuint color;
GLuint texture;
}; };

View File

@ -18,44 +18,33 @@
#define GLAD_GL_IMPLEMENTATION #define GLAD_GL_IMPLEMENTATION
#include <glad/gl.h> #include <glad/gl.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp> #include <glm/ext.hpp>
#include <glm/glm.hpp>
#include <glm/mat2x2.hpp> #include <glm/mat2x2.hpp>
#include <stb/stb_image.h>
static std::vector<Quad *> quads = {}; static std::vector<Quad *> quads = {};
static void dbg_log(const char* str) { static void dbg_log(const char *str) { std::cout << str << std::endl; }
std::cout << str << std::endl;
void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length,
const GLchar *message, const void *userParam) {
fprintf(stderr,
"GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = \n\t%s\n",
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), type, severity,
message);
} }
void GLAPIENTRY static void key_callback(GLFWwindow *w, int key, int scancode, int action,
MessageCallback( GLenum source, int mods) {
GLenum type, if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
GLuint id, glfwSetWindowShouldClose(w, GL_TRUE);
GLenum severity, }
GLsizei length,
const GLchar* message,
const void* userParam )
{
fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = \n\t%s\n",
( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ),
type, severity, message );
} }
static void key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) { static void cursor_position_callback(GLFWwindow *window, double xpos,
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { double ypos) {
glfwSetWindowShouldClose(w, GL_TRUE); int width, height;
}
}
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
int width, height;
glfwGetWindowSize(window, &width, &height);
quads[0]->m_pos_y= height-ypos;
quads[0]->m_pos_x= xpos;
} }
#define VERTEX_SHADER_LOCATION "shaders/shader.vert" #define VERTEX_SHADER_LOCATION "shaders/shader.vert"
@ -63,116 +52,120 @@ static void cursor_position_callback(GLFWwindow* window, double xpos, double ypo
GLuint g_program_id = 0; GLuint g_program_id = 0;
static Uniform uniform_locations; static Uniform uniform_locations;
void framebuffer_size_callback(GLFWwindow* window, int width, int height) void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
{ // make sure the viewport matches the new window dimensions; note that width
// make sure the viewport matches the new window dimensions; note that width and // and height will be significantly larger than specified on retina displays.
// height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height);
glViewport(0, 0, width, height); // Re-render the scene because the current frame was drawn for the old
// Re-render the scene because the current frame was drawn for the old resolution // resolution
} }
static void init_shaders() { static void init_shaders() {
dbg_log("Initialising shaders"); dbg_log("Initialising shaders");
const std::vector<std::pair<GLuint, std::string>> shaders = { const std::vector<std::pair<GLuint, std::string>> shaders = {
{GL_VERTEX_SHADER, VERTEX_SHADER_LOCATION}, {GL_VERTEX_SHADER, VERTEX_SHADER_LOCATION},
{GL_FRAGMENT_SHADER, FRAGMENT_SHADER_LOCATION}, {GL_FRAGMENT_SHADER, FRAGMENT_SHADER_LOCATION},
}; };
try { try {
g_program_id = compile_and_link_program(shaders); g_program_id = compile_and_link_program(shaders);
} catch (GLProgramException e) { } catch (GLProgramException e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
} catch (...) { } catch (...) {
std::cerr << "Unexpected exception while compiling shaders." << std::endl; std::cerr << "Unexpected exception while compiling shaders." << std::endl;
} }
glUseProgram(g_program_id); glUseProgram(g_program_id);
uniform_locations.mvp = glGetUniformLocation(g_program_id, "mvp"); uniform_locations.mvp = glGetUniformLocation(g_program_id, "mvp");
uniform_locations.color = glGetUniformLocation(g_program_id, "color");
uniform_locations.texture = glGetUniformLocation(g_program_id, "texture");
} }
static GLuint vertex_buf[2]; static GLuint vertex_buf[2];
static GLuint array_buf[2]; static GLuint array_buf[2];
static const GLuint vertex_data_position = 0; static const GLuint vertex_data_position = 0;
static std::array<glm::vec2, 6> verts({ static std::array<float, 7 * 6> verts({
// Tri 2 // Tri 2
{0.0f, 0.0f}, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, //
{20.0f, 0.0f}, 200.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, //
{20.0f, 20.0f}, 200.0f, 200.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, //
// Tri 1 // Tri 1
{0.0f, 0.0f}, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, //
{20.0f, 20.0f}, 200.0f, 200.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, // 0000 000
{0.0f, 20.0f}, 0.0f, 200.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f //
}); });
// Do the work of initialising opengl so we can draw stuff // Do the work of initialising opengl so we can draw stuff
static void init_opengl() { static void init_opengl() {
dbg_log("Initialising opengl"); dbg_log("Initialising opengl");
// During init, enable debug output // During init, enable debug output
glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(MessageCallback, 0); glDebugMessageCallback(MessageCallback, 0);
// Configure the context's capabilities // Configure the context's capabilities
glClearColor(0.0, 0.0, 0.0, 1.0); glClearColor(0.0, 1.0, 0.0, 1.0);
init_shaders(); init_shaders();
quads.push_back(new Quad(std::span<glm::vec2>(verts), uniform_locations)); quads.push_back(new Quad(std::span<float>(verts), uniform_locations));
quads[0]->m_pos_y = 40;
quads[0]->m_pos_x = 40;
} }
int main() { int main() {
dbg_log("Initialising glfw"); dbg_log("Initialising glfw");
// Initialise GLFW // Initialise GLFW
if (!glfwInit()) { if (!glfwInit()) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create our context // Create our context
GLFWwindow *w = glfwCreateWindow(640, 480, "Test", NULL, NULL); GLFWwindow *w = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!w) { if (!w) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(w);
glfwSwapInterval(1); // Essentially vsync
gladLoadGL(glfwGetProcAddress); // Load openGL using glfw
// Set up the key handler
glfwSetKeyCallback(w, key_callback);
glfwSetFramebufferSizeCallback(w, framebuffer_size_callback);
glfwSetCursorPosCallback(w, cursor_position_callback);
init_opengl();
// Main Loop
while(!glfwWindowShouldClose(w)) {
glClear(GL_COLOR_BUFFER_BIT);
for(auto q : quads) {
q->draw(w);
}
glfwSwapBuffers(w);
glfwPollEvents();
}
for(auto q: quads) {
delete(q);
}
glfwDestroyWindow(w);
#ifndef DEBUG
glfwTerminate(); glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(w);
glfwSwapInterval(1); // Essentially vsync
gladLoadGL(glfwGetProcAddress); // Load openGL using glfw
// Set up the key handler
glfwSetKeyCallback(w, key_callback);
glfwSetFramebufferSizeCallback(w, framebuffer_size_callback);
glfwSetCursorPosCallback(w, cursor_position_callback);
init_opengl();
// Main Loop
while (!glfwWindowShouldClose(w)) {
glClear(GL_COLOR_BUFFER_BIT);
for (auto q : quads) {
q->draw(w);
}
glfwSwapBuffers(w);
glfwPollEvents();
}
for (auto q : quads) {
delete (q);
}
glfwDestroyWindow(w);
#ifndef DEBUG
glfwTerminate();
#endif #endif
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }

View File

@ -1,8 +1,13 @@
#version 430 core #version 430 core
in vec4 unif_color;
in vec2 tex_coord;
out vec4 f_color; out vec4 f_color;
// All fragments are the same colour for now. uniform sampler2D u_texture;
void main() { void main() {
f_color = vec4(1.0, 1.0, 1.0, 1.0); vec4 texcolor = texture(u_texture, tex_coord);
} f_color = texcolor;
}

View File

@ -1,9 +1,17 @@
#version 430 core #version 430 core
layout (location = 0) in vec3 v_position; layout (location = 0) in vec3 v_position;
layout (location = 1) in vec3 v_colour;
layout (location = 2) in vec2 v_tex_coord;
uniform mat4 mvp; uniform mat4 mvp;
uniform vec4 color;
out vec4 unif_color;
out vec2 tex_coord;
// Simple passthrough shader for now. // Simple passthrough shader for now.
void main() { void main() {
unif_color = color;
tex_coord = v_tex_coord;
gl_Position = mvp * vec4(v_position, 1.0); gl_Position = mvp * vec4(v_position, 1.0);
} }

View File

@ -1,2 +0,0 @@
#define STB_IMAGE_IMPLEMENTATION
#include <stb/stb_image.h>