← index
cplusplus11.Examples/SDL2/opengl/simple/gltest.cpp
Source: cplusplus11.Examples/SDL2/opengl/simple/gltest.cpp
/*
 SDL2 OpenGL Example
 sets up a window and draws a few triangles
 using a vertex shader and fragment shader.
 
 - written by Jared Bruni
 adapated from the book "OpenGL Programming Guide " 8th Edition
 
*/

#include<GL/glew.h>
#include"SDL.h"
#include<iostream>
#include<string>
#include<fstream>



#define BUFFER_OFFSET(i) ((char *)NULL + (i))
class FileReadError {};


GLint vert, frag, prog;

std::string readFile(std::string f) {
    std::fstream file;
    file.open(f.c_str(), std::ios::in | std::ios::binary);
    if(!file.is_open()) {
        throw FileReadError();
    }
    unsigned long size = 0;
    file.seekg(0, std::ios::end);
    size = file.tellg();
    file.seekg(0, std::ios::beg);
    char *buf = new char [size+1];
    file.read(buf, size);
    buf[size] = 0;
    std::string text = buf;
    delete [] buf;
    file.close();
    return text;
}



bool LoadShader(std::string f_vert, std::string f_frag) {
    vert = glCreateShader(GL_VERTEX_SHADER);
    frag = glCreateShader(GL_FRAGMENT_SHADER);
    prog = glCreateProgram();
    
    std::string vert_text = readFile(f_vert);
    std::string frag_text = readFile(f_frag);
    
    const char *vs = (const char *)vert_text.c_str();
    const char *fs = (const char *)frag_text.c_str();
    
    glShaderSource(vert, 1, &vs, NULL);
    glShaderSource(frag, 1, &fs, NULL);

    int len = 0;
    glCompileShader(vert);
    GLint result;
    glGetShaderiv(vert, GL_COMPILE_STATUS, &result);
    if(result == GL_TRUE) {
        glAttachShader(prog, vert);
    } else {
        GLchar *str = (GLchar*)malloc(5096);
        glGetShaderInfoLog(vert, 5096, &len, str);
        printf("vertex shader: %s\n", str);
        free(str);
        exit(0); // exit
    }
    glCompileShader(frag);
    glGetShaderiv(frag, GL_COMPILE_STATUS, &result);
    if(result == GL_TRUE)
        glAttachShader(prog, frag);
    else {
        GLchar *str = (GLchar*)malloc(5096);
        glGetShaderInfoLog(frag, 5096, &len, str);
        printf("fragment: %s\n", str);
        free(str);
        exit(0); // exit
    }
    
    glBindAttribLocation(prog, 0, "a_Vertex");
    glLinkProgram(prog);
    glGetProgramiv(prog, GL_LINK_STATUS,&result);
    if(result == GL_TRUE) {
        return true;
    }
    GLchar *str = (GLchar*)malloc(5096);
    glGetProgramInfoLog(prog, 5096, &len, str);
    printf("Program %s\n", str);
    free(str);
    exit(0);// exit
    return false;
}

enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[1];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;

void init() {
    glGenVertexArrays(1, VAOs);
    glBindVertexArray(VAOs[Triangles]);
    
    GLfloat  vertices[NumVertices][2] = {
        { -0.90, -0.90 },  // Triangle 1
        {  0.85, -0.90 },
        { -0.90,  0.85 },
        {  0.90, -0.85 },  // Triangle 2
        {  0.90,  0.90 },
        { -0.85,  0.90 }
    };
    
    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    try {
        if(LoadShader("v.vert", "f.frag") == true) {
            glUseProgram(prog);
        }
    } catch(FileReadError) {
        std::cerr << "Could not open file for shader. Exiting..\n";
        exit(-1);
    }
    
    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);
}

void render() {
    // draw something
    
    glBindVertexArrayAPPLE(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    
    glFlush();
}


int main(int argc, char **argv) {
    if(SDL_Init(SDL_INIT_VIDEO) < 0) {
        std::cerr << "Error initailizing..\n";
        return -1;
    }
    SDL_Event e;
    SDL_DisplayMode src, src_closest;
    
    src.w = 640;
    src.h = 480;
    src.format = 0;
    src.refresh_rate = 0;
    src.driverdata = 0;
    
    if(SDL_GetClosestDisplayMode(0, &src, &src_closest) == NULL) {
        std::cerr << "No acceptable display mode.\n";
        SDL_Quit();
        return -1;
    }
    
    SDL_Window *window = SDL_CreateWindow("OpenGL SDL2 Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, src_closest.w, src_closest.h, SDL_WINDOW_OPENGL);
    
    if(SDL_SetWindowDisplayMode(window, &src_closest)) {
        std::cerr << "Could Not set display mode.\n";
        SDL_Quit();
        return -1;
    }
    
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    
    SDL_GLContext glcontext = SDL_GL_CreateContext(window);

    SDL_GL_SetSwapInterval(1);
    
    glewExperimental = GL_TRUE;
    
    if(glewInit()) {
        std::cerr << "Error initalizing GLEW.\n";
        exit(-1);
    }
    
    std::cout <<"GL Version: "<< glGetString(GL_VERSION) << "\n";

    init();
    glViewport(0, 0, src_closest.w, src_closest.h);
 
    bool active = true;
    while(active) {
        while(SDL_PollEvent(&e)) {
            switch(e.type) {
                case SDL_QUIT:
                    active = false;
                    break;
                case SDL_KEYDOWN:
                    if(e.key.keysym.sym == SDLK_ESCAPE)
                        active = false;
                    break;
            }
        }
        glClear(GL_COLOR_BUFFER_BIT);
        render();
        SDL_GL_SwapWindow(window);
        
    }
    SDL_GL_DeleteContext(glcontext);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}