From 708b6e523d7f57f4eb4eb8395530be9ddf67986a Mon Sep 17 00:00:00 2001 From: talha Date: Thu, 25 Apr 2024 03:19:05 +0500 Subject: Added freetype, started refactoring --- source/main.cpp | 704 ++++++++++++++------------------------------------------ 1 file changed, 167 insertions(+), 537 deletions(-) (limited to 'source/main.cpp') diff --git a/source/main.cpp b/source/main.cpp index a9e5c81..7deb893 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -2,14 +2,14 @@ #include #include #include -#include -#include -#include #include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" +#include +#include FT_FREETYPE_H + /* @lookup: * - understand kernals, how they work and how they affect post processing * - Check to see why it is necessary to do glBindTexture() @@ -50,6 +50,31 @@ typedef u8 b8; // =========== Shader Loading ============= +enum Texture_Filtering { TF_NEAREST, TF_LINEAR }; + +struct GlTexturedQuad { + u32 vao; + u32 vbo; + u32 texture_id; +}; + +struct GlShader { + u32 id; + s32 model_loc; + s32 view_loc; + s32 proj_loc; +}; + +void gl_shader_load_locations(GlShader *shader) +{ + glUseProgram(shader->id); + shader->model_loc = glGetUniformLocation(shader->id, "Model"); + shader->view_loc = glGetUniformLocation(shader->id, "View"); + shader->proj_loc = glGetUniformLocation(shader->id, "Projection"); + + return; +} + unsigned int gl_create_vertex_shader(char* vertex_shader_source) { unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER); @@ -121,36 +146,25 @@ unsigned int gl_shader_program(char* vertex_shader_source, char* fragment_shader return shader_program; } -Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up) +u32 gl_shader_program_from_path(char* vs_path, char* fs_path) { - // @note: We do this because this allows the camera to have the axis it looks at - // inwards be the +z axis. - // If we did not do this, then the inward axis the camera looks at would be negative. - // I am still learning from learnopengl.com but I imagine that this was done for conveniences' sake. - Vec3 camera_forward_dir = normalize3v(subtract3v(camera_pos, camera_look)); - Vec3 camera_right_dir = normalize3v(cross_multiply3v(camera_up, camera_forward_dir)); - Vec3 camera_up_dir = normalize3v(cross_multiply3v(camera_forward_dir, camera_right_dir)); - - Mat4 res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos); - - return res; -} + // @todo: add failure handling here + // what to do if we fail to read the shaders + size_t read_count; + char* vs = (char*)SDL_LoadFile(vs_path, &read_count); + char* fs = (char*)SDL_LoadFile(fs_path, &read_count); -Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw) -{ - Vec3 camera_look = {0.0}; - camera_look.x = cosf(angle_yaw) * cosf(angle_pitch); - camera_look.y = sinf(angle_pitch); - camera_look.z = sinf(angle_yaw) * cosf(angle_pitch); - camera_look = normalize3v(camera_look); - - return camera_look; + u32 shader_program = gl_shader_program(vs, fs); + + return shader_program; } -s32 gl_load_texture(u32 texture_id, const char* path) +s32 gl_load_texture(u32 texture_id, char *path, enum Texture_Filtering filter) { s32 width, height, nrChannels; + stbi_set_flip_vertically_on_load(1); unsigned char *data = stbi_load(path, &width, &height, &nrChannels, 0); + stbi_set_flip_vertically_on_load(0); if (data) { GLenum format; @@ -167,431 +181,137 @@ s32 gl_load_texture(u32 texture_id, const char* path) 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); - stbi_image_free(data); - } - else - { - printf("failed to load image texture at path: %s", path); - stbi_image_free(data); - } - - return texture_id; -} - -// =================== Model Loading ======================== -// This section contains a whole host of things: -// 1. classes -// 2. std::vectors -// 3. std::strings -// that I have only used as a glue for I did not know if I had the model loading setup properly. -// @todo: replace these things eventually. For now the goal is to complete learnopengl - -s32 TextureFromFile(const char* filepath, std::string directory) -{ - // @note: this function is stupid as it already became outdated as I needed to tweak the parameters - // for wrapping. Either those become function parameters (Which makes sense I guess) or I look at - // exactly what steps I am reusing and just make that a function so the function is called fewer times. - // - // I am guessing this won't look good from a design point of view for all those jobs and postings, even if - // this may be the simpler and faster thing to do, albeit at the cost of typing. - std::string filename = std::string(filepath); - filename = directory + '/' + filename; - - u32 texid; - glGenTextures(1, &texid); - - s32 width, height, nrChannels; - unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrChannels, 0); - if (data) - { - GLenum format; - if (nrChannels == 1) - format = GL_RED; - else if (nrChannels == 3) - format = GL_RGB; - else if (nrChannels == 4) - format = GL_RGBA; - - glBindTexture(GL_TEXTURE_2D, texid); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - - 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); - - stbi_image_free(data); - } - else - { - printf("failed to load image texture at path: %s", filepath); - stbi_image_free(data); - } - - return texid; -} - -enum TextureType { TextureDiffuse=0, TextureSpecular }; -struct Vertex { - Vec3 position; - Vec3 normal; - Vec2 texture; -}; - -struct Texture { - u32 id; - enum TextureType type; - std::string fname; -}; - -class Mesh { - public: - std::vector vertices; - std::vector indices; - std::vector textures; - - u32 vao; - u32 vbo; - u32 ebo; - - Mesh(std::vector vertices, std::vector indices, std::vector textures) - { - this->vertices = vertices; - this->indices = indices; - this->textures = textures; - - // setup mesh shader stuff - glGenVertexArrays(1, &vao); - glGenBuffers(1, &vbo); - glGenBuffers(1, &ebo); - - glBindVertexArray(vao); - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(struct Vertex), &(this->vertices[0]), GL_STATIC_DRAW); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(u32), &(this->indices[0]), GL_STATIC_DRAW); - - // position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); - // normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal)); - // texture - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, texture)); - - glBindVertexArray(0); - } - - void draw(u32 shader_program) - { - glUseProgram(shader_program); + u32 min_filter; + u32 max_filter; - u32 diffuse_num = 1; - u32 specular_num = 1; - char tex_unit_name[64]; - // set shininess - s32 mat_shine_loc = glGetUniformLocation(shader_program, "material.shininess"); - glUniform1f(mat_shine_loc, 32.0f); - - for (u32 i=0; i loaded_textures; - std::vector meshes; - std::string directory; - - Model(std::string path) - { - load_model(path); - } - void instance_mesh(); - void draw(u32 shader_program); - void draw_instanced(u32 shader_program, u32 instance_count); - private: - void load_model(std::string path); - void process_node(aiNode *node, const aiScene *scene); - Mesh process_mesh(aiMesh *mesh, const aiScene *scene); - std::vector load_material_textures(aiMaterial *mat, aiTextureType type, TextureType type_name); -}; - -void Model::instance_mesh() -{ - for (u32 i=0; i < meshes.size(); i++) + else { - Mesh curr_mesh = meshes[i]; - glBindVertexArray(curr_mesh.vao); - glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)0); - glEnableVertexAttribArray(3); - - glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(4*sizeof(u32))); - glEnableVertexAttribArray(4); - - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(8*sizeof(u32))); - glEnableVertexAttribArray(5); - - glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 16 * sizeof(u32), (void*)(12*sizeof(u32))); - glEnableVertexAttribArray(6); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glVertexAttribDivisor(3, 1); - glVertexAttribDivisor(4, 1); - glVertexAttribDivisor(5, 1); - glVertexAttribDivisor(6, 1); - - glBindVertexArray(0); + // @todo: logging + printf("failed to load image texture at path: %s", path); + stbi_image_free(data); + return -1; } + + return 0; } -void Model::draw(u32 shader_program) +GlTexturedQuad gl_setup_textured_quad(char* texture_path, enum Texture_Filtering filter) { - for (int i=0; i < meshes.size(); i++) - { - meshes[i].draw(shader_program); - } + // rendering is clock-wise + r32 quad_vertices[] = { + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom-right + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top-right + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // top-left + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom-left + }; + u32 vao, vbo, tex_id; + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertices), &quad_vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(r32), (void*)(3*sizeof(r32))); + glBindVertexArray(0); + + glGenTextures(1, &tex_id); + glActiveTexture(GL_TEXTURE0); + gl_load_texture(tex_id, texture_path, filter); + + GlTexturedQuad tex_quad; + tex_quad.vao = vao; + tex_quad.vbo = vbo; + tex_quad.texture_id = tex_id; + + return tex_quad; } -void Model::draw_instanced(u32 shader_program, u32 instance_count) +void gl_draw_tex_quad(u32 shader_program, GlTexturedQuad tex_quad) { - for (int i=0; i < meshes.size(); i++) - { - meshes[i].draw_instanced(shader_program, instance_count); - } + glUseProgram(shader_program); + s32 tex_id_loc = glGetUniformLocation(shader_program, "Texture"); + glUniform1i(tex_id_loc, 0); + glBindVertexArray(tex_quad.vao); + glBindTexture(GL_TEXTURE_2D, tex_quad.texture_id); + glDrawArrays(GL_TRIANGLES, 0, 6); } -void Model::load_model(std::string path) +// =============== CAMERA STUFF ================= +// @note: Be sure to update and refactor the camera +Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up) { - Assimp::Importer import; - const aiScene *scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - printf("error loading model :%s\n", import.GetErrorString()); - return; - } - - directory = path.substr(0, path.find_last_of('/')); - process_node(scene->mRootNode, scene); + // @note: We do this because this allows the camera to have the axis it looks at + // inwards be the +z axis. + // If we did not do this, then the inward axis the camera looks at would be negative. + // I am still learning from learnopengl.com but I imagine that this was done for conveniences' sake. + Vec3 camera_forward_dir = normalize3v(subtract3v(camera_pos, camera_look)); + Vec3 camera_right_dir = normalize3v(cross_multiply3v(camera_up, camera_forward_dir)); + Vec3 camera_up_dir = normalize3v(cross_multiply3v(camera_forward_dir, camera_right_dir)); + + Mat4 res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos); + + return res; } -void Model::process_node(aiNode *node, const aiScene *scene) +Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw) { - for (int i=0; i < node->mNumMeshes; i++) - { - aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; - meshes.push_back(process_mesh(mesh, scene)); - } - - for (int i=0; imNumChildren; i++) - { - process_node(node->mChildren[i], scene); - } + Vec3 camera_look = {0.0}; + camera_look.x = cosf(angle_yaw) * cosf(angle_pitch); + camera_look.y = sinf(angle_pitch); + camera_look.z = sinf(angle_yaw) * cosf(angle_pitch); + camera_look = normalize3v(camera_look); + + return camera_look; } -Mesh Model::process_mesh(aiMesh *mesh, const aiScene *scene) +int main(int argc, char* argv[]) { - std::vector vertices; - std::vector indices; - std::vector textures; - - for (u32 i=0; i < mesh->mNumVertices; i++) - { - Vec3 position; - position.x = mesh->mVertices[i].x; - position.y = mesh->mVertices[i].y; - position.z = mesh->mVertices[i].z; - - Vec3 normal; - normal.x = mesh->mNormals[i].x; - normal.y = mesh->mNormals[i].y; - normal.z = mesh->mNormals[i].z; - - Vec2 texture = {0, 0}; - if (mesh->mTextureCoords[0]) - { - texture.x = mesh->mTextureCoords[0][i].x; - texture.y = mesh->mTextureCoords[0][i].y; - } - struct Vertex vertex; - vertex.position = position; - vertex.normal = normal; - vertex.texture = texture; + // Load freetype + FT_Library library; + FT_Face face; - vertices.push_back(vertex); - } - // process indices - for (u32 i = 0; i < mesh->mNumFaces; i++) + if (FT_Init_FreeType(&library)) { - aiFace face = mesh->mFaces[i]; - for(u32 j = 0; j < face.mNumIndices; j++) - { - indices.push_back(face.mIndices[j]); - } + printf("Error: Could not init freetype library\n"); + return -1; } - // process material - if (mesh->mMaterialIndex >= 0) + + FT_Error error = FT_New_Face(library, "assets/fonts/Arial.ttf", 0, &face); + if (error == FT_Err_Unknown_File_Format) { - aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; - std::vector diffuse_maps = load_material_textures(material, aiTextureType_DIFFUSE, TextureDiffuse); - textures.insert(textures.end(), diffuse_maps.begin(), diffuse_maps.end()); - std::vector specular_maps = load_material_textures(material, aiTextureType_SPECULAR, TextureSpecular); - textures.insert(textures.end(), specular_maps.begin(), specular_maps.end()); + printf("Error: Font Loading Failed. The font format is unsupported.\n"); + return -1; } - - return Mesh(vertices, indices, textures); -} - -std::vector Model::load_material_textures(aiMaterial *mat, aiTextureType type, TextureType tex_type) -{ - std::vector textures; - for(u32 i=0; iGetTextureCount(type); i++) + else if (error) { - bool load_texture = true; - aiString str; - mat->GetTexture(type, i, &str); - const char* fname = str.C_Str(); - - for (s32 j=0; j