Last active
          December 29, 2015 22:29 
        
      - 
      
- 
        Save vittorioromeo/7736527 to your computer and use it in GitHub Desktop. 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | #include <thread> | |
| #include <string> | |
| #include <iostream> | |
| #include <SSVUtils/SSVUtils.hpp> | |
| #include <GL/glew.h> | |
| #include <GLFW/glfw3.h> | |
| namespace ssvgl | |
| { | |
| class ShaderSource; | |
| class Shader; | |
| class Program; | |
| using Attribute = GLint; | |
| using Uniform = GLint; | |
| constexpr std::size_t shaderLogBufferSize{512}; | |
| enum class DataType | |
| { | |
| Byte = GL_BYTE, | |
| UnsignedByte = GL_UNSIGNED_BYTE, | |
| Short = GL_SHORT, | |
| UnsignedShort = GL_UNSIGNED_SHORT, | |
| Int = GL_INT, | |
| UnsignedInt = GL_UNSIGNED_INT, | |
| Float = GL_FLOAT, | |
| Double = GL_DOUBLE | |
| }; | |
| enum class PrimitiveType | |
| { | |
| Triangles = GL_TRIANGLES, | |
| Lines = GL_LINES, | |
| Points = GL_POINTS, | |
| }; | |
| enum class BufferType | |
| { | |
| StaticDraw = GL_STATIC_DRAW, | |
| StaticRead = GL_STATIC_READ, | |
| StaticCopy = GL_STATIC_COPY, | |
| DynamicDraw = GL_DYNAMIC_DRAW, | |
| DynamicRead = GL_DYNAMIC_READ, | |
| DynamicCopy = GL_DYNAMIC_COPY, | |
| StreamDraw = GL_STREAM_DRAW, | |
| StreamRead = GL_STREAM_READ, | |
| StreamCopy = GL_STREAM_COPY | |
| }; | |
| enum class ShaderType | |
| { | |
| Vertex = GL_VERTEX_SHADER, | |
| Fragment = GL_FRAGMENT_SHADER, | |
| Geometry = GL_GEOMETRY_SHADER | |
| }; | |
| class VertexBufferObject | |
| { | |
| friend class VertexArrayObject; | |
| private: | |
| GLuint glId; | |
| inline void bind() const noexcept { glBindBuffer(GL_ARRAY_BUFFER, glId); } | |
| inline void buffer() const noexcept { } | |
| public: | |
| template<typename... TArgs> inline VertexBufferObject(TArgs&&... mArgs) noexcept | |
| { | |
| glGenBuffers(1, &glId); | |
| buffer(std::forward<TArgs>(mArgs)...); | |
| } | |
| inline ~VertexBufferObject() noexcept { glDeleteBuffers(1, &glId); } | |
| template<typename T, std::size_t TS> inline void buffer(const T(&mArray)[TS]) const noexcept | |
| { | |
| bind(); | |
| glBufferData(GL_ARRAY_BUFFER, sizeof(mArray), mArray, GL_STATIC_DRAW); | |
| } | |
| }; | |
| class VertexArrayObject | |
| { | |
| private: | |
| GLuint glId; | |
| inline void bind() const noexcept { glBindVertexArray(glId); } | |
| public: | |
| inline VertexArrayObject() noexcept { glGenVertexArrays(1, &glId); } | |
| inline ~VertexArrayObject() noexcept { glDeleteVertexArrays(1, &glId); } | |
| inline void bindAttribute(const Attribute& mAttribute, const VertexBufferObject& mVBO, DataType mType, | |
| std::size_t mSize, std::size_t mStride = 0, std::size_t mOffset = 0, bool mNormalized = GL_FALSE) const noexcept | |
| { | |
| bind(); mVBO.bind(); | |
| glEnableVertexAttribArray(mAttribute); | |
| glVertexAttribPointer(mAttribute, mSize, GLenum(mType), mNormalized, mStride, reinterpret_cast<GLvoid*>(mOffset)); | |
| } | |
| }; | |
| class ShaderSource | |
| { | |
| private: | |
| std::string sourceStr; | |
| const char* sourceData; | |
| public: | |
| inline ShaderSource(std::string mStr) : sourceStr{std::move(mStr)}, sourceData{sourceStr.c_str()} { } | |
| inline const char** getSourceData() noexcept { return &sourceData; } | |
| }; | |
| class Shader | |
| { | |
| friend class Program; | |
| private: | |
| const ShaderType type; | |
| const GLuint glId; | |
| public: | |
| inline Shader(ShaderType mType) : type{mType}, glId{glCreateShader(GLenum(type))} { } | |
| inline Shader(ShaderType mType, ShaderSource& mSource) : Shader{mType} { compile(mSource); } | |
| inline ~Shader() noexcept { glDeleteShader(glId); } | |
| inline void compile(ShaderSource& mSource) | |
| { | |
| glShaderSource(glId, 1, mSource.getSourceData(), nullptr); | |
| glCompileShader(glId); | |
| GLint status; | |
| glGetShaderiv(glId, GL_COMPILE_STATUS, &status); | |
| char logBuffer[shaderLogBufferSize]; | |
| glGetShaderInfoLog(glId, shaderLogBufferSize, nullptr, logBuffer); | |
| std::string compilationLog = std::string{logBuffer}; | |
| if(!compilationLog.empty()) ssvu::lo("Shader compilation log") << compilationLog << std::endl; | |
| } | |
| }; | |
| class Program | |
| { | |
| private: | |
| const GLuint glId{glCreateProgram()}; | |
| std::vector<Shader> attached; | |
| public: | |
| inline Program() = default; | |
| inline Program(const Shader& mVertex) | |
| { | |
| assert(mVertex.type == ShaderType::Vertex); | |
| attach(mVertex); | |
| link(); use(); | |
| } | |
| inline Program(const Shader& mVertex, const Shader& mFragment) | |
| { | |
| assert(mVertex.type == ShaderType::Vertex); | |
| assert(mFragment.type == ShaderType::Fragment); | |
| attach(mVertex); attach(mFragment); | |
| link(); use(); | |
| } | |
| inline Program(const Shader& mVertex, const Shader& mFragment, const Shader& mGeometry) | |
| { | |
| assert(mVertex.type == ShaderType::Vertex); | |
| assert(mFragment.type == ShaderType::Fragment); | |
| assert(mGeometry.type == ShaderType::Geometry); | |
| attach(mVertex); attach(mFragment); attach(mGeometry); | |
| link(); use(); | |
| } | |
| inline ~Program() noexcept { glDeleteProgram(glId); } | |
| inline void attach(const Shader& mShader) noexcept | |
| { | |
| glAttachShader(glId, mShader.glId); | |
| attached.push_back(mShader); | |
| } | |
| inline void link() noexcept | |
| { | |
| glLinkProgram(glId); | |
| for(const auto& s : attached) glDetachShader(glId, s.glId); | |
| } | |
| inline void use() noexcept | |
| { glUseProgram(glId); } | |
| inline Attribute getAttribute(const std::string& mName) const noexcept | |
| { | |
| return glGetAttribLocation(glId, mName.c_str()); | |
| } | |
| }; | |
| inline void errorCallback(int mError, const char* mDescription) | |
| { | |
| ssvu::lo("GLFW error #" + ssvu::toStr(mError)) << mDescription << std::endl; | |
| } | |
| namespace Internal | |
| { | |
| inline bool& getInitialized() noexcept { static bool initialized{false}; return initialized; } | |
| inline bool isInitialized() noexcept { return Internal::getInitialized(); } | |
| inline void deInitialize() noexcept | |
| { | |
| assert(isInitialized()); | |
| glfwTerminate(); | |
| Internal::getInitialized() = false; | |
| } | |
| } | |
| inline void initialize() noexcept | |
| { | |
| assert(!Internal::isInitialized()); | |
| glfwSetErrorCallback(&errorCallback); | |
| if(!glfwInit()) std::terminate(); | |
| glewExperimental = GL_TRUE; | |
| Internal::getInitialized() = true; | |
| std::atexit(&Internal::deInitialize); | |
| } | |
| class Window | |
| { | |
| private: | |
| GLFWwindow* glfwWindow{nullptr}; | |
| std::size_t width{640}, height{480}; | |
| std::string title; | |
| bool fullscreen{false}; | |
| public: | |
| inline Window(std::size_t mWidth, std::size_t mHeight, std::string mTitle, bool mFullscreen) | |
| : width{mWidth}, height{mHeight}, title{std::move(mTitle)}, fullscreen{mFullscreen} | |
| { | |
| assert(Internal::isInitialized()); | |
| glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | |
| glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |
| glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |
| glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); | |
| glfwWindow = glfwCreateWindow(width, height, title.c_str(), fullscreen ? glfwGetPrimaryMonitor() : nullptr, nullptr); | |
| if(!glfwWindow) { glfwTerminate(); std::terminate(); } | |
| glfwMakeContextCurrent(glfwWindow); | |
| assert(glfwGetCurrentContext() == glfwWindow); | |
| glewInit(); | |
| } | |
| inline ~Window() { glfwDestroyWindow(glfwWindow); } | |
| inline GLFWwindow* getGLFWWindow() noexcept { return glfwWindow; } | |
| inline void display() noexcept { glfwSwapBuffers(glfwWindow); } | |
| inline void close() noexcept { glfwSetWindowShouldClose(glfwWindow, GL_TRUE); } | |
| inline bool shouldClose() const noexcept { return glfwWindowShouldClose(glfwWindow); } | |
| }; | |
| } | |
| ssvgl::ShaderSource vertexShaderSource{R"( | |
| #version 150 | |
| in vec2 inVSPosition; | |
| in vec3 inVSColor; | |
| out vec3 inFSColor; | |
| void main() | |
| { | |
| inFSColor = inVSColor; | |
| gl_Position = vec4(inVSPosition, 0.0, 1.0); | |
| } | |
| )"}; | |
| ssvgl::ShaderSource fragmentShaderSource{R"( | |
| #version 150 | |
| in vec3 inFSColor; | |
| out vec4 outFSColor; | |
| void main() | |
| { | |
| outFSColor = vec4(1.0, 1.0, 1.0, 1.0); | |
| } | |
| )"}; | |
| int main() | |
| { | |
| ssvgl::initialize(); | |
| ssvgl::Window window{800, 600, "ssvgl tests", false}; | |
| ssvgl::Shader vertexShader{ssvgl::ShaderType::Vertex, vertexShaderSource}; | |
| ssvgl::Shader fragmentShader{ssvgl::ShaderType::Fragment, fragmentShaderSource}; | |
| ssvgl::Program program{vertexShader, fragmentShader}; | |
| GLfloat vertices[] = { | |
| 0.0f, 0.5f, | |
| 0.5f, -0.5f, | |
| -0.5f, -0.5f | |
| }; | |
| ssvgl::VertexBufferObject vbo{vertices}; | |
| /*GLuint ebo; | |
| glGenBuffers(1, &ebo); | |
| GLuint elements[]{ | |
| 0, 1, 2, | |
| 2, 3, 0 | |
| }; | |
| !glfwWindowShouldClose(window) | |
| glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); | |
| glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);*/ | |
| ssvgl::VertexArrayObject vao; | |
| vao.bindAttribute(program.getAttribute("inVSPosition"), vbo, ssvgl::DataType::Float, 2, 0, 0); | |
| //vao.bindAttribute(program.getAttribute("inVSColor"), vbo, ssvgl::AttributeType::Float, 2, 5 * sizeof(GLfloat), 2 * sizeof(GLfloat)); | |
| // ssvgl::VertexAttribute{program, ssvgl::VertexAttributeType::Float, "inVSPosition", 2, 5 * sizeof(GLfloat), 0}; | |
| // ssvgl::VertexAttribute{program, ssvgl::VertexAttributeType::Float, "inVSColor", 3, 5 * sizeof(GLfloat), 2 * sizeof(GLfloat)}; | |
| while(!window.shouldClose()) | |
| { | |
| glfwPollEvents(); | |
| if(glfwGetKey(window.getGLFWWindow(), GLFW_KEY_ESCAPE) == GLFW_PRESS) window.close(); | |
| glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | |
| glClear(GL_COLOR_BUFFER_BIT); | |
| glDrawArrays(GL_TRIANGLES, 0, 3); | |
| window.display(); | |
| } | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment