├── .gitattributes ├── .gitignore ├── .gitmodules ├── Build └── .gitignore ├── CMakeLists.txt ├── Glitter ├── Headers │ └── glitter.hpp ├── Shaders │ └── .gitignore └── Sources │ └── main.cpp ├── Readme.md └── Samples ├── mesh.cpp ├── mesh.hpp ├── readme.md ├── shader.cpp └── shader.hpp /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Bb]uild/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Glitter/Vendor/assimp"] 2 | path = Glitter/Vendor/assimp 3 | url = https://github.com/assimp/assimp.git 4 | branch = master 5 | [submodule "Glitter/Vendor/glad"] 6 | path = Glitter/Vendor/glad 7 | url = https://github.com/Dav1dde/glad.git 8 | branch = c 9 | [submodule "Glitter/Vendor/glfw"] 10 | path = Glitter/Vendor/glfw 11 | url = https://github.com/glfw/glfw.git 12 | branch = master 13 | [submodule "Glitter/Vendor/glm"] 14 | path = Glitter/Vendor/glm 15 | url = https://github.com/g-truc/glm.git 16 | branch = master 17 | [submodule "Glitter/Vendor/stb"] 18 | path = Glitter/Vendor/stb 19 | url = https://github.com/nothings/stb.git 20 | branch = master 21 | [submodule "Glitter/Vendor/bullet"] 22 | path = Glitter/Vendor/bullet 23 | url = https://github.com/bulletphysics/bullet3.git 24 | branch = master 25 | -------------------------------------------------------------------------------- /Build/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polytonic/Glitter/d7c3d5d3a6aebf18b441b14f93fb0e159480d5d7/Build/.gitignore -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | project(Glitter) 3 | 4 | option(GLFW_BUILD_DOCS OFF) 5 | option(GLFW_BUILD_EXAMPLES OFF) 6 | option(GLFW_BUILD_TESTS OFF) 7 | add_subdirectory(Glitter/Vendor/glfw) 8 | 9 | option(ASSIMP_BUILD_ASSIMP_TOOLS OFF) 10 | option(ASSIMP_BUILD_SAMPLES OFF) 11 | option(ASSIMP_BUILD_TESTS OFF) 12 | add_subdirectory(Glitter/Vendor/assimp) 13 | 14 | option(BUILD_BULLET2_DEMOS OFF) 15 | option(BUILD_CPU_DEMOS OFF) 16 | option(BUILD_EXTRAS OFF) 17 | option(BUILD_OPENGL3_DEMOS OFF) 18 | option(BUILD_UNIT_TESTS OFF) 19 | add_subdirectory(Glitter/Vendor/bullet) 20 | 21 | if(MSVC) 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") 23 | else() 24 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -std=c++11") 25 | if(NOT WIN32) 26 | set(GLAD_LIBRARIES dl) 27 | endif() 28 | endif() 29 | 30 | include_directories(Glitter/Headers/ 31 | Glitter/Vendor/assimp/include/ 32 | Glitter/Vendor/bullet/src/ 33 | Glitter/Vendor/glad/include/ 34 | Glitter/Vendor/glfw/include/ 35 | Glitter/Vendor/glm/ 36 | Glitter/Vendor/stb/) 37 | 38 | file(GLOB VENDORS_SOURCES Glitter/Vendor/glad/src/glad.c) 39 | file(GLOB PROJECT_HEADERS Glitter/Headers/*.hpp) 40 | file(GLOB PROJECT_SOURCES Glitter/Sources/*.cpp) 41 | file(GLOB PROJECT_SHADERS Glitter/Shaders/*.comp 42 | Glitter/Shaders/*.frag 43 | Glitter/Shaders/*.geom 44 | Glitter/Shaders/*.vert) 45 | file(GLOB PROJECT_CONFIGS CMakeLists.txt 46 | Readme.md 47 | .gitattributes 48 | .gitignore 49 | .gitmodules) 50 | 51 | source_group("Headers" FILES ${PROJECT_HEADERS}) 52 | source_group("Shaders" FILES ${PROJECT_SHADERS}) 53 | source_group("Sources" FILES ${PROJECT_SOURCES}) 54 | source_group("Vendors" FILES ${VENDORS_SOURCES}) 55 | 56 | add_definitions(-DGLFW_INCLUDE_NONE 57 | -DPROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\") 58 | add_executable(${PROJECT_NAME} ${PROJECT_SOURCES} ${PROJECT_HEADERS} 59 | ${PROJECT_SHADERS} ${PROJECT_CONFIGS} 60 | ${VENDORS_SOURCES}) 61 | target_link_libraries(${PROJECT_NAME} assimp glfw 62 | ${GLFW_LIBRARIES} ${GLAD_LIBRARIES} 63 | BulletDynamics BulletCollision LinearMath) 64 | set_target_properties(${PROJECT_NAME} PROPERTIES 65 | RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PROJECT_NAME}) 66 | 67 | add_custom_command( 68 | TARGET ${PROJECT_NAME} POST_BUILD 69 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Glitter/Shaders $ 70 | DEPENDS ${PROJECT_SHADERS}) 71 | -------------------------------------------------------------------------------- /Glitter/Headers/glitter.hpp: -------------------------------------------------------------------------------- 1 | // Preprocessor Directives 2 | #ifndef GLITTER 3 | #define GLITTER 4 | #pragma once 5 | 6 | // System Headers 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // Reference: https://github.com/nothings/stb/blob/master/stb_image.h#L4 16 | // To use stb_image, add this in *one* C++ source file. 17 | // #define STB_IMAGE_IMPLEMENTATION 18 | #include 19 | 20 | // Define Some Constants 21 | const int mWidth = 1280; 22 | const int mHeight = 800; 23 | 24 | #endif //~ Glitter Header 25 | -------------------------------------------------------------------------------- /Glitter/Shaders/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Polytonic/Glitter/d7c3d5d3a6aebf18b441b14f93fb0e159480d5d7/Glitter/Shaders/.gitignore -------------------------------------------------------------------------------- /Glitter/Sources/main.cpp: -------------------------------------------------------------------------------- 1 | // Local Headers 2 | #include "glitter.hpp" 3 | 4 | // System Headers 5 | #include 6 | #include 7 | 8 | // Standard Headers 9 | #include 10 | #include 11 | 12 | int main(int argc, char * argv[]) { 13 | 14 | // Load GLFW and Create a Window 15 | glfwInit(); 16 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 17 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 18 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 19 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 20 | glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 21 | auto mWindow = glfwCreateWindow(mWidth, mHeight, "OpenGL", nullptr, nullptr); 22 | 23 | // Check for Valid Context 24 | if (mWindow == nullptr) { 25 | fprintf(stderr, "Failed to Create OpenGL Context"); 26 | return EXIT_FAILURE; 27 | } 28 | 29 | // Create Context and Load OpenGL Functions 30 | glfwMakeContextCurrent(mWindow); 31 | gladLoadGL(); 32 | fprintf(stderr, "OpenGL %s\n", glGetString(GL_VERSION)); 33 | 34 | // Rendering Loop 35 | while (glfwWindowShouldClose(mWindow) == false) { 36 | if (glfwGetKey(mWindow, GLFW_KEY_ESCAPE) == GLFW_PRESS) 37 | glfwSetWindowShouldClose(mWindow, true); 38 | 39 | // Background Fill Color 40 | glClearColor(0.25f, 0.25f, 0.25f, 1.0f); 41 | glClear(GL_COLOR_BUFFER_BIT); 42 | 43 | // Flip Buffers and Draw 44 | glfwSwapBuffers(mWindow); 45 | glfwPollEvents(); 46 | } glfwTerminate(); 47 | return EXIT_SUCCESS; 48 | } 49 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # [Glitter](http://polytonic.github.io/Glitter/) 2 | ![Screenshot](http://i.imgur.com/MDo2rsy.jpg) 3 | 4 | ## Summary 5 | Glitter is a dead simple boilerplate for OpenGL, intended as a starting point for the tutorials on [learnopengl.com](http://www.learnopengl.com) and [open.gl](https://open.gl). Glitter compiles and statically links every required library, so you can jump right into doing what you probably want: how to get started with OpenGL. 6 | 7 | ## Getting Started 8 | Glitter has a single dependency: [cmake](http://www.cmake.org/download/), which is used to generate platform-specific makefiles or project files. Start by cloning this repository, making sure to pass the `--recursive` flag to grab all the dependencies. If you forgot, then you can `git submodule update --init` instead. 9 | 10 | ```bash 11 | git clone --recursive https://github.com/Polytonic/Glitter 12 | cd Glitter 13 | cd Build 14 | ``` 15 | 16 | Now generate a project file or makefile for your platform. If you want to use a particular IDE, make sure it is installed; don't forget to set the Start-Up Project in Visual Studio or the Target in Xcode. 17 | 18 | ```bash 19 | # UNIX Makefile 20 | cmake .. 21 | 22 | # Mac OSX 23 | cmake -G "Xcode" .. 24 | 25 | # Microsoft Windows 26 | cmake -G "Visual Studio 14" .. 27 | cmake -G "Visual Studio 14 Win64" .. 28 | ... 29 | ``` 30 | 31 | If you compile and run, you should now be at the same point as the [Hello Window](http://www.learnopengl.com/#!Getting-started/Hello-Window) or [Context Creation](https://open.gl/context) sections of the tutorials. Open [main.cpp](https://github.com/Polytonic/Glitter/blob/master/Glitter/Sources/main.cpp) on your computer and start writing code! 32 | 33 | ## Documentation 34 | Many people overlook how frustrating it is to install dependencies, especially in environments lacking package managers or administrative privileges. For beginners, just getting set up properly set up can be a huge challenge. Glitter is meant to help you overcome that roadblock. 35 | 36 | Glitter provides the most basic windowing example. It is a starting point, and tries very hard not to enforce any sort of directory structure. Feel free to edit the include paths in `CMakeLists.txt`. Glitter bundles most of the dependencies needed to implement a basic rendering engine. This includes: 37 | 38 | Functionality | Library 39 | ----------------------- | ------------------------------------------ 40 | Mesh Loading | [assimp](https://github.com/assimp/assimp) 41 | Physics | [bullet](https://github.com/bulletphysics/bullet3) 42 | OpenGL Function Loader | [glad](https://github.com/Dav1dde/glad) 43 | Windowing and Input | [glfw](https://github.com/glfw/glfw) 44 | OpenGL Mathematics | [glm](https://github.com/g-truc/glm) 45 | Texture Loading | [stb](https://github.com/nothings/stb) 46 | 47 | If you started the tutorials by installing [SDL](https://www.libsdl.org/), [GLEW](https://github.com/nigels-com/glew), or [SOIL](http://www.lonesock.net/soil.html), *stop*. The libraries bundled with Glitter supersede or are functional replacements for these libraries. 48 | 49 | I have provided sample implementations of an intrusive tree mesh and shader class, if you're following along with the tutorials and need another reference point. These were used to generate the screenshot above, but will not compile out-of-the-box. I leave that exercise for the reader. :smiley: 50 | 51 | ## License 52 | >The MIT License (MIT) 53 | 54 | >Copyright (c) 2015 Kevin Fung 55 | 56 | >Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 57 | 58 | >The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 59 | 60 | >THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | -------------------------------------------------------------------------------- /Samples/mesh.cpp: -------------------------------------------------------------------------------- 1 | // Preprocessor Directives 2 | #define STB_IMAGE_IMPLEMENTATION 3 | 4 | // Local Headers 5 | #include "mesh.hpp" 6 | 7 | // System Headers 8 | #include 9 | 10 | // Define Namespace 11 | namespace Mirage 12 | { 13 | Mesh::Mesh(std::string const & filename) : Mesh() 14 | { 15 | // Load a Model from File 16 | Assimp::Importer loader; 17 | aiScene const * scene = loader.ReadFile( 18 | PROJECT_SOURCE_DIR "/Mirage/Models/" + filename, 19 | aiProcessPreset_TargetRealtime_MaxQuality | 20 | aiProcess_OptimizeGraph | 21 | aiProcess_FlipUVs); 22 | 23 | // Walk the Tree of Scene Nodes 24 | auto index = filename.find_last_of("/"); 25 | if (!scene) fprintf(stderr, "%s\n", loader.GetErrorString()); 26 | else parse(filename.substr(0, index), scene->mRootNode, scene); 27 | } 28 | 29 | Mesh::Mesh(std::vector const & vertices, 30 | std::vector const & indices, 31 | std::map const & textures) 32 | : mIndices(indices) 33 | , mVertices(vertices) 34 | , mTextures(textures) 35 | { 36 | // Bind a Vertex Array Object 37 | glGenVertexArrays(1, & mVertexArray); 38 | glBindVertexArray(mVertexArray); 39 | 40 | // Copy Vertex Buffer Data 41 | glGenBuffers(1, & mVertexBuffer); 42 | glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer); 43 | glBufferData(GL_ARRAY_BUFFER, 44 | mVertices.size() * sizeof(Vertex), 45 | & mVertices.front(), GL_STATIC_DRAW); 46 | 47 | // Copy Index Buffer Data 48 | glGenBuffers(1, & mElementBuffer); 49 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer); 50 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, 51 | mIndices.size() * sizeof(GLuint), 52 | & mIndices.front(), GL_STATIC_DRAW); 53 | 54 | // Set Shader Attributes 55 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *) offsetof(Vertex, position)); 56 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *) offsetof(Vertex, normal)); 57 | glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid *) offsetof(Vertex, uv)); 58 | glEnableVertexAttribArray(0); // Vertex Positions 59 | glEnableVertexAttribArray(1); // Vertex Normals 60 | glEnableVertexAttribArray(2); // Vertex UVs 61 | 62 | // Cleanup Buffers 63 | glBindVertexArray(0); 64 | glDeleteBuffers(1, & mVertexBuffer); 65 | glDeleteBuffers(1, & mElementBuffer); 66 | } 67 | 68 | void Mesh::draw(GLuint shader) 69 | { 70 | unsigned int unit = 0, diffuse = 0, specular = 0; 71 | for (auto &i : mSubMeshes) i->draw(shader); 72 | for (auto &i : mTextures) 73 | { // Set Correct Uniform Names Using Texture Type (Omit ID for 0th Texture) 74 | std::string uniform = i.second; 75 | if (i.second == "diffuse") uniform += (diffuse++ > 0) ? std::to_string(diffuse) : ""; 76 | else if (i.second == "specular") uniform += (specular++ > 0) ? std::to_string(specular) : ""; 77 | 78 | // Bind Correct Textures and Vertex Array Before Drawing 79 | glActiveTexture(GL_TEXTURE0 + unit); 80 | glBindTexture(GL_TEXTURE_2D, i.first); 81 | glUniform1f(glGetUniformLocation(shader, uniform.c_str()), ++unit); 82 | } glBindVertexArray(mVertexArray); 83 | glDrawElements(GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, 0); 84 | } 85 | 86 | void Mesh::parse(std::string const & path, aiNode const * node, aiScene const * scene) 87 | { 88 | for (unsigned int i = 0; i < node->mNumMeshes; i++) 89 | parse(path, scene->mMeshes[node->mMeshes[i]], scene); 90 | for (unsigned int i = 0; i < node->mNumChildren; i++) 91 | parse(path, node->mChildren[i], scene); 92 | } 93 | 94 | void Mesh::parse(std::string const & path, aiMesh const * mesh, aiScene const * scene) 95 | { 96 | // Create Vertex Data from Mesh Node 97 | std::vector vertices; Vertex vertex; 98 | for (unsigned int i = 0; i < mesh->mNumVertices; i++) 99 | { if (mesh->mTextureCoords[0]) 100 | vertex.uv = glm::vec2(mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y); 101 | vertex.position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z); 102 | vertex.normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z); 103 | vertices.push_back(vertex); 104 | } 105 | 106 | // Create Mesh Indices for Indexed Drawing 107 | std::vector indices; 108 | for (unsigned int i = 0; i < mesh->mNumFaces; i++) 109 | for (unsigned int j = 0; j < mesh->mFaces[i].mNumIndices; j++) 110 | indices.push_back(mesh->mFaces[i].mIndices[j]); 111 | 112 | // Load Mesh Textures into VRAM 113 | std::map textures; 114 | auto diffuse = process(path, scene->mMaterials[mesh->mMaterialIndex], aiTextureType_DIFFUSE); 115 | auto specular = process(path, scene->mMaterials[mesh->mMaterialIndex], aiTextureType_SPECULAR); 116 | textures.insert(diffuse.begin(), diffuse.end()); 117 | textures.insert(specular.begin(), specular.end()); 118 | 119 | // Create New Mesh Node 120 | mSubMeshes.push_back(std::unique_ptr(new Mesh(vertices, indices, textures))); 121 | } 122 | 123 | std::map Mesh::process(std::string const & path, 124 | aiMaterial * material, 125 | aiTextureType type) 126 | { 127 | std::map textures; 128 | for(unsigned int i = 0; i < material->GetTextureCount(type); i++) 129 | { 130 | // Define Some Local Variables 131 | GLenum format; 132 | GLuint texture; 133 | std::string mode; 134 | 135 | // Load the Texture Image from File 136 | aiString str; material->GetTexture(type, i, & str); 137 | std::string filename = str.C_Str(); int width, height, channels; 138 | filename = PROJECT_SOURCE_DIR "/Mirage/Models/" + path + "/" + filename; 139 | unsigned char * image = stbi_load(filename.c_str(), & width, & height, & channels, 0); 140 | if (!image) fprintf(stderr, "%s %s\n", "Failed to Load Texture", filename.c_str()); 141 | 142 | // Set the Correct Channel Format 143 | switch (channels) 144 | { 145 | case 1 : format = GL_ALPHA; break; 146 | case 2 : format = GL_LUMINANCE; break; 147 | case 3 : format = GL_RGB; break; 148 | case 4 : format = GL_RGBA; break; 149 | } 150 | 151 | // Bind Texture and Set Filtering Levels 152 | glGenTextures(1, & texture); 153 | glBindTexture(GL_TEXTURE_2D, texture); 154 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 155 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 156 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 157 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 158 | glTexImage2D(GL_TEXTURE_2D, 0, format, 159 | width, height, 0, format, GL_UNSIGNED_BYTE, image); 160 | glGenerateMipmap(GL_TEXTURE_2D); 161 | 162 | // Release Image Pointer and Store the Texture 163 | stbi_image_free(image); 164 | if (type == aiTextureType_DIFFUSE) mode = "diffuse"; 165 | else if (type == aiTextureType_SPECULAR) mode = "specular"; 166 | textures.insert(std::make_pair(texture, mode)); 167 | } return textures; 168 | } 169 | }; 170 | -------------------------------------------------------------------------------- /Samples/mesh.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // System Headers 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Standard Headers 11 | #include 12 | #include 13 | #include 14 | 15 | // Define Namespace 16 | namespace Mirage 17 | { 18 | // Vertex Format 19 | struct Vertex { 20 | glm::vec3 position; 21 | glm::vec3 normal; 22 | glm::vec2 uv; 23 | }; 24 | 25 | class Mesh 26 | { 27 | public: 28 | 29 | // Implement Default Constructor and Destructor 30 | Mesh() { glGenVertexArrays(1, & mVertexArray); } 31 | ~Mesh() { glDeleteVertexArrays(1, & mVertexArray); } 32 | 33 | // Implement Custom Constructors 34 | Mesh(std::string const & filename); 35 | Mesh(std::vector const & vertices, 36 | std::vector const & indices, 37 | std::map const & textures); 38 | 39 | // Public Member Functions 40 | void draw(GLuint shader); 41 | 42 | private: 43 | 44 | // Disable Copying and Assignment 45 | Mesh(Mesh const &) = delete; 46 | Mesh & operator=(Mesh const &) = delete; 47 | 48 | // Private Member Functions 49 | void parse(std::string const & path, aiNode const * node, aiScene const * scene); 50 | void parse(std::string const & path, aiMesh const * mesh, aiScene const * scene); 51 | std::map process(std::string const & path, 52 | aiMaterial * material, 53 | aiTextureType type); 54 | 55 | // Private Member Containers 56 | std::vector> mSubMeshes; 57 | std::vector mIndices; 58 | std::vector mVertices; 59 | std::map mTextures; 60 | 61 | // Private Member Variables 62 | GLuint mVertexArray; 63 | GLuint mVertexBuffer; 64 | GLuint mElementBuffer; 65 | 66 | }; 67 | }; 68 | -------------------------------------------------------------------------------- /Samples/readme.md: -------------------------------------------------------------------------------- 1 | # [Glitter](https://github.com/Polytonic/Glitter/) :: [Samples](https://github.com/Polytonic/Glitter/tree/master/Samples) 2 | 3 | If you're new to OpenGL, it's almost a rite of passage to write your own shader class and model loader. To help you out, I ripped these directly from my own renderer (`Mirage`), so you'll see a bunch of references to it in this sample code. I wrote this when I was still in college, so there are *definitely* some warts in my code. 4 | 5 | ### Shader 6 | 7 | If you're following along with a tutorial, you'll want to read through this one first. The [shader class](https://github.com/Polytonic/Glitter/blob/master/Samples/shader.hpp) covers how to load a GLSL shader source file and turn it into a usable OpenGL shader object. I wrote it in a fashion that allows you to "chain" attach calls, like in JavaScript. 8 | 9 | ```cpp 10 | Shader shader; 11 | shader.attach("main.vert") 12 | .attach("main.frag") 13 | ... // and so on ... 14 | ``` 15 | 16 | There is some basic error handling to help you out if you get stuck. 17 | 18 | ### Mesh 19 | 20 | Model loading is a bit harder. Most standard models are actually comprised of multiple, "sub-models" (or sub-meshes). For example, a character model in a video game might have a "torso" section, a "left arm" and a "right arm" section, and so on, all inside the same model file. Here I provide a sample [mesh class](https://github.com/Polytonic/Glitter/blob/master/Samples/mesh.hpp) that will handle multi-meshes; the screenshot on the main page is one of them! 21 | 22 | Most OpenGL tutorials will guide you through writing a standard "Mesh" class, which involves writing a standard tree containing a set of nodes. This entails a containing "tree" class, and a "node" class containing data. As an alternative, I wrote an intrusive tree implementation, which stores the tree relation directly inside the nodes. This [Quora post](http://qr.ae/RFzeSU) might be helpful in understanding what an intrusive data structure is, and why they are used. 23 | -------------------------------------------------------------------------------- /Samples/shader.cpp: -------------------------------------------------------------------------------- 1 | // Local Headers 2 | #include "shader.hpp" 3 | 4 | // Standard Headers 5 | #include 6 | #include 7 | #include 8 | 9 | // Define Namespace 10 | namespace Mirage 11 | { 12 | Shader & Shader::activate() 13 | { 14 | glUseProgram(mProgram); 15 | return *this; 16 | } 17 | 18 | void Shader::bind(unsigned int location, float value) { glUniform1f(location, value); } 19 | void Shader::bind(unsigned int location, glm::mat4 const & matrix) 20 | { glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); } 21 | 22 | Shader & Shader::attach(std::string const & filename) 23 | { 24 | // Load GLSL Shader Source from File 25 | std::string path = PROJECT_SOURCE_DIR "/Mirage/Shaders/"; 26 | std::ifstream fd(path + filename); 27 | auto src = std::string(std::istreambuf_iterator(fd), 28 | (std::istreambuf_iterator())); 29 | 30 | // Create a Shader Object 31 | const char * source = src.c_str(); 32 | auto shader = create(filename); 33 | glShaderSource(shader, 1, & source, nullptr); 34 | glCompileShader(shader); 35 | glGetShaderiv(shader, GL_COMPILE_STATUS, & mStatus); 36 | 37 | // Display the Build Log on Error 38 | if (mStatus == false) 39 | { 40 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, & mLength); 41 | std::unique_ptr buffer(new char[mLength]); 42 | glGetShaderInfoLog(shader, mLength, nullptr, buffer.get()); 43 | fprintf(stderr, "%s\n%s", filename.c_str(), buffer.get()); 44 | } 45 | 46 | // Attach the Shader and Free Allocated Memory 47 | glAttachShader(mProgram, shader); 48 | glDeleteShader(shader); 49 | return *this; 50 | } 51 | 52 | GLuint Shader::create(std::string const & filename) 53 | { 54 | auto index = filename.rfind("."); 55 | auto ext = filename.substr(index + 1); 56 | if (ext == "comp") return glCreateShader(GL_COMPUTE_SHADER); 57 | else if (ext == "frag") return glCreateShader(GL_FRAGMENT_SHADER); 58 | else if (ext == "geom") return glCreateShader(GL_GEOMETRY_SHADER); 59 | else if (ext == "vert") return glCreateShader(GL_VERTEX_SHADER); 60 | else return false; 61 | } 62 | 63 | Shader & Shader::link() 64 | { 65 | glLinkProgram(mProgram); 66 | glGetProgramiv(mProgram, GL_LINK_STATUS, & mStatus); 67 | if(mStatus == false) 68 | { 69 | glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, & mLength); 70 | std::unique_ptr buffer(new char[mLength]); 71 | glGetProgramInfoLog(mProgram, mLength, nullptr, buffer.get()); 72 | fprintf(stderr, "%s", buffer.get()); 73 | } 74 | assert(mStatus == true); 75 | return *this; 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /Samples/shader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // System Headers 4 | #include 5 | #include 6 | #include 7 | 8 | // Standard Headers 9 | #include 10 | 11 | // Define Namespace 12 | namespace Mirage 13 | { 14 | class Shader 15 | { 16 | public: 17 | 18 | // Implement Custom Constructor and Destructor 19 | Shader() { mProgram = glCreateProgram(); } 20 | ~Shader() { glDeleteProgram(mProgram); } 21 | 22 | // Public Member Functions 23 | Shader & activate(); 24 | Shader & attach(std::string const & filename); 25 | GLuint create(std::string const & filename); 26 | GLuint get() { return mProgram; } 27 | Shader & link(); 28 | 29 | // Wrap Calls to glUniform 30 | void bind(unsigned int location, float value); 31 | void bind(unsigned int location, glm::mat4 const & matrix); 32 | template Shader & bind(std::string const & name, T&& value) 33 | { 34 | int location = glGetUniformLocation(mProgram, name.c_str()); 35 | if (location == -1) fprintf(stderr, "Missing Uniform: %s\n", name.c_str()); 36 | else bind(location, std::forward(value)); 37 | return *this; 38 | } 39 | 40 | private: 41 | 42 | // Disable Copying and Assignment 43 | Shader(Shader const &) = delete; 44 | Shader & operator=(Shader const &) = delete; 45 | 46 | // Private Member Variables 47 | GLuint mProgram; 48 | GLint mStatus; 49 | GLint mLength; 50 | 51 | }; 52 | }; 53 | --------------------------------------------------------------------------------