Пример #1
0
int main()
{
   // init the library
   piguInit();
   
   int width, height;
   piguGetScreenSize(&width, &height);
   float aspect = static_cast<float>(width)/height;

   // create the window
   if(piguCreateWindow(width, height, 8, 8, 8, 8, 24, 8, 0)<0)
   {
      std::cerr << "failed to create window" << std::endl;
      return 1;
   }
   
   // vsync
   piguSwapInterval(1);

   // shader source code
    std::string vertex_source =
        "uniform mat4 ViewProjection;\n" // the projection matrix uniform
        "attribute vec4 vposition;\n"
        "attribute vec4 vcolor;\n"
        "varying vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = ViewProjection*vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "varying vec4 fcolor;\n"
        "void main() {\n"
        "   gl_FragColor = fcolor;\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
       std::cerr << "failed to compile vertex shader" << std::endl;
       return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
       std::cerr << "failed to compile fragment shader" << std::endl;
       return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    glBindAttribLocation(shader_program, 0, "vposition");
    glBindAttribLocation(shader_program, 1, "vcolor");

    // link the program and check for errors
    glLinkProgram(shader_program);
    if(!check_program_link_status(shader_program))
    {
       std::cerr << "failed to link shaders" << std::endl;
       return 1;
    }

   
    // obtain location of projection uniform
    GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection");
    
    
    // vao and vbo handle
    GLuint vbo, ibo;
 
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a cube
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
    // face 0:
       1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 3

    // face 1:
       1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 2
       1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 3

    // face 2:
       1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 0
       1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 1
      -1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 2
      -1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      
    // face 3:
       1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 1
      -1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 3

    // face 4:
      -1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 1
      -1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 3

    // face 5:
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 0
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 1
       1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 3
    }; // 6 faces with 4 vertices with 6 components (floats)

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLushort indexData[] = {
        // face 0:
        0,1,2,      // first triangle
        2,1,3,      // second triangle
        // face 1:
        4,5,6,      // first triangle
        6,5,7,      // second triangle
        // face 2:
        8,9,10,     // first triangle
        10,9,11,    // second triangle
        // face 3:
        12,13,14,   // first triangle
        14,13,15,   // second triangle
        // face 4:
        16,17,18,   // first triangle
        18,17,19,   // second triangle
        // face 5:
        20,21,22,   // first triangle
        22,21,23,   // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*6*2*3, indexData, GL_STATIC_DRAW);
        
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    glClearColor(0, 0, 0, 1);

    running = true;
    while(running)
    {   
        // get the time in seconds
        float t = piguGetTime();

	// poll events so key state is updated
	piguPollEvents();
	
        // terminate on escape 
        if(piguIsKeyDown(KEY_ESC))
        {
	   running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);

        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, aspect, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 
        
        glm::mat4 ViewProjection = Projection*View;
        
        // set the uniform
        glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 
       
        // draw
        glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_SHORT, 0);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
	    std::cerr << "error: " << error << std::endl;
	    running = false;       
        }
        
        // finally swap buffers
        piguSwapBuffers();       
    }
    
    // delete the created objects
        
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    piguTerminate();

    return 0;
}
Пример #2
0
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }
 
    // sadly glew doesn't play nice with core profiles... 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }
 
    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n" // the projection matrix uniform
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "layout(location = 2) in vec3 voffset;\n" // the per instance offset
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = ViewProjection*(vposition + vec4(voffset, 0));\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;
 
    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection");
    
    
    // vao and vbo handles
    GLuint vao, vbo, tbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a cube
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
    // face 0:
       1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 3
 
    // face 1:
       1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 2
       1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 3
 
    // face 2:
       1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 0
       1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 1
      -1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 2
      -1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      
    // face 3:
       1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 1
      -1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 3
 
    // face 4:
      -1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 1
      -1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 3
 
    // face 5:
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 0
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 1
       1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 3
    }; // 6 faces with 4 vertices with 6 components (floats)
 
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
 
    
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        // face 0:
        0,1,2,      // first triangle
        2,1,3,      // second triangle
        // face 1:
        4,5,6,      // first triangle
        6,5,7,      // second triangle
        // face 2:
        8,9,10,     // first triangle
        10,9,11,    // second triangle
        // face 3:
        12,13,14,   // first triangle
        14,13,15,   // second triangle
        // face 4:
        16,17,18,   // first triangle
        18,17,19,   // second triangle
        // face 5:
        20,21,22,   // first triangle
        22,21,23,   // second triangle
    };
 
    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW);
    

    // generate and bind the vertex buffer object containing the
    // instance offsets
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
            
    // the offsets
    GLfloat translationData[] = {
                 2.0f, 2.0f, 2.0f,  // cube 0
                 2.0f, 2.0f,-2.0f,  // cube 1
                 2.0f,-2.0f, 2.0f,  // cube 2
                 2.0f,-2.0f,-2.0f,  // cube 3
                -2.0f, 2.0f, 2.0f,  // cube 4
                -2.0f, 2.0f,-2.0f,  // cube 5
                -2.0f,-2.0f, 2.0f,  // cube 6
                -2.0f,-2.0f,-2.0f,  // cube 7
    }; // 8 offsets with 3 components each
 
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*8, translationData, GL_STATIC_DRAW);
                    
    // set up generic attrib pointers
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
    
    // a attrib divisor of 1 means that attribute 2 will advance once
    // every instance (0 would mean once per vertex) 
    glVertexAttribDivisor(2, 1);
    
    
    // "unbind" vao
    glBindVertexArray(0);
 
    
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);
 
    running = true;
    while(running)
    {   
        // get the time in seconds
        float t = glfwGetTime();
        
        // terminate on excape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 
        
        glm::mat4 ViewProjection = Projection*View;
        
        // set the uniform
        glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        // the additional parameter indicates how many instances to render
        glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &tbo);
    
    glDetachShader(shader_program, vertex_shader);      
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #3
0
int main() {
    int width = 640;
    int height = 480;

    if(glfwInit() == GL_FALSE) {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    // create a window
    GLFWwindow *window;
    if((window = glfwCreateWindow(width, height, "02indexed_vbo", 0, 0)) == 0) {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }

    glfwMakeContextCurrent(window);

    if(glxwInit()) {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = vposition;\n"
        "}\n";

    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;

    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length);
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader)) {
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader)) {
        glfwDestroyWindow(window);
        glfwTerminate();
        return 1;
    }

    // create program
    shader_program = glCreateProgram();

    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);

    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);

    // vao and vbo handle
    GLuint vao, vbo, ibo;

    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // data for a fullscreen quad
    GLfloat vertexData[] = {
        //  X     Y     Z           R     G     B
        1.0f, 1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 0
        -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 1
        1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 2
        -1.0f,-1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 3
    }; // 4 vertices with 6 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*6, vertexData, GL_STATIC_DRAW);


    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));


    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW);

    while(!glfwWindowShouldClose(window)) {
        glfwPollEvents();

        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        // use the shader program
        glUseProgram(shader_program);

        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cerr << error << std::endl;
            break;
        }

        // finally swap buffers
        glfwSwapBuffers(window);
    }

    // delete the created objects
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);

    glDetachShader(shader_program, vertex_shader);
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
   
    UserData userdata;
    userdata.running = true;
    
    GLWTConfig glwt_config;
    glwt_config.red_bits = 8;
    glwt_config.green_bits = 8;
    glwt_config.blue_bits = 8;
    glwt_config.alpha_bits = 8;
    glwt_config.depth_bits = 24;
    glwt_config.stencil_bits = 8;
    glwt_config.samples = 0;
    glwt_config.sample_buffers = 0;
    glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE;
    glwt_config.api_version_major = 3;
    glwt_config.api_version_minor = 3;
    
    GLWTAppCallbacks app_callbacks;
    app_callbacks.error_callback = error_callback;
    app_callbacks.userdata = &userdata;
    
    if(glwtInit(&glwt_config, &app_callbacks) != 0)
    {
        std::cerr << "failed to init GLWT" << std::endl;
        return 1;
    }
 
    GLWTWindowCallbacks win_callbacks;
    win_callbacks.close_callback = close_callback;
    win_callbacks.expose_callback = 0;
    win_callbacks.resize_callback = 0;
    win_callbacks.show_callback = 0;
    win_callbacks.focus_callback = 0;
    win_callbacks.key_callback = key_callback,
    win_callbacks.motion_callback = 0;
    win_callbacks.button_callback = 0;
    win_callbacks.mouseover_callback = 0;
    win_callbacks.userdata = &userdata;
    
    // create a window
    GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0);
    if(window == 0)
    {
        std::cerr << "failed to open window" << std::endl;
        glwtQuit();
        return 1;
    }
    
    if (glxwInit())
    {
        std::cerr << "failed to init GLXW" << std::endl;
        glwtWindowDestroy(window);
        glwtQuit();
        return 1;
    }
    
    glwtWindowShow(window, 1);
    glwtMakeCurrent(window);
    glwtSwapInterval(window, 1);

    // shader source code
    
    // the vertex shader simply passes through data
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = vposition;\n"
        "}\n";

    // the geometry shader creates the billboard quads
    std::string geometry_source =
        "#version 330\n"
        "uniform mat4 View;\n"
        "uniform mat4 Projection;\n"
        "layout (points) in;\n"
        "layout (triangle_strip, max_vertices = 4) out;\n"
        "out vec2 txcoord;\n"
        "void main() {\n"
        "   vec4 pos = View*gl_in[0].gl_Position;\n"
        "   txcoord = vec2(-1,-1);\n"
        "   gl_Position = Projection*(pos+vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1,-1);\n"
        "   gl_Position = Projection*(pos+vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2(-1, 1);\n"
        "   gl_Position = Projection*(pos+vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1, 1);\n"
        "   gl_Position = Projection*(pos+vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "}\n";    
    
    // the fragment shader creates a bell like radial color distribution    
    std::string fragment_source =
        "#version 330\n"
        "in vec2 txcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n"
        "   FragColor = s*vec4(1,0.9,0.6,1);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, geometry_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
    
    // create and compiler geometry shader
    geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
    source = geometry_source.c_str();
    length = geometry_source.size();
    glShaderSource(geometry_shader, 1, &source, &length); 
    glCompileShader(geometry_shader);
    if(!check_shader_compile_status(geometry_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, geometry_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint View_location = glGetUniformLocation(shader_program, "View");
    GLint Projection_location = glGetUniformLocation(shader_program, "Projection");
    
    
    // vao and vbo handle
    GLuint vao, vbo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    
    const int particles = 128*1024;

    // create a galaxylike distribution of points
    std::vector<GLfloat> vertexData(particles*3);
    for(int i = 0;i<particles;++i)
    {
        int arm = 3*(std::rand()/float(RAND_MAX));
        float alpha = 1/(0.1f+std::pow(std::rand()/float(RAND_MAX),0.7f))-1/1.1f;
        float r = 4.0f*alpha;
        alpha += arm*2.0f*3.1416f/3.0f;
        
        vertexData[3*i+0] = r*std::sin(alpha);
        vertexData[3*i+1] = 0;
        vertexData[3*i+2] = r*std::cos(alpha);
        
        vertexData[3*i+0] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+
                                                  std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)));
        vertexData[3*i+1] += (2.0f-0.1*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+
                                                  std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)));
        vertexData[3*i+2] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+
                                                  std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)));
    }

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    
    // "unbind" vao
    glBindVertexArray(0);

    
    // we are blending so no depth testing
    glDisable(GL_DEPTH_TEST);
    
    // enable blending
    glEnable(GL_BLEND);
    //  and set the blend function to result = 1*source + 1*destination
    glBlendFunc(GL_ONE, GL_ONE);

    while(userdata.running)
    {   
        // get the time in seconds
        float t = glwtGetNanoTime()*1.e-9f;
        
        // update events
        glwtEventHandle(0);
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -50.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 30.0f*std::sin(0.1f*t), glm::vec3(1.0f, 0.0f, 0.0f)); 
        View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); 
        
        
        // set the uniform
        glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); 
        glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); 
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_POINTS, 0, particles);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            userdata.running = false;       
        }
        
        // finally swap buffers
        glwtSwapBuffers(window);       
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, geometry_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(geometry_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glwtWindowDestroy(window);
    glwtQuit();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    } 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    glfwSwapInterval(0);
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code
    
    // the vertex shader simply passes through data
    std::string vertex_source =
        "#version 430\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = vposition;\n"
        "}\n";
    
    // the geometry shader creates the billboard quads
    std::string geometry_source =
        "#version 430\n"
        "layout(location = 0) uniform mat4 View;\n"
        "layout(location = 1) uniform mat4 Projection;\n"
        "layout (points) in;\n"
        "layout (triangle_strip, max_vertices = 4) out;\n"
        "out vec2 txcoord;\n"
        "void main() {\n"
        "   vec4 pos = View*gl_in[0].gl_Position;\n"
        "   txcoord = vec2(-1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2(-1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "}\n";    
    
    // the fragment shader creates a bell like radial color distribution    
    std::string fragment_source =
        "#version 330\n"
        "in vec2 txcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   float s = (1/(1+15.*dot(txcoord, txcoord))-1/16.);\n"
        "   FragColor = s*vec4(0.3,0.3,1.0,1);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, geometry_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
    
    // create and compiler geometry shader
    geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
    source = geometry_source.c_str();
    length = geometry_source.size();
    glShaderSource(geometry_shader, 1, &source, &length); 
    glCompileShader(geometry_shader);
    if(!check_shader_compile_status(geometry_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, geometry_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    

    std::string acceleration_source =
        "#version 430\n"
        "layout(local_size_x=256) in;\n"
        
        "layout(location = 0) uniform float dt;\n"
        "layout(rgba32f, location = 1) uniform imageBuffer positions;\n"
        "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n"
        
        "void main() {\n"
        "   int N = int(gl_NumWorkGroups.x*gl_WorkGroupSize.x);\n"
        "   int index = int(gl_GlobalInvocationID);\n"
        
        "   vec3 position = imageLoad(positions, index).xyz;\n"
        "   vec3 velocity = imageLoad(velocities, index).xyz;\n"
        "   vec3 acceleration = vec3(0,0,0);\n"
        "   for(int i = 0;i<N;++i) {\n"
        "       vec3 other = imageLoad(positions, i).xyz;\n"
        "       vec3 diff = position - other;\n"
        "       float dist = length(diff)+0.001;\n"
        "       acceleration -= 0.1*diff/(dist*dist*dist);\n"
        "   }\n"
        "   imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n"
        "}\n";
   
    // program and shader handles
    GLuint acceleration_program, acceleration_shader;

    // create and compiler vertex shader
    acceleration_shader = glCreateShader(GL_COMPUTE_SHADER);
    source = acceleration_source.c_str();
    length = acceleration_source.size();
    glShaderSource(acceleration_shader, 1, &source, &length); 
    glCompileShader(acceleration_shader);
    if(!check_shader_compile_status(acceleration_shader))
    {
        return 1;
    }

    // create program
    acceleration_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(acceleration_program, acceleration_shader);
   
    // link the program and check for errors
    glLinkProgram(acceleration_program);
    check_program_link_status(acceleration_program);


    std::string tiled_acceleration_source =
        "#version 430\n"
        "layout(local_size_x=256) in;\n"
        
        "layout(location = 0) uniform float dt;\n"
        "layout(rgba32f, location = 1) uniform imageBuffer positions;\n"
        "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n"
        "layout(location = 3) uniform int tile;\n"
        
        "shared vec4 tmp[256];\n"
        "void main() {\n"
        "   int index = int(gl_GlobalInvocationID);\n"
        "   vec3 position = imageLoad(positions, index).xyz;\n"
        "   vec3 velocity = imageLoad(velocities, index).xyz;\n"
        "   vec3 acceleration = vec3(0,0,0);\n"
        "   tmp[gl_LocalInvocationIndex] = imageLoad(positions, 256*tile + int(gl_LocalInvocationIndex));\n"
        "   groupMemoryBarrier();\n"
        "   barrier();\n"
        "   for(int i = 0;i<gl_WorkGroupSize.x;++i) {\n"
        "       vec3 other = tmp[i].xyz;\n"
        "       vec3 diff = position - other;\n"
        "       float invdist = 1/sqrt(dot(diff,diff)+0.00001);\n"
        "       acceleration -= diff*0.1*invdist*invdist*invdist;\n"
        "   }\n"
        "   imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n"
        "}\n";
   
    // program and shader handles
    GLuint tiled_acceleration_program, tiled_acceleration_shader;

    // create and compiler vertex shader
    tiled_acceleration_shader = glCreateShader(GL_COMPUTE_SHADER);
    source = tiled_acceleration_source.c_str();
    length = tiled_acceleration_source.size();
    glShaderSource(tiled_acceleration_shader, 1, &source, &length); 
    glCompileShader(tiled_acceleration_shader);
    if(!check_shader_compile_status(tiled_acceleration_shader))
    {
        return 1;
    }

    // create program
    tiled_acceleration_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(tiled_acceleration_program, tiled_acceleration_shader);
   
    // link the program and check for errors
    glLinkProgram(tiled_acceleration_program);
    check_program_link_status(tiled_acceleration_program);

   

    std::string integrate_source =
        "#version 430\n"
        "layout(local_size_x=256) in;\n"
        
        "layout(location = 0) uniform float dt;\n"
        "layout(rgba32f, location = 1) uniform imageBuffer positions;\n"
        "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n"
        
        "void main() {\n"
        "   int index = int(gl_GlobalInvocationID);\n"
        "   vec4 position = imageLoad(positions, index);\n"
        "   vec4 velocity = imageLoad(velocities, index);\n"
        "   position.xyz += dt*velocity.xyz;\n"
        "   imageStore(positions, index, position);\n"
        "}\n";
   
    // program and shader handles
    GLuint integrate_program, integrate_shader;

    // create and compiler vertex shader
    integrate_shader = glCreateShader(GL_COMPUTE_SHADER);
    source = integrate_source.c_str();
    length = integrate_source.size();
    glShaderSource(integrate_shader, 1, &source, &length); 
    glCompileShader(integrate_shader);
    if(!check_shader_compile_status(integrate_shader))
    {
        return 1;
    }

    // create program
    integrate_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(integrate_program, integrate_shader);
   
    // link the program and check for errors
    glLinkProgram(integrate_program);
    check_program_link_status(integrate_program);   
   
   
    const int particles = 32*1024;

    // randomly place particles in a cube
    std::vector<glm::vec4> positionData(particles);
    std::vector<glm::vec4> velocityData(particles);
    for(int i = 0;i<particles;++i)
    {
        // initial position
        positionData[i] = glm::vec4(
                                1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX),
                                1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX),
                                1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX),
                                0
                            );
        positionData[i] = glm::vec4(0.0f,0.0f,0.0f,1) + glm::vec4(4.0f,1.0f,4.0f,1)*positionData[i];
        velocityData[i] = 40.0f*glm::vec4(glm::cross(glm::vec3(positionData[i].xyz()), glm::vec3(0,1,0)), 0)/glm::dot(glm::vec3(positionData[i].xyz()),glm::vec3(positionData[i].xyz()));
    }
    
    // generate positions_vbos and vaos
    GLuint vao, positions_vbo, velocities_vbo;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &positions_vbo);
    

    glBindVertexArray(vao);
        
    glBindBuffer(GL_ARRAY_BUFFER, positions_vbo);

    // fill with initial data
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*particles, &positionData[0], GL_STATIC_DRAW);
                        
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    // "unbind" vao
    glBindVertexArray(0);
    
    glm::vec4 zero(0,0,0,0);
    
    glGenBuffers(1, &velocities_vbo);
    glBindBuffer(GL_TEXTURE_BUFFER, velocities_vbo);
    glBufferData(GL_TEXTURE_BUFFER, sizeof(glm::vec4)*particles,  &velocityData[0], GL_STATIC_DRAW);                  
 
 


    // texture handle
    GLuint positions_texture, velocities_texture;
    
    glGenTextures(1, &positions_texture);
    glBindTexture(GL_TEXTURE_BUFFER, positions_texture);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, positions_vbo);
    
    glGenTextures(1, &velocities_texture);
    glBindTexture(GL_TEXTURE_BUFFER, velocities_texture);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, velocities_vbo);

    // bind images
    glBindImageTexture(0, positions_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
    glBindImageTexture(1, velocities_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
    
    // physical parameters
    float dt = 1.0f/60.0f;
    
    // setup uniforms
    glUseProgram(tiled_acceleration_program);
    glUniform1f(0, dt);
    glUniform1i(1, 0);
    glUniform1i(2, 1);
        
    glUseProgram(acceleration_program);
    glUniform1f(0, dt);
    glUniform1i(1, 0);
    glUniform1i(2, 1);
        
    glUseProgram(integrate_program);
    glUniform1f(0, dt);
    glUniform1i(1, 0);
    glUniform1i(2, 1);
    
    // we are blending so no depth testing
    glDisable(GL_DEPTH_TEST);
    
    // enable blending
    glEnable(GL_BLEND);
    //  and set the blend function to result = 1*source + 1*destination
    glBlendFunc(GL_ONE, GL_ONE);

    GLuint query;
    glGenQueries(1, &query);

    bool tiled = false;
    bool space_down = false;
    
    running = true;
    while(running)
    {   
        // get the time in seconds
        float t = glfwGetTime();
        
        // terminate on excape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // toggle occlusion culling
        if(glfwGetKey(GLFW_KEY_SPACE) && !space_down)
        {
            tiled = !tiled;
        }
        space_down = glfwGetKey(GLFW_KEY_SPACE);
        
        
        glBeginQuery(GL_TIME_ELAPSED, query);
        
        if(tiled)
        {
            glUseProgram(tiled_acceleration_program);
            int tiles = particles/256;
            for(int tile = 0;tile<tiles;++tile)
            {
                glUniform1i(3, tile);
                glDispatchCompute(particles/256, 1, 1);
            }
        }
        else
        {
            glUseProgram(acceleration_program);
            glDispatchCompute(particles/256, 1, 1);
        }
        
        glEndQuery(GL_TIME_ELAPSED);
        
        glUseProgram(integrate_program);

        glDispatchCompute(particles/256, 1, 1);
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f));
        
        // tilt the camera
        View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 
        
        // set the uniforms
        glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(View)); 
        glUniformMatrix4fv(1, 1, GL_FALSE, glm::value_ptr(Projection)); 
        
        // bind the current vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_POINTS, 0, particles);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();
        
        {
            GLuint64 result;
            glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result);
            std::cout << result*1.e-6 << " ms/frame" << std::endl;
        }
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &positions_vbo);
    glDeleteBuffers(1, &velocities_vbo);
    glDeleteTextures(1, &positions_texture);
    glDeleteTextures(1, &velocities_texture);
    
    glDetachShader(shader_program, vertex_shader);  
    glDetachShader(shader_program, geometry_shader);    
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(geometry_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glDetachShader(acceleration_program, acceleration_shader);  
    glDeleteShader(acceleration_shader);
    glDeleteProgram(acceleration_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #6
0
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "in vec4 vposition;\n"
        "in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);

    // bind the attribute locations (inputs)
    glBindAttribLocation(shader_program, 0, "vposition");
    glBindAttribLocation(shader_program, 1, "vcolor");
    
    // bind the FragDataLocation (output)
    glBindFragDataLocation(shader_program, 0, "FragColor");
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // vao and vbo handle
    GLuint vao, vbo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a fullscreen quad
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
       1.0f, 1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 2
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 4
      -1.0f,-1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 5
    }; // 6 vertices with 6 components (floats) each

    
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    // "unbind" vao
    glBindVertexArray(0);

    running = true;
    while(running)
    {    
        // terminate on escape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_TRIANGLES, 0, 6);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }

    // delete the created objects
    
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
int main()
{
    int width = 512;
    int height = 512;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }
    
    
    // select opengl version 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }
    
    glfwSwapInterval(1);
    

    // shader source code
    // shared vertex shader
    std::string vertex_source =
        "#version 420\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = vposition;\n"
        "}\n";
    
    // the first fragment shader doesn't output anything since it only
    // updates the image in place
    std::string fragment1_source =
        "#version 420\n"
        "uniform float dt;\n"
        "uniform ivec2 image_size;\n"
        "uniform layout(rgba32f) image2D image;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   ivec2 coords = ivec2(gl_FragCoord.xy);\n"
        "	vec4 HE = imageLoad(image, coords);\n"
		"	float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;\n"
		"	float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;\n"
		"   HE.xy += dt*vec2(-Ezdy, Ezdx);\n"
        "   imageStore(image, coords, HE);\n"
        "}\n";
    
        
    // the second fragment shader also outputs the frag color for display
    // purposes
    std::string fragment2_source =
        "#version 420\n"
        "uniform float t;\n"
        "uniform float dt;\n"
        "uniform ivec2 image_size;\n"
        "uniform layout(rgba32f) image2D image;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   ivec2 coords = ivec2(gl_FragCoord.xy);\n"
		
        "	float e = 1;\n"
        "	vec4 HE = imageLoad(image, coords);\n"
		"	float r = HE.w;\n"
		"	float Hydx = imageLoad(image, coords+ivec2(1, 0)).y\n"
		"				-HE.y;\n"
		"	float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x\n"
		"				-HE.x;\n"
		
		"	float Eout = dt*(Hydx-Hxdy)/(e);\n"
        "   HE.z = HE.z*(1-dt*r/e) + Eout;\n"
        
        // add source at image center
        "   if(coords.x == image_size.x/2 && coords.y == image_size.y/2) {\n"
        "   	HE.z += 30*sin(15*t)*exp(-10*(t-2)*(t-2));\n"
        "	}\n"
        
        "   imageStore(image, coords, HE);\n"
        "   FragColor = vec4(HE.z, HE.w, -HE.z, 1);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader1_program, shader2_program, vertex_shader, fragment1_shader, fragment2_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment1_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment1_source.c_str();
    length = fragment1_source.size();
    glShaderSource(fragment1_shader, 1, &source, &length);   
    glCompileShader(fragment1_shader);
    if(!check_shader_compile_status(fragment1_shader))
    {
        return 1;
    }

    // create and compiler fragment shader
    fragment2_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment2_source.c_str();
    length = fragment2_source.size();
    glShaderSource(fragment2_shader, 1, &source, &length);   
    glCompileShader(fragment2_shader);
    if(!check_shader_compile_status(fragment2_shader))
    {
        return 1;
    }
    
    // create program
    shader1_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader1_program, vertex_shader);
    glAttachShader(shader1_program, fragment1_shader);
    
    // link the program and check for errors
    glLinkProgram(shader1_program);
    check_program_link_status(shader1_program);
    
    // get texture uniform location
    GLint image_size_location1 = glGetUniformLocation(shader1_program, "image_size");
    GLint image_location1 = glGetUniformLocation(shader1_program, "image");
    GLint dt_location1 = glGetUniformLocation(shader1_program, "dt");

    
    // create program
    shader2_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader2_program, vertex_shader);
    glAttachShader(shader2_program, fragment2_shader);
    
    // link the program and check for errors
    glLinkProgram(shader2_program);
    check_program_link_status(shader2_program);
    
    // get texture uniform location
    GLint image_size_location2 = glGetUniformLocation(shader2_program, "image_size");
    GLint image_location2 = glGetUniformLocation(shader2_program, "image");
    GLint t_location2 = glGetUniformLocation(shader2_program, "t");
    GLint dt_location2 = glGetUniformLocation(shader2_program, "dt");

    
    // vao and vbo handle
    GLuint vao, vbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a fullscreen quad
    GLfloat vertexData[] = {
    //  X     Y     Z
       1.0f, 1.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 0.0f, // vertex 3
    }; // 4 vertices with 3 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*3, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW);
    
    // "unbind" vao
    glBindVertexArray(0);

    // texture handle
    GLuint texture;
    
    // generate texture
    glGenTextures(1, &texture);

    // bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // create some image data
    std::vector<GLfloat> image(4*width*height);
    for(int j = 0;j<height;++j)
        for(int i = 0;i<width;++i)
        {
            size_t index = j*width + i;
            image[4*index + 0] = 0.0f;
            image[4*index + 1] = 0.0f;
            image[4*index + 2] = 0.0f;
            image[4*index + 3] = 20.0f*glm::clamp(glm::perlin(0.008f*glm::vec2(i,j+70)),0.0f,0.1f);
        }
    
    
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    
    // set texture content
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &image[0]);
    
    float t = 0;
    float dt = 1.0f/60.0f;
    running = true;
    while(running)
    {   
        t += dt;
        
        // reset time every 10 seconds to repeat the sequence
        if(t>10) t -= 10;
        
        // terminate on escape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
        
        // bind the vao
        glBindVertexArray(vao);

        int substeps = 5;
        
        glUseProgram(shader1_program);
            
        glUniform2i(image_size_location1, width, height);
        glUniform1i(image_location1, 0);
        glUniform1f(dt_location1, 50*dt/substeps);

        glUseProgram(shader2_program);

        glUniform2i(image_size_location2, width, height);
        glUniform1i(image_location2, 0);
        glUniform1f(dt_location2, 50*dt/substeps);

        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        int i = 0;
        for(;i<substeps-1;++i)
        {
            glUseProgram(shader1_program);

            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            
            glUseProgram(shader2_program);
            glUniform1f(t_location2, t+i*dt/substeps);
            
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }
        
        
        glUseProgram(shader1_program);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
            
        glUseProgram(shader2_program);
        glUniform1f(t_location2, t+i*dt/substeps);
            
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
         
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
    
    glDeleteTextures(1, &texture);
    
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    
    glDetachShader(shader1_program, vertex_shader);	
    glDetachShader(shader1_program, fragment1_shader);
    glDetachShader(shader2_program, vertex_shader);	
    glDetachShader(shader2_program, fragment2_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment1_shader);
    glDeleteProgram(shader1_program);
    glDeleteShader(fragment2_shader);
    glDeleteProgram(shader2_program);

    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
   
    UserData userdata;
    userdata.running = true;
    
    GLWTConfig glwt_config;
    glwt_config.red_bits = 8;
    glwt_config.green_bits = 8;
    glwt_config.blue_bits = 8;
    glwt_config.alpha_bits = 8;
    glwt_config.depth_bits = 24;
    glwt_config.stencil_bits = 8;
    glwt_config.samples = 0;
    glwt_config.sample_buffers = 0;
    glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE;
    glwt_config.api_version_major = 3;
    glwt_config.api_version_minor = 3;
    
    GLWTAppCallbacks app_callbacks;
    app_callbacks.error_callback = error_callback;
    app_callbacks.userdata = &userdata;
    
    if(glwtInit(&glwt_config, &app_callbacks) != 0)
    {
        std::cerr << "failed to init GLWT" << std::endl;
        return 1;
    }
 
    GLWTWindowCallbacks win_callbacks;
    win_callbacks.close_callback = close_callback;
    win_callbacks.expose_callback = 0;
    win_callbacks.resize_callback = 0;
    win_callbacks.show_callback = 0;
    win_callbacks.focus_callback = 0;
    win_callbacks.key_callback = key_callback,
    win_callbacks.motion_callback = 0;
    win_callbacks.button_callback = 0;
    win_callbacks.mouseover_callback = 0;
    win_callbacks.userdata = &userdata;
    
    // create a window
    GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0);
    if(window == 0)
    {
        std::cerr << "failed to open window" << std::endl;
        glwtQuit();
        return 1;
    }
    
    if (glxwInit())
    {
        std::cerr << "failed to init GLXW" << std::endl;
        glwtWindowDestroy(window);
        glwtQuit();
        return 1;
    }
    
    glwtWindowShow(window, 1);
    glwtMakeCurrent(window);
    glwtSwapInterval(window, 1);

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);

    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    

    // vao and vbo handle
    GLuint vao, vbo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a fullscreen quad
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
       1.0f, 1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 2
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 4
      -1.0f,-1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 5
    }; // 6 vertices with 6 components (floats) each

    
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    // "unbind" vao
    glBindVertexArray(0);

    while(userdata.running)
    {
        // update events
        glwtEventHandle(0);
                    
        // clear first
        glClear(GL_COLOR_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_TRIANGLES, 0, 6);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            userdata.running = false;       
        }
        
        // finally swap buffers
        glwtSwapBuffers(window);      
    }

    // delete the created objects
    
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glwtWindowDestroy(window);
    glwtQuit();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    // this time we disable the mouse cursor since we want differential
    // mouse input
    glfwDisable(GLFW_MOUSE_CURSOR);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // draw shader
    std::string vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec3 normal;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   float brightness = dot(normal,normalize(vec3(1,2,3)));\n"
        "   brightness = 0.3+((brightness>0)?0.7*brightness:0.3*brightness);\n"
        "   fcolor = vec4(brightness,brightness,brightness,1);\n"
        "   gl_Position = ViewProjection*vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = abs(fcolor);\n"
        "}\n";
    
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint DrawViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection");
 

    // trivial shader for occlusion queries
    std::string query_vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = ViewProjection*vposition;\n"
        "}\n";
        
    std::string query_fragment_source =
        "#version 330\n"
        "void main() {\n"
        "}\n";
    
    // program and shader handles
    GLuint query_shader_program, query_vertex_shader, query_fragment_shader;

    // create and compiler vertex shader
    query_vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = query_vertex_source.c_str();
    length = query_vertex_source.size();
    glShaderSource(query_vertex_shader, 1, &source, &length); 
    glCompileShader(query_vertex_shader);
    if(!check_shader_compile_status(query_vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    query_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = query_fragment_source.c_str();
    length = query_fragment_source.size();
    glShaderSource(query_fragment_shader, 1, &source, &length);   
    glCompileShader(query_fragment_shader);
    if(!check_shader_compile_status(query_fragment_shader))
    {
        return 1;
    }
    
    // create program
    query_shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(query_shader_program, query_vertex_shader);
    glAttachShader(query_shader_program, query_fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(query_shader_program);
    check_program_link_status(query_shader_program);
    
    // obtain location of projection uniform
    GLint QueryViewProjection_location = glGetUniformLocation(query_shader_program, "ViewProjection");


    // chunk container and chunk parameters
    std::vector<Chunk> chunks;
    int chunkrange = 4;
    int chunksize = 32;
    
    // chunk extraction
    std::cout << "generating chunks, this may take a while." << std::endl;
    
    // iterate over all chunks we want to extract        
    for(int i = -chunkrange;i<chunkrange;++i)
        for(int j = -chunkrange;j<chunkrange;++j)
            for(int k = -chunkrange;k<chunkrange;++k)
    {
        
        Chunk chunk;
        
        // chunk data
        
        // generate and bind the vao
        glGenVertexArrays(1, &chunk.vao);
        glBindVertexArray(chunk.vao);
        
        // generate and bind the vertex buffer object
        glGenBuffers(1, &chunk.vbo);
        glBindBuffer(GL_ARRAY_BUFFER, chunk.vbo);
        
        std::vector<glm::vec3> vertexData;
        glm::vec3 offset = static_cast<float>(chunksize) * glm::vec3(i,j,k);
        float threshold = 0.0f;
        // iterate over all blocks within the chunk
        for(int x = 0;x<chunksize;++x)
            for(int y = 0;y<chunksize;++y)
                for(int z = 0;z<chunksize;++z)
                {
                    glm::vec3 pos = glm::vec3(x,y,z) + offset;
                    // insert quads if current block is solid and neighbors are not
                    if(world_function(pos)<threshold)
                    {
                        if(world_function(pos+glm::vec3(1,0,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 1, 0, 0));
                        }
                        if(world_function(pos+glm::vec3(0,1,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 1, 0));
                        }
                        if(world_function(pos+glm::vec3(0,0,1))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3( 0, 0, 1));
                        }
                        if(world_function(pos-glm::vec3(1,0,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3(-1, 0, 0));
                        }
                        if(world_function(pos-glm::vec3(0,1,0))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3( 0,-1, 0));
                        }
                        if(world_function(pos-glm::vec3(0,0,1))>=threshold)
                        {
                            vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                            vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1));
                            vertexData.push_back(glm::vec3( 0, 0,-1));
                        }
                    }
                }
        // upload
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
                        
               
        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
     
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
        
        
        // generate and bind the index buffer object
        glGenBuffers(1, &chunk.ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.ibo);
        
        chunk.quadcount = vertexData.size()/8;
        std::vector<GLuint> indexData(6*chunk.quadcount);
        for(int i = 0;i<chunk.quadcount;++i)
        {
            indexData[6*i + 0] = 4*i + 0;
            indexData[6*i + 1] = 4*i + 1;
            indexData[6*i + 2] = 4*i + 2;
            indexData[6*i + 3] = 4*i + 2;
            indexData[6*i + 4] = 4*i + 1;
            indexData[6*i + 5] = 4*i + 3;
        }
        
        // upload
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indexData.size(), &indexData[0], GL_STATIC_DRAW);


        // chunk bounding box

        // generate and bind the vao
        glGenVertexArrays(1, &chunk.bounding_vao);
        glBindVertexArray(chunk.bounding_vao);
        
        // generate and bind the vertex buffer object
        glGenBuffers(1, &chunk.bounding_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, chunk.bounding_vbo);
                
        // data for the bounding cube
        GLfloat boundingVertexData[] = {
        //  X                           Y                           Z 
        // face 0:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,

        // face 1:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,

        // face 2:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
          
        // face 3:
            offset.x+chunksize-0.5f,    offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,

        // face 4:
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y+chunksize-0.5f,    offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,

        // face 5:
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z+chunksize-0.5f,
            offset.x+chunksize-0.5f,    offset.y-0.5f,              offset.z-0.5f,
            offset.x-0.5f,              offset.y-0.5f,              offset.z-0.5f,
        }; // 6 faces with 4 vertices with 6 components (floats)

        // fill with data
        glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*3, boundingVertexData, GL_STATIC_DRAW);
                        
               
        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
        
        // generate and bind the index buffer object
        glGenBuffers(1, &chunk.bounding_ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.bounding_ibo);
                
        GLuint boundingIndexData[] = {
             0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7, 8, 9,10,10, 9,11,
            12,13,14,14,13,15,16,17,18,18,17,19,20,21,22,22,21,23,
        };

        // fill with data
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, boundingIndexData, GL_STATIC_DRAW);
        
        // generate the query object for the occlusion query
        glGenQueries(1, &chunk.query);
        
        // set the center location of the chunk
        chunk.center = offset + 0.5f*chunksize;
        
        // add to container
        chunks.push_back(chunk);
    }
    
    // "unbind" vao
    glBindVertexArray(0);

    // timer query setup
    // use multiple queries to avoid stalling on getting the results
    const int querycount = 5;
    GLuint queries[querycount];
    int current_query = 0;
    glGenQueries(querycount, queries);
    
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);

    // camera position and orientation
    glm::vec3 position;
    glm::mat4 rotation = glm::mat4(1.0f);
    
    running = true;
    float t = glfwGetTime();
    bool occlusion_cull = true;
    bool space_down = false;
    
    // mouse position
    int mousex, mousey;
    glfwGetMousePos(&mousex, &mousey);
    while(running)
    {   
        // calculate timestep
        float new_t = glfwGetTime();
        float dt = new_t - t;
        t = new_t;

        // update mouse differential
        int tmpx, tmpy;
        glfwGetMousePos(&tmpx, &tmpy);
        glm::vec2 mousediff(tmpx-mousex, tmpy-mousey);
        mousex = tmpx;
        mousey = tmpy;
        
        // find up, forward and right vector
        glm::mat3 rotation3(rotation);
        glm::vec3 up = glm::transpose(rotation3)*glm::vec3(0.0f, 1.0f, 0.0f);
        glm::vec3 right = glm::transpose(rotation3)*glm::vec3(1.0f, 0.0f, 0.0f);
        glm::vec3 forward = glm::transpose(rotation3)*glm::vec3(0.0f, 0.0f,-1.0f);
        
        // apply mouse rotation
        rotation = glm::rotate(rotation,  0.2f*mousediff.x, up);
        rotation = glm::rotate(rotation,  0.2f*mousediff.y, right);
        
        // roll
        if(glfwGetKey('Q'))
        {
            rotation = glm::rotate(rotation, 180.0f*dt, forward); 
        }  
        if(glfwGetKey('E'))
        {
            rotation = glm::rotate(rotation,-180.0f*dt, forward); 
        }
        
        // movement
        if(glfwGetKey('W'))
        {
            position += 10.0f*dt*forward; 
        }  
        if(glfwGetKey('S'))
        {
            position -= 10.0f*dt*forward;
        }
        if(glfwGetKey('D'))
        {
            position += 10.0f*dt*right; 
        }  
        if(glfwGetKey('A'))
        {
            position -= 10.0f*dt*right;
        }
        
        // toggle occlusion culling
        if(glfwGetKey(GLFW_KEY_SPACE) && !space_down)
        {
            occlusion_cull = !occlusion_cull;
        }
        space_down = glfwGetKey(GLFW_KEY_SPACE);
        
        // terminate on escape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 200.f);
        glm::mat4 View = rotation*glm::translate(glm::mat4(1.0f), -position);
        glm::mat4 ViewProjection = Projection*View;


        // set matrices for both shaders
        glUseProgram(query_shader_program);
        glUniformMatrix4fv(QueryViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 
        glUseProgram(shader_program);
        glUniformMatrix4fv(DrawViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection));
        
        // set clear color to sky blue
        glClearColor(0.5f,0.8f,1.0f,1.0f);
        
        // clear
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // sort chunks by distance
        std::sort(chunks.begin(), chunks.end(), DistancePred(position));
        
        size_t i = 0;
        float maxdist = chunksize;

        // start timer query
        glBeginQuery(GL_TIME_ELAPSED, queries[current_query]);
        
        // peel chunks
        while(i!=chunks.size())
        {
            size_t j = i;
            if(occlusion_cull)
            {
                // start occlusion queries and render for the current slice
                glDisable(GL_CULL_FACE);
                
                // we don't want the queries to actually render something
                glDepthMask(GL_FALSE);
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                glUseProgram(query_shader_program);
                for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j)
                {
                    // frustum culling
                    glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1);
                    if( (glm::distance(chunks[j].center,position) > chunksize) &&
                        (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize))
                        continue;
                    
                    // begin occlusion query
                    glBeginQuery(GL_ANY_SAMPLES_PASSED, chunks[j].query);
                    
                    // draw bounding box
                    glBindVertexArray(chunks[j].bounding_vao);
                    glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0);
                    
                    // end occlusion query
                    glEndQuery(GL_ANY_SAMPLES_PASSED);
                }
                j = i;
            }

            // render the current slice
            glEnable(GL_CULL_FACE);
            
            // turn rendering back on
            glDepthMask(GL_TRUE);
            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
            glUseProgram(shader_program);
            for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j)
            {
                // frustum culling
                glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1);
                if( (glm::distance(chunks[j].center,position) > chunksize) &&
                    (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize))
                    continue;
                
                // begin conditional render
                if(occlusion_cull)
                    glBeginConditionalRender(chunks[j].query, GL_QUERY_BY_REGION_WAIT);
                
                // draw chunk
                glBindVertexArray(chunks[j].vao);
                glDrawElements(GL_TRIANGLES, 6*chunks[j].quadcount, GL_UNSIGNED_INT, 0);
                
                // end conditional render
                if(occlusion_cull)
                    glEndConditionalRender();
            }
            i = j;
            maxdist += 2*chunksize;
        }
        
        // end timer query
        glEndQuery(GL_TIME_ELAPSED);
        
        // display timer query results from querycount frames before
        if(GL_TRUE == glIsQuery(queries[(current_query+1)%querycount]))
        {
            GLuint64 result;
            glGetQueryObjectui64v(queries[(current_query+1)%querycount], GL_QUERY_RESULT, &result);
            std::cout << result*1.e-6 << " ms/frame" << std::endl;
        }
        // advance query counter
        current_query = (current_query + 1)%querycount;
        
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
    
    for(size_t i = 0;i<chunks.size();++i)
    {    
        glDeleteVertexArrays(1, &chunks[i].vao);
        glDeleteBuffers(1, &chunks[i].vbo);
        glDeleteBuffers(1, &chunks[i].ibo);
        glDeleteVertexArrays(1, &chunks[i].bounding_vao);
        glDeleteBuffers(1, &chunks[i].bounding_vbo);
        glDeleteBuffers(1, &chunks[i].bounding_ibo);
        glDeleteQueries(1, &chunks[i].query);
    }
    
    glDeleteQueries(querycount, queries);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glDetachShader(query_shader_program, query_vertex_shader);	
    glDetachShader(query_shader_program, query_fragment_shader);
    glDeleteShader(query_vertex_shader);
    glDeleteShader(query_fragment_shader);
    glDeleteProgram(query_shader_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #10
0
int main()
{
    int width = 640;
    int height = 480;

    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);

    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }

    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);



    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code

    // the vertex shader simply passes through data
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = vposition;\n"
        "}\n";

    // the geometry shader creates the billboard quads
    std::string geometry_source =
        "#version 330\n"
        "uniform mat4 View;\n"
        "uniform mat4 Projection;\n"
        "layout (points) in;\n"
        "layout (triangle_strip, max_vertices = 4) out;\n"
        "out vec2 txcoord;\n"
        "void main() {\n"
        "   vec4 pos = View*gl_in[0].gl_Position;\n"
        "   txcoord = vec2(-1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2(-1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "}\n";

    // the fragment shader creates a bell like radial color distribution
    std::string fragment_source =
        "#version 330\n"
        "in vec2 txcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n"
        "   FragColor = s*vec4(0.3,0.3,1.0,1);\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, geometry_shader, fragment_shader;

    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length);
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }

    // create and compiler geometry shader
    geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
    source = geometry_source.c_str();
    length = geometry_source.size();
    glShaderSource(geometry_shader, 1, &source, &length);
    glCompileShader(geometry_shader);
    if(!check_shader_compile_status(geometry_shader))
    {
        return 1;
    }

    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }

    // create program
    shader_program = glCreateProgram();

    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, geometry_shader);
    glAttachShader(shader_program, fragment_shader);

    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);

    // obtain location of projection uniform
    GLint View_location = glGetUniformLocation(shader_program, "View");
    GLint Projection_location = glGetUniformLocation(shader_program, "Projection");



    const int particles = 128*1024;

    // randomly place particles in a cube
    std::vector<glm::vec3> vertexData(particles);
    std::vector<glm::vec3> velocity(particles);
    for(int i = 0; i<particles; ++i)
    {
        vertexData[i] = glm::vec3(0.5f-float(std::rand())/RAND_MAX,
                                  0.5f-float(std::rand())/RAND_MAX,
                                  0.5f-float(std::rand())/RAND_MAX);
        vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i];
    }


    int buffercount = 3;
    // generate vbos and vaos
    GLuint vao[buffercount], vbo[buffercount];
    glGenVertexArrays(buffercount, vao);
    glGenBuffers(buffercount, vbo);

    for(int i = 0; i<buffercount; ++i)
    {
        glBindVertexArray(vao[i]);

        glBindBuffer(GL_ARRAY_BUFFER, vbo[i]);

        // fill with initial data
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_DYNAMIC_DRAW);

        // set up generic attrib pointers
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
    }

    // "unbind" vao
    glBindVertexArray(0);

    // we are blending so no depth testing
    glDisable(GL_DEPTH_TEST);

    // enable blending
    glEnable(GL_BLEND);
    //  and set the blend function to result = 1*source + 1*destination
    glBlendFunc(GL_ONE, GL_ONE);

    // define spheres for the particles to bounce off
    const int spheres = 3;
    glm::vec3 center[spheres];
    float radius[spheres];
    center[0] = glm::vec3(0,12,1);
    radius[0] = 3;
    center[1] = glm::vec3(-3,0,0);
    radius[1] = 7;
    center[2] = glm::vec3(5,-10,0);
    radius[2] = 12;

    // physical parameters
    float dt = 1.0f/60.0f;
    glm::vec3 g(0.0f, -9.81f, 0.0f);
    float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f

    int current_buffer=0;
    running = true;
    while(running)
    {
        // get the time in seconds
        float t = glfwGetTime();

        // terminate on escape
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }

        // update physics
        for(int i = 0; i<particles; ++i)
        {
            // resolve sphere collisions
            for(int j = 0; j<spheres; ++j)
            {
                glm::vec3 diff = vertexData[i]-center[j];
                float dist = glm::length(diff);
                if(dist<radius[j] && glm::dot(diff, velocity[i])<0.0f)
                    velocity[i] -= bounce*diff/(dist*dist)*glm::dot(diff, velocity[i]);
            }
            // euler iteration
            velocity[i] += dt*g;
            vertexData[i] += dt*velocity[i];
            // reset particles that fall out to a starting position
            if(vertexData[i].y<-30.0)
            {
                vertexData[i] = glm::vec3(
                                    0.5f-float(std::rand())/RAND_MAX,
                                    0.5f-float(std::rand())/RAND_MAX,
                                    0.5f-float(std::rand())/RAND_MAX
                                );
                vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i];
                velocity[i] = glm::vec3(0,0,0);
            }
        }

        // bind a buffer to upload to
        glBindBuffer(GL_ARRAY_BUFFER, vbo[(current_buffer+buffercount-1)%buffercount]);

        // explicitly invalidate the buffer
        glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), 0, GL_DYNAMIC_DRAW);

        // map the buffer
        glm::vec3 *mapped =
            reinterpret_cast<glm::vec3*>(
                glMapBufferRange(GL_ARRAY_BUFFER, 0,
                                 sizeof(glm::vec3)*vertexData.size(),
                                 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT
                                )
            );

        // copy data into the mapped memory
        std::copy(vertexData.begin(), vertexData.end(), mapped);

        // unmap the buffer
        glUnmapBuffer(GL_ARRAY_BUFFER);


        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // use the shader program
        glUseProgram(shader_program);

        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);

        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f));

        // make the camera rotate around the origin
        View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f));
        View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f));

        // set the uniform
        glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View));
        glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection));

        // bind the current vao
        glBindVertexArray(vao[current_buffer]);

        // draw
        glDrawArrays(GL_POINTS, 0, particles);

        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;
        }

        // finally swap buffers
        glfwSwapBuffers();

        // advance buffer index
        current_buffer = (current_buffer + 1) % buffercount;
    }

    // delete the created objects

    glDeleteVertexArrays(buffercount, vao);
    glDeleteBuffers(buffercount, vbo);

    glDetachShader(shader_program, vertex_shader);
    glDetachShader(shader_program, geometry_shader);
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(geometry_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #11
0
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    } 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code
    
    // the vertex shader simply passes through data
    std::string vertex_source =
        "#version 430\n"
        "layout(location = 0) in vec4 vposition;\n"
        "void main() {\n"
        "   gl_Position = vposition;\n"
        "}\n";
    
    // the geometry shader creates the billboard quads
    std::string geometry_source =
        "#version 430\n"
        "uniform mat4 View;\n"
        "uniform mat4 Projection;\n"
        "layout (points) in;\n"
        "layout (triangle_strip, max_vertices = 4) out;\n"
        "out vec2 txcoord;\n"
        "void main() {\n"
        "   vec4 pos = View*gl_in[0].gl_Position;\n"
        "   txcoord = vec2(-1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1,-1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2(-1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "   txcoord = vec2( 1, 1);\n"
        "   gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n"
        "   EmitVertex();\n"
        "}\n";    
    
    // the fragment shader creates a bell like radial color distribution    
    std::string fragment_source =
        "#version 330\n"
        "in vec2 txcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n"
        "   FragColor = s*vec4(0.3,0.3,1.0,1);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, geometry_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
    
    // create and compiler geometry shader
    geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
    source = geometry_source.c_str();
    length = geometry_source.size();
    glShaderSource(geometry_shader, 1, &source, &length); 
    glCompileShader(geometry_shader);
    if(!check_shader_compile_status(geometry_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, geometry_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint View_location = glGetUniformLocation(shader_program, "View");
    GLint Projection_location = glGetUniformLocation(shader_program, "Projection");

    std::string compute_source =
        "#version 430\n"
        "layout(local_size_x=256) in;\n"
        
        "uniform vec3 center[3];\n"
        "uniform float radius[3];\n"
        "uniform vec3 g;\n"
        "uniform float dt;\n"
        "uniform float bounce;\n"
        "uniform int seed;\n"
        "uniform layout(rgba32f) imageBuffer particles;\n"
                
        "float hash(int x) {\n"
        "   x = x*1235167 + int(gl_GlobalInvocationID)*948737 + seed*9284365;\n"
        "   x = (x >> 13) ^ x;\n"
        "   return ((x * (x * x * 60493 + 19990303) + 1376312589) & 0x7fffffff)/float(0x7fffffff-1);\n"
        "}\n"
        
        "void main() {\n"
        "   int index = int(gl_GlobalInvocationID);\n"
        "   vec3 inposition = imageLoad(particles, 2*index).xyz;\n"
        "   vec3 invelocity = imageLoad(particles, 2*index+1).xyz;\n"
        "   vec3 outvelocity = invelocity;\n"
        "   for(int j = 0;j<3;++j) {\n"
        "       vec3 diff = inposition-center[j];\n"
        "       float dist = length(diff);\n"
        "       float vdot = dot(diff, invelocity);\n"
        "       if(dist<radius[j] && vdot<0.0)\n"
        "           outvelocity -= bounce*diff*vdot/(dist*dist);\n"
        "   }\n"
        "   outvelocity += dt*g;\n"
        "   vec3 outposition = inposition + dt*outvelocity;\n"
        "   if(outposition.y < -30.0)\n"
        "   {\n"
        "       outvelocity = vec3(0,0,0);\n"
        "       outposition = 0.5-vec3(hash(3*index+0),hash(3*index+1),hash(3*index+2));\n"
        "       outposition = vec3(0,20,0) + 5.0*outposition;\n"
        "   }\n"
        "   imageStore(particles, 2*index, vec4(outposition,1));\n"
        "   imageStore(particles, 2*index+1, vec4(outvelocity,1));\n"
        "}\n";
   
    // program and shader handles
    GLuint compute_program, compute_shader;

    // create and compiler vertex shader
    compute_shader = glCreateShader(GL_COMPUTE_SHADER);
    source = compute_source.c_str();
    length = compute_source.size();
    glShaderSource(compute_shader, 1, &source, &length); 
    glCompileShader(compute_shader);
    if(!check_shader_compile_status(compute_shader))
    {
        return 1;
    }

    // create program
    compute_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(compute_program, compute_shader);
   
    // link the program and check for errors
    glLinkProgram(compute_program);
    check_program_link_status(compute_program);

    GLint center_location = glGetUniformLocation(compute_program, "center");
    GLint radius_location = glGetUniformLocation(compute_program, "radius");
    GLint g_location = glGetUniformLocation(compute_program, "g");
    GLint dt_location = glGetUniformLocation(compute_program, "dt");
    GLint bounce_location = glGetUniformLocation(compute_program, "bounce");
    GLint seed_location = glGetUniformLocation(compute_program, "seed");
    GLint particles_location = glGetUniformLocation(compute_program, "particles");
   
    const int particles = 128*1024;

    // randomly place particles in a cube
    std::vector<glm::vec4> vertexData(2*particles);
    for(int i = 0;i<particles;++i)
    {
        // initial position
        vertexData[2*i+0] = glm::vec4(
                                0.5f-float(std::rand())/RAND_MAX,
                                0.5f-float(std::rand())/RAND_MAX,
                                0.5f-float(std::rand())/RAND_MAX,
                                0
                            );
        vertexData[2*i+0] = glm::vec4(0.0f,20.0f,0.0f,1) + 5.0f*vertexData[2*i+0];
        
        // initial velocity
        vertexData[2*i+1] = glm::vec4(0,0,0,0);
    }
    
    // generate vbos and vaos
    GLuint vao, vbo;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    

    glBindVertexArray(vao);
        
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // fill with initial data
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW);
                        
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
    // set up generic attrib pointers
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 4*sizeof(GLfloat));


    // "unbind" vao
    glBindVertexArray(0);
    
    // texture handle
    GLuint buffer_texture;
    
    // generate and bind the buffer texture
    glGenTextures(1, &buffer_texture);
    glBindTexture(GL_TEXTURE_BUFFER, buffer_texture);
    
    // tell the buffer texture to use 
    glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, vbo);
    
    
    
    // we are blending so no depth testing
    glDisable(GL_DEPTH_TEST);
    
    // enable blending
    glEnable(GL_BLEND);
    //  and set the blend function to result = 1*source + 1*destination
    glBlendFunc(GL_ONE, GL_ONE);

    // define spheres for the particles to bounce off
    const int spheres = 3;
    glm::vec3 center[spheres];
    float radius[spheres];
    center[0] = glm::vec3(0,12,1);
    radius[0] = 3;
    center[1] = glm::vec3(-3,0,0);
    radius[1] = 7;
    center[2] = glm::vec3(5,-10,0);
    radius[2] = 12;

    // physical parameters
    float dt = 1.0f/60.0f;
    glm::vec3 g(0.0f, -9.81f, 0.0f);
    float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f

    int current_buffer=0;
    running = true;
    while(running)
    {   
        // get the time in seconds
        float t = glfwGetTime();
        
        // terminate on excape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }



        // use the transform shader program
        glUseProgram(compute_program);

        // set the uniforms
        glUniform3fv(center_location, 3, reinterpret_cast<GLfloat*>(center)); 
        glUniform1fv(radius_location, 3, reinterpret_cast<GLfloat*>(radius));
        glUniform3fv(g_location, 1, glm::value_ptr(g));
        glUniform1f(dt_location, dt);
        glUniform1f(bounce_location, bounce);
        glUniform1i(seed_location, std::rand());
        
        glBindImageTexture(0, buffer_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
        glUniform1i(particles_location, 0);

        glDispatchCompute(particles/256, 1, 1);

        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 
        View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); 
        
        // set the uniform
        glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); 
        glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); 
        
        // bind the current vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_POINTS, 0, particles);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteTextures(1, &buffer_texture);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, geometry_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(geometry_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glDetachShader(compute_program, compute_shader);	
    glDeleteShader(compute_shader);
    glDeleteProgram(compute_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
   
    UserData userdata;
    userdata.running = true;
    
    GLWTConfig glwt_config;
    glwt_config.red_bits = 8;
    glwt_config.green_bits = 8;
    glwt_config.blue_bits = 8;
    glwt_config.alpha_bits = 8;
    glwt_config.depth_bits = 24;
    glwt_config.stencil_bits = 8;
    glwt_config.samples = 0;
    glwt_config.sample_buffers = 0;
    glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE;
    glwt_config.api_version_major = 3;
    glwt_config.api_version_minor = 3;
    
    GLWTAppCallbacks app_callbacks;
    app_callbacks.error_callback = error_callback;
    app_callbacks.userdata = &userdata;
    
    if(glwtInit(&glwt_config, &app_callbacks) != 0)
    {
        std::cerr << "failed to init GLWT" << std::endl;
        return 1;
    }
 
    GLWTWindowCallbacks win_callbacks;
    win_callbacks.close_callback = close_callback;
    win_callbacks.expose_callback = 0;
    win_callbacks.resize_callback = 0;
    win_callbacks.show_callback = 0;
    win_callbacks.focus_callback = 0;
    win_callbacks.key_callback = key_callback,
    win_callbacks.motion_callback = 0;
    win_callbacks.button_callback = 0;
    win_callbacks.mouseover_callback = 0;
    win_callbacks.userdata = &userdata;
    
    // create a window
    GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0);
    if(window == 0)
    {
        std::cerr << "failed to open window" << std::endl;
        glwtQuit();
        return 1;
    }
    
    if (glxwInit())
    {
        std::cerr << "failed to init GLXW" << std::endl;
        glwtWindowDestroy(window);
        glwtQuit();
        return 1;
    }
    
    glwtWindowShow(window, 1);
    glwtMakeCurrent(window);
    glwtSwapInterval(window, 1);
 
    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "uniform mat4 ViewProjection;\n" // the projection matrix uniform
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "layout(location = 2) in vec3 voffset;\n" // the per instance offset
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = ViewProjection*(vposition + vec4(voffset, 0));\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;
 
    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // obtain location of projection uniform
    GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection");
    
    
    // vao and vbo handles
    GLuint vao, vbo, tbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a cube
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
    // face 0:
       1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 3
 
    // face 1:
       1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 2
       1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 3
 
    // face 2:
       1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 0
       1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 1
      -1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 2
      -1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      
    // face 3:
       1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 1
      -1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 3
 
    // face 4:
      -1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 1
      -1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 3
 
    // face 5:
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 0
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 1
       1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 3
    }; // 6 faces with 4 vertices with 6 components (floats)
 
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
 
    
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        // face 0:
        0,1,2,      // first triangle
        2,1,3,      // second triangle
        // face 1:
        4,5,6,      // first triangle
        6,5,7,      // second triangle
        // face 2:
        8,9,10,     // first triangle
        10,9,11,    // second triangle
        // face 3:
        12,13,14,   // first triangle
        14,13,15,   // second triangle
        // face 4:
        16,17,18,   // first triangle
        18,17,19,   // second triangle
        // face 5:
        20,21,22,   // first triangle
        22,21,23,   // second triangle
    };
 
    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW);
    

    // generate and bind the vertex buffer object containing the
    // instance offsets
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
            
    // the offsets
    GLfloat translationData[] = {
                 2.0f, 2.0f, 2.0f,  // cube 0
                 2.0f, 2.0f,-2.0f,  // cube 1
                 2.0f,-2.0f, 2.0f,  // cube 2
                 2.0f,-2.0f,-2.0f,  // cube 3
                -2.0f, 2.0f, 2.0f,  // cube 4
                -2.0f, 2.0f,-2.0f,  // cube 5
                -2.0f,-2.0f, 2.0f,  // cube 6
                -2.0f,-2.0f,-2.0f,  // cube 7
    }; // 8 offsets with 3 components each
 
    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*8, translationData, GL_STATIC_DRAW);
                    
    // set up generic attrib pointers
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
    
    // a attrib divisor of 1 means that attribute 2 will advance once
    // every instance (0 would mean once per vertex) 
    glVertexAttribDivisor(2, 1);
    
    
    // "unbind" vao
    glBindVertexArray(0);
 
    
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);
 
    while(userdata.running)
    {   
        // get the time in seconds
        float t = glwtGetNanoTime()*1.e-9f;
        
        // update events
        glwtEventHandle(0);
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 
        
        glm::mat4 ViewProjection = Projection*View;
        
        // set the uniform
        glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        // the additional parameter indicates how many instances to render
        glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            userdata.running = false;       
        }
        
        // finally swap buffers
        glwtSwapBuffers(window);       
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    glDeleteBuffers(1, &tbo);
    
    glDetachShader(shader_program, vertex_shader);      
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glwtWindowDestroy(window);
    glwtQuit();
    return 0;
}
Пример #13
0
int main()
{
    int width = 640;
    int height = 480;
   
    UserData userdata;
    userdata.running = true;
    
    GLWTConfig glwt_config;
    glwt_config.red_bits = 8;
    glwt_config.green_bits = 8;
    glwt_config.blue_bits = 8;
    glwt_config.alpha_bits = 8;
    glwt_config.depth_bits = 24;
    glwt_config.stencil_bits = 8;
    glwt_config.samples = 0;
    glwt_config.sample_buffers = 0;
    glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE;
    glwt_config.api_version_major = 3;
    glwt_config.api_version_minor = 3;
    
    GLWTAppCallbacks app_callbacks;
    app_callbacks.error_callback = error_callback;
    app_callbacks.userdata = &userdata;
    
    if(glwtInit(&glwt_config, &app_callbacks) != 0)
    {
        std::cerr << "failed to init GLWT" << std::endl;
        return 1;
    }
 
    GLWTWindowCallbacks win_callbacks;
    win_callbacks.close_callback = close_callback;
    win_callbacks.expose_callback = 0;
    win_callbacks.resize_callback = 0;
    win_callbacks.show_callback = 0;
    win_callbacks.focus_callback = 0;
    win_callbacks.key_callback = key_callback,
    win_callbacks.motion_callback = 0;
    win_callbacks.button_callback = 0;
    win_callbacks.mouseover_callback = 0;
    win_callbacks.userdata = &userdata;
    
    // create a window
    GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0);
    if(window == 0)
    {
        std::cerr << "failed to open window" << std::endl;
        glwtQuit();
        return 1;
    }
    
    if (glxwInit())
    {
        std::cerr << "failed to init GLXW" << std::endl;
        glwtWindowDestroy(window);
        glwtQuit();
        return 1;
    }
    
    glwtWindowShow(window, 1);
    glwtMakeCurrent(window);
    glwtSwapInterval(window, 1);

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec2 vtexcoord;\n"
        "out vec2 ftexcoord;\n"
        "void main() {\n"
        "   ftexcoord = vtexcoord;\n"
        "   gl_Position = vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "uniform sampler2D tex;\n" // texture uniform
        "in vec2 ftexcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = texture(tex, ftexcoord);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // get texture uniform location
    GLint texture_location = glGetUniformLocation(shader_program, "tex");
    
    // vao and vbo handle
    GLuint vao, vbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a fullscreen quad (this time with texture coords)
    GLfloat vertexData[] = {
    //  X     Y     Z           U     V     
       1.0f, 1.0f, 0.0f,       1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, // vertex 1
       1.0f,-1.0f, 0.0f,       1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 0.0f,       0.0f, 0.0f, // vertex 3
    }; // 4 vertices with 5 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW);
    
    // "unbind" vao
    glBindVertexArray(0);

    // texture handle
    GLuint texture;
    
    // generate texture
    glGenTextures(1, &texture);

    // bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // create some image data
    std::vector<GLubyte> image(4*width*height);
    for(int j = 0;j<height;++j)
        for(int i = 0;i<width;++i)
        {
            size_t index = j*width + i;
            image[4*index + 0] = 0xFF*(j/10%2)*(i/10%2); // R
            image[4*index + 1] = 0xFF*(j/13%2)*(i/13%2); // G
            image[4*index + 2] = 0xFF*(j/17%2)*(i/17%2); // B
            image[4*index + 3] = 0xFF;                   // A
        }
    
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    // set texture content
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);
    
    while(userdata.running)
    {
        // update events
        glwtEventHandle(0);
            
        // clear first
        glClear(GL_COLOR_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);

        // bind texture to texture unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        
        // set texture uniform
        glUniform1i(texture_location, 0);
        
        // bind the vao
        glBindVertexArray(vao);
        
        // draw
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            userdata.running = false;       
        }
        
        // finally swap buffers
        glwtSwapBuffers(window);       
    }
    
    // delete the created objects
    
    glDeleteTextures(1, &texture);
    
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glwtWindowDestroy(window);
    glwtQuit();
    return 0;
}
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // select opengl version 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(std140) uniform Matrices {\n"
        "   mat4 ViewProjection;\n"
        "   mat4 Model[8];\n"
        "};\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = ViewProjection*Model[gl_InstanceID]*vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);

    // obtain location of the uniform block
    GLuint Matrices_binding = 0;
    GLint uniform_block_index = glGetUniformBlockIndex(shader_program, "Matrices");
    // assign the block binding
    glUniformBlockBinding(shader_program, uniform_block_index, Matrices_binding);
    
    // create uniform buffer
    GLuint ubo;
    glGenBuffers(1, &ubo);
    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
    glBufferData(GL_UNIFORM_BUFFER, 9*sizeof(float)*4*4, 0, GL_STREAM_DRAW);
    
    // fill the Model matrix array
    glm::mat4 ModelMatrices[8];
    ModelMatrices[0] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f, 2.0f));
    ModelMatrices[1] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f,-2.0f));
    ModelMatrices[2] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f, 2.0f));
    ModelMatrices[3] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f,-2.0f));
    ModelMatrices[4] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f, 2.0f));
    ModelMatrices[5] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f,-2.0f));
    ModelMatrices[6] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f, 2.0f));
    ModelMatrices[7] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f,-2.0f));
    
    glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float)*4*4, 8*sizeof(float)*4*4, ModelMatrices);
    
    
    // vao and vbo handle
    GLuint vao, vbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a cube
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
    // face 0:
       1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 0.0f, // vertex 3

    // face 1:
       1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 2
       1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 0.0f, // vertex 3

    // face 2:
       1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 0
       1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 1
      -1.0f, 1.0f, 1.0f,       0.0f, 0.0f, 1.0f, // vertex 2
      -1.0f, 1.0f,-1.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      
    // face 3:
       1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 0
       1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 1
      -1.0f, 1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 1.0f, 0.0f, // vertex 3

    // face 4:
      -1.0f, 1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 1
      -1.0f,-1.0f, 1.0f,       0.0f, 1.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       0.0f, 1.0f, 1.0f, // vertex 3

    // face 5:
       1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 0
      -1.0f,-1.0f, 1.0f,       1.0f, 0.0f, 1.0f, // vertex 1
       1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 2
      -1.0f,-1.0f,-1.0f,       1.0f, 0.0f, 1.0f, // vertex 3
    }; // 6 faces with 4 vertices with 6 components (floats)

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        // face 0:
        0,1,2,      // first triangle
        2,1,3,      // second triangle
        // face 1:
        4,5,6,      // first triangle
        6,5,7,      // second triangle
        // face 2:
        8,9,10,     // first triangle
        10,9,11,    // second triangle
        // face 3:
        12,13,14,   // first triangle
        14,13,15,   // second triangle
        // face 4:
        16,17,18,   // first triangle
        18,17,19,   // second triangle
        // face 5:
        20,21,22,   // first triangle
        22,21,23,   // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW);
    
    // "unbind" vao
    glBindVertexArray(0);

    
    // we are drawing 3d objects so we want depth testing
    glEnable(GL_DEPTH_TEST);

    running = true;
    while(running)
    {   
        // get the time in seconds
        float t = glfwGetTime();
        
        // terminate on escape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);
        
        // calculate ViewProjection matrix
        glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f);
        
        // translate the world/view position
        glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
        
        // make the camera rotate around the origin
        View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 
        
        glm::mat4 ViewProjection = Projection*View;
        
        // set the ViewProjection in the uniform buffer
        glBindBuffer(GL_UNIFORM_BUFFER, ubo);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float)*4*4, glm::value_ptr(ViewProjection));
        glBindBufferRange(GL_UNIFORM_BUFFER, Matrices_binding, ubo, 0, sizeof(float)*4*4*9);
        
        // bind the vao
        glBindVertexArray(vao);

        // draw
        // the additional parameter indicates how many instances to render
        glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
        
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);
    
    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #15
0
int main() {
    int width = 640;
    int height = 480;

    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) {
        std::cerr << "failed to init SDL" << std::endl;
        return 1;
    }

    // select opengl version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);

    // create a window
    SDL_Window *window;
    if((window = SDL_CreateWindow("SDL2", 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)) == 0) {
        std::cerr << "failed to open window" << std::endl;
        SDL_Quit();
        return 1;
    }

    SDL_GLContext context = SDL_GL_CreateContext(window);

    if(gl3wInit()) {
        std::cerr << "failed to init GL3W" << std::endl;
        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = vposition;\n"
        "}\n";

    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;

    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length);
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader)) {
        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader)) {
        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // create program
    shader_program = glCreateProgram();

    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);

    // link the program and check for errors
    glLinkProgram(shader_program);
    if(!check_program_link_status(shader_program)) {
        SDL_GL_DeleteContext(context);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // vao and vbo handle
    GLuint vao, vbo;

    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // generate and bind the buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // data for a fullscreen quad
    GLfloat vertexData[] = {
        //  X     Y     Z           R     G     B
        1.0f, 1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 0
        -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 1
        1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 2
        1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 3
        -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 4
        -1.0f,-1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 5
    }; // 6 vertices with 6 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW);

    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));

    bool closed = false;
    while(!closed) {
        SDL_Event event;
        while(SDL_PollEvent(&event)) {
            if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) {
                closed = true;
            }
        }

        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        // use the shader program
        glUseProgram(shader_program);

        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_TRIANGLES, 0, 6);

        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cerr << error << std::endl;
            break;
        }

        // finally swap buffers
        SDL_GL_SwapWindow(window);
    }

    // delete the created objects

    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);

    glDetachShader(shader_program, vertex_shader);
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    SDL_GL_DeleteContext(context);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}
Пример #16
0
int main()
{
    int width = 640;
    int height = 480;
    
    if(glfwInit() == GL_FALSE)
    {
        std::cerr << "failed to init GLFW" << std::endl;
        return 1;
    }

    // sadly glew doesn't play nice with core profiles... 
    glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
    glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
 
    // create a window
    if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE)
    {
        std::cerr << "failed to open window" << std::endl;
        glfwTerminate();
        return 1;
    }
    
    // setup windows close callback
    glfwSetWindowCloseCallback(closedWindow);
    
    
    
    if (gl3wInit())
    {
        std::cerr << "failed to init GL3W" << std::endl;
        glfwCloseWindow();
        glfwTerminate();
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec2 vtexcoord;\n"
        "out vec2 ftexcoord;\n"
        "void main() {\n"
        "   ftexcoord = vtexcoord;\n"
        "   gl_Position = vposition;\n"
        "}\n";
        
    std::string fragment_source =
        "#version 330\n"
        "uniform sampler2D tex;\n" // texture uniform
        "in vec2 ftexcoord;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = texture(tex, ftexcoord);\n"
        "}\n";
   
    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;
    
    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length); 
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader))
    {
        return 1;
    }
 
    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);   
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader))
    {
        return 1;
    }
    
    // create program
    shader_program = glCreateProgram();
    
    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    
    // link the program and check for errors
    glLinkProgram(shader_program);
    check_program_link_status(shader_program);
    
    // get texture uniform location
    GLint texture_location = glGetUniformLocation(shader_program, "tex");
    
    // vao and vbo handle
    GLuint vao, vbo, ibo;
 
    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // generate and bind the vertex buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
            
    // data for a fullscreen quad (this time with texture coords)
    GLfloat vertexData[] = {
    //  X     Y     Z           U     V     
       1.0f, 1.0f, 0.0f,       1.0f, 1.0f, // vertex 0
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, // vertex 1
       1.0f,-1.0f, 0.0f,       1.0f, 0.0f, // vertex 2
      -1.0f,-1.0f, 0.0f,       0.0f, 0.0f, // vertex 3
    }; // 4 vertices with 5 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, vertexData, GL_STATIC_DRAW);
                    
           
    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));
 
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));
    
    
    // generate and bind the index buffer object
    glGenBuffers(1, &ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
            
    GLuint indexData[] = {
        0,1,2, // first triangle
        2,1,3, // second triangle
    };

    // fill with data
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW);
    
    // "unbind" vao
    glBindVertexArray(0);

    // texture handle
    GLuint texture;
    
    // generate texture
    glGenTextures(1, &texture);

    // bind the texture
    glBindTexture(GL_TEXTURE_2D, texture);

    // create some image data
    std::vector<GLubyte> image(4*width*height);
    for(int j = 0;j<height;++j)
        for(int i = 0;i<width;++i)
        {
            size_t index = j*width + i;
            image[4*index + 0] = 0xFF*(j/10%2)*(i/10%2); // R
            image[4*index + 1] = 0xFF*(j/13%2)*(i/13%2); // G
            image[4*index + 2] = 0xFF*(j/17%2)*(i/17%2); // B
            image[4*index + 3] = 0xFF;                   // A
        }
    
    // set texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    // set texture content
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]);
    
    running = true;
    while(running)
    {    
        // terminate on excape 
        if(glfwGetKey(GLFW_KEY_ESC))
        {
            running = false;
        }
        
        // clear first
        glClear(GL_COLOR_BUFFER_BIT);
        
        // use the shader program
        glUseProgram(shader_program);

        // bind texture to texture unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        
        // set texture uniform
        glUniform1i(texture_location, 0);
        
        // bind the vao
        glBindVertexArray(vao);
        
        // draw
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
       
        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR)
        {
            std::cerr << gluErrorString(error);
            running = false;       
        }
        
        // finally swap buffers
        glfwSwapBuffers();       
    }
    
    // delete the created objects
    
    glDeleteTextures(1, &texture);
    
    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);
    glDeleteBuffers(1, &ibo);
    
    glDetachShader(shader_program, vertex_shader);	
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    glfwCloseWindow();
    glfwTerminate();
    return 0;
}
Пример #17
0
int main() {
    int width = 640;
    int height = 480;

    sf::Window window(sf::VideoMode(width, height), "sfml", sf::Style::Default, sf::ContextSettings(0,0,0,3,3));

    // using glew since sfml doesn create a core context
    if(glewInit()) {
        std::cerr << "failed to init GLEW" << std::endl;
        return 1;
    }

    // shader source code
    std::string vertex_source =
        "#version 330\n"
        "layout(location = 0) in vec4 vposition;\n"
        "layout(location = 1) in vec4 vcolor;\n"
        "out vec4 fcolor;\n"
        "void main() {\n"
        "   fcolor = vcolor;\n"
        "   gl_Position = vposition;\n"
        "}\n";

    std::string fragment_source =
        "#version 330\n"
        "in vec4 fcolor;\n"
        "layout(location = 0) out vec4 FragColor;\n"
        "void main() {\n"
        "   FragColor = fcolor;\n"
        "}\n";

    // program and shader handles
    GLuint shader_program, vertex_shader, fragment_shader;

    // we need these to properly pass the strings
    const char *source;
    int length;

    // create and compiler vertex shader
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    source = vertex_source.c_str();
    length = vertex_source.size();
    glShaderSource(vertex_shader, 1, &source, &length);
    glCompileShader(vertex_shader);
    if(!check_shader_compile_status(vertex_shader)) {
        return 1;
    }

    // create and compiler fragment shader
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    source = fragment_source.c_str();
    length = fragment_source.size();
    glShaderSource(fragment_shader, 1, &source, &length);
    glCompileShader(fragment_shader);
    if(!check_shader_compile_status(fragment_shader)) {
        return 1;
    }

    // create program
    shader_program = glCreateProgram();

    // attach shaders
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);

    // link the program and check for errors
    glLinkProgram(shader_program);
    if(!check_program_link_status(shader_program)) {
        return 1;
    }

    // vao and vbo handle
    GLuint vao, vbo;

    // generate and bind the vao
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    // generate and bind the buffer object
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);

    // data for a fullscreen quad
    GLfloat vertexData[] = {
    //  X     Y     Z           R     G     B
       1.0f, 1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 0
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 1
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 2
       1.0f,-1.0f, 0.0f,       0.0f, 0.0f, 1.0f, // vertex 3
      -1.0f, 1.0f, 0.0f,       0.0f, 1.0f, 0.0f, // vertex 4
      -1.0f,-1.0f, 0.0f,       1.0f, 0.0f, 0.0f, // vertex 5
    }; // 6 vertices with 6 components (floats) each

    // fill with data
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW);

    // set up generic attrib pointers
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat));

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat));

    bool closed = false;
    while(!closed) {
        sf::Event event;
        while(window.pollEvent(event)) {
            if(event.type == sf::Event::Closed) {
                closed = true;
            }
        }

        // clear first
        glClear(GL_COLOR_BUFFER_BIT);

        // use the shader program
        glUseProgram(shader_program);

        // bind the vao
        glBindVertexArray(vao);

        // draw
        glDrawArrays(GL_TRIANGLES, 0, 6);

        // check for errors
        GLenum error = glGetError();
        if(error != GL_NO_ERROR) {
            std::cerr << error << std::endl;
            break;
        }

        // finally swap buffers
        window.display();
    }

    // delete the created objects

    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(1, &vbo);

    glDetachShader(shader_program, vertex_shader);
    glDetachShader(shader_program, fragment_shader);
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    glDeleteProgram(shader_program);

    return 0;
}