Problems with perspective in Open_GL - c++

Could someone please explain me what is wrong in my code? When I try to run it I get a black window, but if I don't set the perspective matrix as I do in the 31th line I get the right solid (a pyramid) drawn on the window. Here's the main of the code. In the vertex shader I just define model, view and projection as uniform 4x4 matrices and multiply them by the poistion of the vertex and pass the colors of the vertices to the fragment shader. I don't think the problem is in those files but if you need them I'll post them.
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <string>
#include <fstream>
#include <sstream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
GLuint IBO, VBO, gModelLocation, gViewLocation, gProjectionLocation;
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
const char* VSfileName = "vertex.vs";
const char* FSfileName = "fragment.fs";
void RenderSceneCB()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glm::mat4 model;
model = glm::rotate( model, 0.0f, glm::normalize( glm::vec3( 1.0, 0.0, 0.0 ) ) );
glm::mat4 view;
view = glm::translate( view, glm::vec3( 0.0f, 0.0f, 0.0f ) );
glm::mat4 projection;
projection = glm::perspective( 90.0f, float( WINDOW_WIDTH ) / float( WINDOW_HEIGHT ), 0.1f, 100.0f );
glUniformMatrix4fv( gModelLocation, 1, GL_FALSE, &model[ 0 ][ 0 ] );
glUniformMatrix4fv( gViewLocation, 1, GL_FALSE, &view[ 0 ][ 0 ] );
glUniformMatrix4fv( gProjectionLocation, 1, GL_FALSE, glm::value_ptr( projection ) );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IBO );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)( 15 * sizeof( GLfloat ) ) );
glEnableVertexAttribArray( 1 );
glDrawElements( GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0 );
//glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray( 1 );
glDisableVertexAttribArray( 0 );
glutSwapBuffers();
}
void InizializeGlutCallBacks()
{
glutDisplayFunc( RenderSceneCB );
glutIdleFunc( RenderSceneCB );
}
void InizializeVertices()
{
GLfloat Vertices[ 9 ][ 3 ]
{
{ -0.5f, 0.5f, 0.0f},
{ 0.5f, -0.5f, 0.0f },
{ 0.5f, 0.5f, 0.0f},
{ -0.5f, -0.5f, 0.0f },
{ 0.0f, 0.0f, 1.0f},
{ 1.0f, 0.0f, 0.0f},
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f}
};
GLint Indices[ 12 ]
{
0,2,4,0,3,4,1,2,4,1,3,4
};
glGenBuffers( 1, &VBO );
glGenBuffers( 1, &IBO );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IBO );
glBufferData( GL_ARRAY_BUFFER, sizeof( Vertices ), Vertices, GL_STATIC_DRAW );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( Indices ), Indices, GL_STATIC_DRAW );
}
void AddShader( GLuint ShaderProgram, const char* ShaderSource, GLenum ShaderType )
{
GLuint ShaderObj = glCreateShader( ShaderType );
if( ShaderObj == 0 )
{
fprintf( stderr, "Error creating Shader Object %d \n", ShaderType );
}
const GLchar* p[ 1 ];
p[ 0 ] = ShaderSource;
GLint Lengths[ 1 ];
Lengths[ 0 ] = strlen( p[ 0 ] );
glShaderSource( ShaderObj, 1, p, Lengths );
glCompileShader( ShaderObj );
GLint success;
glGetShaderiv( ShaderObj, GL_COMPILE_STATUS, &success );
if( !success )
{
GLchar InfoLog[ 1024 ];
glGetShaderInfoLog( ShaderObj, 1024, NULL, InfoLog );
fprintf( stderr, "Error Compiling Shader %d: '%s' \n", ShaderType, InfoLog );
}
glAttachShader( ShaderProgram, ShaderObj );
}
void CompileShaders()
{
GLuint ShaderProgram = glCreateProgram();
if( ShaderProgram == 0 )
{
fprintf( stderr, "Error creating Shader Program \n" );
}
string vs, fs;
ifstream VertexFile;
ifstream FragmentFile;
VertexFile.open( VSfileName );
if( !VertexFile )
{
std::cout << "Error in opening vertex.vs \n";
exit( 1 );
}
FragmentFile.open( FSfileName );
if( !FragmentFile )
{
std::cout << "Error in opening fragment.fs \n";
exit( 1 );
}
stringstream VertexStream;
stringstream FragmentStream;
VertexStream << VertexFile.rdbuf();
FragmentStream << FragmentFile.rdbuf();
vs = VertexStream.str();
fs = FragmentStream.str();
AddShader( ShaderProgram, vs.c_str(), GL_VERTEX_SHADER );
AddShader( ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER );
glLinkProgram( ShaderProgram );
GLint success;
glGetProgramiv( ShaderProgram, GL_LINK_STATUS, &success );
if( !success )
{
GLchar InfoLog[ 1024 ];
glGetProgramInfoLog( ShaderProgram, 1024, NULL, InfoLog );
fprintf( stderr, "Error in linking Shader '%s' \n", InfoLog );
}
glValidateProgram( ShaderProgram );
glGetProgramiv( ShaderProgram, GL_VALIDATE_STATUS, &success );
if( !success )
{
GLchar InfoLog[ 1024 ];
glGetProgramInfoLog( ShaderProgram, 1024, NULL, InfoLog );
fprintf( stderr, "Error in linking Shader '%s' \n", InfoLog );
}
//gScaleLocation = glGetUniformLocation(ShaderProgram, "gScale");
gModelLocation = glGetUniformLocation( ShaderProgram, "gModel" );
gViewLocation = glGetUniformLocation( ShaderProgram, "gView" );
gProjectionLocation = glGetUniformLocation( ShaderProgram, "gProjection" );
glUseProgram( ShaderProgram );
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize( WINDOW_WIDTH, WINDOW_HEIGHT );
glutInitWindowPosition( 100, 100 );
glutCreateWindow( "Hello World" );
InizializeGlutCallBacks();
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
GLenum res = glewInit();
if( res != GLEW_OK )
{
std::cout << "Error, check please \n";
}
glViewport( 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT );
glEnable( GL_DEPTH_TEST );
// enable alpha support
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
InizializeVertices();
CompileShaders();
glutMainLoop();
system( "pause" );
return 0;
}

First of all you should initialize all the matrizes (see glm returning nan on simple translate):
glm::mat4 model(1.0f);
glm::mat4 view(1.0f);
glm::mat4 projection(1.0f);
The geometry has to be in the clip space. When you setup the projection, then you define a near plan of 0.1 and a far plane of 100.0. This both values define the near and the far clipping plane.
This means you can only "see" the geomentry with a Z-component in the range [0.1, 100.0].
Setup the view matrix, to solve your issue.
glm::mat4 view(1.0f);
view = glm::translate( view, glm::vec3( 0.0f, 0.0f, -1.0f ) );
Further:
See the GLM documentation of glm::perspective, version 0.9.8:
LM_FUNC_DECL tmat4x4<T, defaultp> glm::perspective(T fovy, T aspect, T near, T far)
Creates a matrix for a symetric perspective-view frustum based on the default handedness.
Parameters
fovy Specifies the field of view angle in the y direction. Expressed in radians.
At the same place is noted for the version 0.9.4 (glm::perspective, version 0.9.4):
fovy Expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise.
This is because the GLM in general changed from degrees to radians a while ago.
Setup the perspective projection matrix like this:
projection = glm::perspective(
90.0f * (float)M_PI / 180.0,
float( WINDOW_WIDTH ) / float( WINDOW_HEIGHT ),
0.1f, 100.0f );
Explanation:
The view matrix describes the direction and position from which the scene is looked at. The view matrix transforms from the wolrd space to the view (eye) space.
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. It transforms from eye space to the clip space, and the coordinates in the clip space are transformed to the normalized device coordinates (NDC) by dividing with the w component of the clip coordinates. The NDC are in range (-1,-1,-1) to (1,1,1). Every geometry which is out of the clippspace is clipped.
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport. The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).

Related

Interpolation of a vertex attribute

I am trying to pass in a distance as a vertex attribute from my c++ code into the shader which draws a line between two vertices.
Currently one line has distance 0 (start), and the other has distance 1.0. I would expect this value to be interpolated just like the colors, but it does not seem to work. Thus I would expect half of the line to be red and the other green, but the whole line turns out green.
Fragment shader code below, where dist in the vertex shader comes in from layout(location = 2) in float in_dist and is passed out as out float dist (no operations performed).
in float dist;
Fragment getFragment()
{
Fragment frag;
frag.depth = vs_positionScreenSpace.w;
frag.gPosition = vs_gPosition;
if(dist > 0.5){
frag.color = vec4(1.0,0.0,0.0,1.0);
}else{
frag.color = vec4(0.0,1.0,0.0,1.0);
}
frag.gNormal = vec4(0.0, 0.0, 1.0, 0.0);
return frag;
}
Vertex shader
layout(location = 0) in vec3 in_point_position;
layout(location = 1) in vec4 in_color;
layout(location = 2) in float in_dist;
out float dist;
void main() {
//somestuff....
dist = in_dist;
}
Workin' fine here:
MCVE:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <iostream>
#include <cstdarg>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
std::exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = R"GLSL(
#version 330 core
layout( location = 0 ) in vec4 inPos;
layout( location = 1 ) in float inDist;
out float dist;
void main()
{
dist = inDist;
gl_Position = inPos;
}
)GLSL";
const char* frag = R"GLSL(
#version 330 core
in float dist;
out vec4 outColor;
void main()
{
if( dist > 0.5 )
{
outColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}
else
{
outColor = vec4( 0.0, 1.0, 0.0, 1.0 );
}
}
)GLSL";
int main( int argc, char** argv )
{
glfwInit();
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
glfwMakeContextCurrent( window );
glewInit();
glfwSwapInterval( 1 );
GLuint prog = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram( prog );
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
GLuint vbo0 = 0;
glGenBuffers( 1, &vbo0 );
glBindBuffer( GL_ARRAY_BUFFER, vbo0 );
std::vector<float> data0 =
{
-0.5f, -0.5f,
0.5f, 0.5f,
};
glBufferData( GL_ARRAY_BUFFER, data0.size() * sizeof( std::vector<float>::value_type ), data0.data(), GL_STATIC_DRAW );
glVertexAttribPointer( 0 , 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
GLuint vbo1 = 0;
glGenBuffers( 1, &vbo1 );
glBindBuffer( GL_ARRAY_BUFFER, vbo1 );
std::vector<float> data1 =
{
0.0f, 1.0f,
};
glBufferData( GL_ARRAY_BUFFER, data1.size() * sizeof( std::vector<float>::value_type ), data1.data(), GL_STATIC_DRAW );
glVertexAttribPointer( 1 , 1, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 1 );
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
int w, h;
glfwGetFramebufferSize( window, &w, &h );
glViewport( 0, 0, w, h );
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( prog );
glBindVertexArray( vao );
glDrawArrays( GL_LINES, 0, 2 );
glfwSwapBuffers( window );
}
glfwDestroyWindow( window );
glfwTerminate();
}
Solved; The issue turned out to not be in the shader code, but in how the vertex attribute was defined att glVertexAttributePointer.

OpenGL not rendering anything at all

My program doesn't display anything on the screen. I've tried several things but nothing worked.
Here's my source, vertex and fragment shader:
Renderer.cpp:
#include "Renderer.h"
Renderer::Renderer( Camera& camera, float w, float h )
:
cam( camera ),
winW( w ),
winH( h )
{}
Renderer::~Renderer()
{
glDeleteBuffers( 1, &quad );
glDeleteBuffers( 1, &color );
glDeleteBuffers( 1, &UV );
glDeleteVertexArrays( 1, &vao );
}
void Renderer::load()
{
projectionMatrix = glm::mat4( 1.0f );
projectionMatrix = glm::perspective<float>( 45.0f, (float) winW / (float) winH, 0.01f, 100.0f );
shader.loadAndCompile( "Res/Shaders/std.vs", "Res/Shaders/std.fs" );
texture.loadTexture( "Res/Tex/sheet.png" );
texture.bind();
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
Vertex quadArray[] = {
{ -0.5, -0.5, 0.0 },
{ -0.5, 0.5, 0.0 },
{ 0.5, -0.5, 0.0 },
{ 0.5, -0.5, 0.0 },
{ 0.5, 0.5, 0.0 },
{ -0.5, 0.5, 0.0 }
};
glUseProgram( shader.getProgram() );
MVPLocation = glGetUniformLocation( shader.getProgram(), "MVP" );
glGenBuffers( 1, &quad );
glBindBuffer( GL_ARRAY_BUFFER, quad );
glBufferData( GL_ARRAY_BUFFER, sizeof( quadArray ), quadArray, GL_STATIC_DRAW );
glGenBuffers( 1, &color );
glBindBuffer( GL_ARRAY_BUFFER, color );
glBufferData( GL_ARRAY_BUFFER, 48, NULL, GL_STREAM_DRAW );
glGenBuffers( 1, &UV );
glBindBuffer( GL_ARRAY_BUFFER, UV );
glBufferData( GL_ARRAY_BUFFER, 48, NULL, GL_STREAM_DRAW );
}
void Renderer::translate( glm::vec3 pos )
{
this->transMatrix = glm::translate( glm::mat4( 1.0f ), pos );
}
void Renderer::translate( float x, float y, float z )
{
translate( glm::vec3( x, y, z ) );
}
void Renderer::rotate( float angle, glm::vec3 axis )
{
this->rotationMatrix = glm::rotate( glm::mat4( 1.0f ), angle, axis );
}
void Renderer::scale( glm::vec3 scale )
{
this->scaleMatrix = glm::scale( glm::mat4( 1.0f ), scale );
}
void Renderer::scale( float x, float y, float z )
{
scale( glm::vec3( x, y, z ) );
}
void Renderer::drawSpriteBillboarded( glm::vec3 pos, glm::vec3 lookAtPos, int w, int h, int uP, int vP, glm::vec4 col )
{
int texW = texture.getWidth(), texH = texture.getHeight();
float u = (float) uP / (float) texW, v = (float) vP / (float) texH, uEnd = (float) ( uP + w ) / (float) texW, vEnd = (float) ( vP + h ) / (float) texH;
Color colArray[] = {
{ col.r, col.g, col.b, col.a },
{ col.r, col.g, col.b, col.a },
{ col.r, col.g, col.b, col.a },
{ col.r, col.g, col.b, col.a },
{ col.r, col.g, col.b, col.a },
{ col.r, col.g, col.b, col.a }
};
Vertex uvArray[] = {
{ u, v },
{ u, vEnd },
{ uEnd, v },
{ uEnd, v },
{ uEnd, vEnd },
{ u, vEnd }
};
translate( pos );
glm::vec2 dist = glm::vec2( lookAtPos.x, lookAtPos.z ) - glm::vec2( pos.x, pos.z );
rotate( atan2f( dist.y, dist.x ), glm::vec3( 0, 1, 0 ) );
scale( w / 16 * 1.0, h / 16 * 1.0, 1.0 );
modelMatrix = transMatrix * rotationMatrix * scaleMatrix;
camTransMatrix = glm::translate( glm::mat4( 1.0f ), cam.getPos() );
camRotationMatrix = glm::rotate( camRotationMatrix, cam.getRotX(), glm::vec3( 1, 0, 0 ) );
camRotationMatrix = glm::rotate( camRotationMatrix, cam.getRotY(), glm::vec3( 0, 1, 0 ) );
camRotationMatrix = glm::rotate( camRotationMatrix, cam.getRotZ(), glm::vec3( 0, 0, 1 ) );
viewMatrix = camTransMatrix * camRotationMatrix;
modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix;
glUniformMatrix4fv( MVPLocation, 1, GL_FALSE, &modelViewProjectionMatrix[ 0 ][ 0 ] );
glBindBuffer( GL_ARRAY_BUFFER, quad );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0 );
glBindBuffer( GL_ARRAY_BUFFER, color );
glBufferData( GL_ARRAY_BUFFER, sizeof( colArray ), colArray, GL_STREAM_DRAW );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0 );
glBindBuffer( GL_ARRAY_BUFFER, UV );
glBufferData( GL_ARRAY_BUFFER, sizeof( uvArray ), uvArray, GL_STREAM_DRAW );
glEnableVertexAttribArray( 2 );
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
}
void Renderer::drawSprite( glm::vec3 pos, int w, int h, int uP, int vP, glm::vec4 col )
{}
vertex shader
#version 330 core
layout(location = 0) in vec3 vertPosition;
layout(location = 1) in vec4 color;
layout(location = 2) in vec2 in_UV;
uniform mat4 MVP;
out vec4 col;
out vec2 uv;
void main(void)
{
gl_Position = MVP * vec4(vertPosition, 1.0);
col = color;
uv = in_UV;
}
fragment shader
#version 330 core
in vec4 col;
in vec2 uv;
out vec4 color;
uniform sampler2D tex;
void main(void)
{
vec4 Color = texture2D( tex, uv ) * col;
color = Color;
}
I call the drawSpriteBillboarded function from my Game class like so:
drawSpriteBillboarded( glm::vec3( 0, 0, -5 ), cam.getPos(), 16, 16, 0, 0, glm::vec3( 255, 255, 255, 255 ) );
The camera's position is at 0, 0, 0
I've tried changing the vertex shader to not multiply by the MVP matrix and also tried changing the fragment shader to this:
#version 330 core
in vec4 col;
in vec2 uv;
out vec4 color;
void main(void)
{
color = vec4(1.0, 1.0, 1.0, 1.0);
}
But it doesn't show anything either.
I've also tried changing GL_TRIANGLES to GL_POINTS, but nothing.
EDIT
I also added the loadAndCompile() function:
void Shader::loadAndCompile( const char* vertPath, const char* fragPath )
{
std::string vsCode = "";
std::ifstream vsStream( vertPath, std::ios::in );
fprintf( stdout, "loading vertex shader %s\n", vertPath );
if( vsStream.is_open() )
{
std::string line;
while( std::getline( vsStream, line ) )
vsCode += line + '\n';
vsStream.close();
}
else
{
fprintf( stderr, "Error: could not find vertex shader %s\n", vertPath );
return;
}
std::string fsCode = "";
std::ifstream fsStream( fragPath, std::ios::in );
fprintf( stdout, "loading fragment shader %s\n", fragPath );
if( fsStream.is_open() )
{
std::string line;
while( std::getline( fsStream, line ) )
fsCode += line + '\n';
fsStream.close();
}
else
{
fprintf( stderr, "Error: could not find fragment shader %s\n", fragPath );
return;
}
fprintf( stdout, "Compiling vertexShader %s\n", vertPath );
const char* vertCode = vsCode.c_str();
GLuint vertShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertShader, 1, &vertCode, NULL );
glCompileShader( vertShader );
GLint result = GL_FALSE;
int infoLogLength;
glGetShaderiv( vertShader, GL_COMPILE_STATUS, &result );
glGetShaderiv( vertShader, GL_INFO_LOG_LENGTH, &infoLogLength );
if( infoLogLength > 0 )
{
std::vector< char > errorMsg( infoLogLength );
glGetShaderInfoLog( vertShader, infoLogLength, NULL, &errorMsg[ 0 ] );
fprintf( stderr, "%s\n", &errorMsg[ 0 ] );
}
fprintf( stdout, "Compiling fragmentShader %s\n", fragPath );
const char* fragCode = fsCode.c_str();
GLuint fragShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragShader, 1, &fragCode, NULL );
glCompileShader( fragShader );
glGetShaderiv( fragShader, GL_COMPILE_STATUS, &result );
glGetShaderiv( fragShader, GL_INFO_LOG_LENGTH, &infoLogLength );
if( infoLogLength > 0 )
{
std::vector< char > errorMsg( infoLogLength );
glGetShaderInfoLog( fragShader, infoLogLength, NULL, &errorMsg[ 0 ] );
fprintf( stderr, "%s\n", &errorMsg[ 0 ] );
}
fprintf( stdout, "Linking program...\n" );
GLuint tmpProgID = glCreateProgram();
glAttachShader( tmpProgID, vertShader );
glAttachShader( tmpProgID, fragShader );
glLinkProgram( tmpProgID );
glGetProgramiv( tmpProgID, GL_LINK_STATUS, &result );
glGetProgramiv( tmpProgID, GL_INFO_LOG_LENGTH, &infoLogLength );
if( infoLogLength > 0 )
{
std::vector< char > errorMsg( infoLogLength );
glGetProgramInfoLog( tmpProgID, infoLogLength, NULL, &errorMsg[ 0 ] );
fprintf( stderr, "%s\n", &errorMsg[ 0 ] );
}
glDeleteShader( vertShader );
glDeleteShader( fragShader );
this->programID = tmpProgID;
}
So I'm basically asking you to check my code to see if I made a (silly) mistake.
Solved! - The winW and winH variables were not initialized when the constructor gets called.
I also had to change glDrawElements(...) to glDrawArrays(...)

Drawing part of a texture on a triangle in openGL

I'm trying to draw part of a texture on a triangle. The triangle is defined by 3 points. One of the points will always be the center of the image. Now I want to draw a part of the texture on that triangle. So the triangle would cut out that part of the image and draw it on itself. But I don't want the texture to scale when drawn. It has to stay the same. So even if the triangle's base points fall outside of the image. The image can't be scaled. I don't understand how this can be done. Whenever I play around with texturing, the image gets scaled or drawn multiple times it seems.
Here is an image: so the red triangle would be drawn exactly like that in openGL.
In your fragment shader check the s & t values on your texcoord and discard if either is less than zero or greater than one.
EDIT: Example:
// g++ main.cpp -o main -lglut -lGLEW
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include <iostream>
using namespace std;
void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE, len = 10;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_INFO_LOG_LENGTH, &len );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_INFO_LOG_LENGTH, &len );
vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
cerr << &log[0] << endl;
exit( -1 );
}
GLuint LoadShader( GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
return shader;
}
GLuint LoadProgram( const char* vert, const char* geom, const char* frag )
{
GLuint program = glCreateProgram();
if( vert ) glAttachShader( program, LoadShader( GL_VERTEX_SHADER, vert ) );
if( geom ) glAttachShader( program, LoadShader( GL_GEOMETRY_SHADER, geom ) );
if( frag ) glAttachShader( program, LoadShader( GL_FRAGMENT_SHADER, frag ) );
glLinkProgram( program );
CheckStatus( program );
return program;
}
#define GLSL(version, shader) "#version " #version "\n" #shader
const GLchar* vert = GLSL
(
120,
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
);
const GLchar* frag = GLSL
(
120,
uniform sampler2D texture;
void main()
{
if( any( lessThan( gl_TexCoord[0].st, vec2( 0.0, 0.0 ) ) ) ||
any( greaterThan( gl_TexCoord[0].st, vec2( 1.0, 1.0 ) ) ) )
{
gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 );
//discard;
}
else
{
gl_FragColor = texture2D( texture, gl_TexCoord[0].st );
}
}
);
GLuint prog = 0;
GLuint tex = 0;
void init()
{
prog = LoadProgram( vert, NULL, frag );
unsigned char bits[ 32 * 32 * 4 ];
for( unsigned int i = 0; i < 32*32; ++i )
{
bits[i*4 + 0] = rand() % 255;
bits[i*4 + 1] = rand() % 255;
bits[i*4 + 2] = rand() % 255;
bits[i*4 + 3] = 255;
}
glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_2D, tex );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D, 0, 4, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, bits );
}
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
glOrtho( -3 * ar, 3 * ar, -3, 3, -1, 1);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glUseProgram( prog );
glUniform1i( glGetUniformLocation( prog, "texture" ), 0 );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, tex );
glBegin( GL_TRIANGLES );
glTexCoord2f( 0.5, 0.5 );
glVertex2f( 0, 0 );
glTexCoord2f( 1.5, 0.5 );
glVertex2f( 2, 0 );
glTexCoord2f( 0.5, 1.5 );
glVertex2f( 0, 2 );
glEnd();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 640,480 );
glutCreateWindow( "test" );
glutDisplayFunc( display );
glewInit();
init();
glutMainLoop();
return 0;
}

Weird behavior of OpenGL / glGetUniformLocation()

I just wanna do the basics... give the shaders information from my application. I tried everything and nothing worked because I can never figure out what is new and what is deprecated in OpenGL
Vertex Shader:
#version 420 core
layout(location = 0) in vec2 p_rect;
layout(location = 1) in vec2 p_clipRect;
out vec2 texturePoint;
void main()
{
gl_Position = vec4( p_rect, 0.0, 1.0 );
texturePoint = p_clipRect;
}
Fragment Shader:
#version 420 core
uniform sampler2D p_texture;
in vec2 texturePoint;
out vec4 outColor;
void main()
{
outColor = texture( p_texture, texturePoint );
}
OpenGL Code:
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, texture );
GLint texture_id( glGetUniformLocation( programId, "p_texture" ) );
glUniform1i( texture_id, texture );
// Element
static const GLushort element[] = { 0, 1, 2, 3 };
GLuint element_id;
glGenBuffers( 1, &element_id );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_id );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( element ), element, GL_STATIC_DRAW );
// Vertex data
struct VertexInput
{
GLfloat m_rect[ 8 ];
GLfloat m_clipRect[ 8 ];
}
vertex;
// fill it up with data
GLfloat vertex_data[] =
{
-1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, -1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
memcpy( &vertex, &vertex_data, sizeof( vertex_data ) );
// VBO
GLuint vertex_id;
glGenBuffers( 1, &vertex_id );
glBindBuffer( GL_ARRAY_BUFFER, vertex_id );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertex), &vertex, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_TRUE, 0, (void*)offsetof( VertexInput, m_rect ) );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_TRUE, 0, (void*)offsetof( VertexInput, m_clipRect ) );
// render the VBO
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_id );
glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0 );
// clean it up ;-)
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
The weird thing:
Case 1: If programId is the actual program id, I get texture_id = 0 but no information gets to the shader... nothing happens...
Case 2: If programId is anything other than the actual program id, I get texture_id = -1 but my code RENDERS the image perfectly (WEARD).
The thing is that... I know it's still wrong. I need to be able to give information to the shader and then render... I really don't know how the case 2 is working, but the fact is that I need to give more information to the shaders, like other textures, MVP matrix and so son. I can't do it. What is wrong? How do I give the correct value of my program id and get this information in the shader?
glActiveTexture( GL_TEXTURE0 );
...
glUniform1i( texture_id, texture );
Try this instead:
glActiveTexture( GL_TEXTURE0 + 0 );
...
glUniform1i( texture_id, 0 );
Sampler uniforms should be assigned the index of the desired texture unit, not the texture object ID.

C++ OpenGL wireframe cube rendering blank

I'm just trying to draw a bunch of lines that make up a "cube". I can't for the life of me figure out why this is producing a black screen. The debugger does not break at any point.
I'm sure it's a problem with my pointers, as I'm only decent at them in regular c++ and in OpenGL it gets even worse.
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
GLuint indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
//glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
EDIT: Full code trying the first answer's recommendation. Still blank.
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#pragma comment( lib, "glfw.lib")
#pragma comment( lib, "opengl32.lib")
#pragma comment( lib, "glew32s.lib")
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW();
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i ) {
vertices[i] /= 2.0f;
}
GLubyte indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertices );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, 24, GL_UNSIGNED_BYTE, indices);
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
void initializeGLFW() {
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
The "default" projection is essentially glOrtho(-1, 1, -1, 1, -1, 1) with the camera at (0,0,0) looking down the -Z axis.
Move the camera back:
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
And make your object smaller:
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
Complete:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <cstdlib>
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW()
{
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
int main()
{
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] =
{
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
GLuint indices[] =
{
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED))
{
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}