Drawing part of a texture on a triangle in openGL - 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;
}

Related

Broadcast fragment-shader output to all FBO color attachments?

Is there some way to get OpenGL ES 3.0 to broadcast the value of a single-output fragment shader to all active (as per glDrawBuffers()) FBO color attachments?
If possible I'd like to keep my shaders more-or-less as-is and avoid the re-write required by multiple layout'd outputs:
layout( location = 0 ) out vec4 out_color0;
layout( location = 1 ) out vec4 out_color1;
layout( location = 2 ) out vec4 out_color2;
layout( location = 3 ) out vec4 out_color3;
void main()
{
out_color0 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color1 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color2 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color3 = vec4( 1.0, 0.2, 0.0, 1.0 );
}
...or an output array:
out vec4 out_color[4];
void main()
{
out_color[0] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[1] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[2] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[3] = vec4( 1.0, 0.2, 0.0, 1.0 );
}
Here's the program I'm using for testing, it (tries) to draw a red triangle to all four FBO attachments & then blits the 3rd attachment to the default framebuffer:
#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <cstdarg>
#include <iostream>
#include <vector>
struct Program
{
static GLuint Load( const char* shader, ... )
{
const GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
AttachShader( prog, va_arg( args, GLenum ), 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 )
{
const GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = 1 + R"GLSL(
#version 300 es
void main()
{
const vec2 verts[3] = vec2[3]
(
vec2( -0.5, -0.5 ),
vec2( 0.5, -0.5 ),
vec2( 0.0, 0.5 )
);
gl_Position = vec4( verts[ gl_VertexID ], 0.0, 1.0 );
}
)GLSL";
const char* frag = 1 + R"GLSL(
#version 300 es
precision mediump float;
out vec4 out_color;
void main()
{
out_color = vec4( 1.0, 0.2, 0.0, 1.0 );
}
)GLSL";
int main( int argc, char** argv )
{
glfwSetErrorCallback( []( int err, const char* desc )
{
std::cerr << "GLFW error: " << desc << std::endl;
} );
if( !glfwInit() )
return EXIT_FAILURE;
glfwWindowHint( GLFW_CLIENT_API, GLFW_OPENGL_ES_API );
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 0 );
glfwWindowHint( GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API );
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
if( nullptr == window )
return EXIT_FAILURE;
glfwMakeContextCurrent( window );
glfwSwapInterval( 1 );
gladLoadGLES2Loader( (GLADloadproc)glfwGetProcAddress );
const GLuint prog = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram( prog );
// init framebuffer attachments
std::vector< GLuint > textures( 4, 0 );
glGenTextures( 4, textures.data() );
for( size_t i = 0; i < textures.size(); ++ i )
{
glBindTexture( GL_TEXTURE_2D, textures[i] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
}
GLuint rbDepth = 0;
glGenRenderbuffers(1, &rbDepth );
glBindRenderbuffer( GL_RENDERBUFFER, rbDepth );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32 );
// init FBO
GLuint fbo = 0;
glGenFramebuffers( 1, &fbo );
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
for( size_t i = 0; i < textures.size(); ++ i )
{
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0 );
}
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbDepth );
if( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus( GL_FRAMEBUFFER ) )
{
std::cerr << "Incomplete framebuffer" << std::endl;
std::exit( EXIT_FAILURE );
}
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
// render to FBO
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
GLenum bufs[] =
{
GL_COLOR_ATTACHMENT0 + 0,
GL_COLOR_ATTACHMENT0 + 1,
GL_COLOR_ATTACHMENT0 + 2,
GL_COLOR_ATTACHMENT0 + 3,
};
glDrawBuffers( 4, bufs );
glViewport( 0, 0, 32, 32 );
glClearColor( 0.0f, 0.6f, 1.0f, 1.f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDrawArrays( GL_TRIANGLES, 0, 3 );
// switch back to default framebuffer & clear it with non-black color
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
GLenum defaultBuf = GL_BACK;
glDrawBuffers( 1, &defaultBuf );
glClearColor( 1.0f, 0.0f, 1.0f, 1.f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// blit a color attachment to the default framebuffer
glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo );
glReadBuffer( GL_COLOR_ATTACHMENT0 + 2 );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBlitFramebuffer( 0, 0, 32, 32, 0, 0, 640, 480, GL_COLOR_BUFFER_BIT, GL_LINEAR );
glfwSwapBuffers( window );
}
glfwMakeContextCurrent( NULL );
glfwDestroyWindow( window );
glfwTerminate();
return EXIT_SUCCESS;
}
On this Windows 10 machine using a recent-ish ANGLE build I get the blue clear color but no triangle ("undefined") for the 3rd attachment:
The first attachment is fine:
No such functionality exists in the API:
3) Should we support broadcast from gl_FragColor to all gl_FragData[x]
or should it be synonymous with gl_FragData[0]?
DISCUSSION: With NV_draw_buffers, writing to gl_FragColor writes to all
the enabled draw buffers (ie broadcast). In OpenGL ES 3.0 when using
ESSL 1.0, gl_FragColor is equivalent to writing a single output to
gl_FragData[0] and multiple outputs are not possible. When using ESSL 3.0,
only user-defined out variables may be used.
If broadcast is supported, some implementations may have to replace
writes to gl_FragColor with replicated writes to all possible gl_FragData
locations when this extension is enabled.
RESOLVED: Writes to gl_FragColor are broadcast to all enabled color
buffers. ES 3.0 using ESSL 1.0 doesn't support broadcast because
ESSL 1.0 was not extended to have multiple color outputs (but that is
what this extension adds). ESSL 3.0 doesn't support the broadcast because
it doesn't have the gl_FragColor variable at all, and only has user-
defined out variables. This extension extends ESSL 1.0 to have multiple
color outputs. Broadcasting from gl_FragColor to all enabled color
buffers is the most consistent with existing draw buffer extensions to
date (both NV_draw_buffers and desktop GL).

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.

Rendering Freetype glyph to OpenGL (3.3+) texture results in repeated texture with artifacts

I was simply trying to display a glyph (letter Ě) loaded from Freetype as a bitmap picture onto an OpenGL texture that is stretched across the whole window. Result is here:
To get to this result I had to set an extremely large FT_Set_Pixel_Sizes to 450 otherwise the resulting image looks even worse.
I am using GLSLShader loader class by M.M. Mobeen, GLEW, SDL2 and GLM.
shaders/shader.vert
#version 330 core
layout(location=0) in vec4 vVertex; //object space vertex
out vec2 vUV; // texture coordinates for texture lookup in the fragment shader
void main()
{
gl_Position = vec4(vVertex.xy,0,1);
vUV = vVertex.zw; // texture coordinate
}
shaders/shader.frag
#version 330 core
layout (location=0) out vec4 vFragColor;
smooth in vec2 vUV;
uniform sampler2D textureMap;
void main()
{
vFragColor = texture(textureMap, vUV);
}
main.cpp
#include <glew.h>
#include <glm/glm.hpp>
#include "SDL2/SDL.h"
#include "SDL2/SDL_opengl.h"
#include <ft2build.h>
#include FT_FREETYPE_H
#include "GLSLShader.h" // https://github.com/bagobor/opengl33_dev_cookbook_2013/blob/master/Chapter3/src/GLSLShader.h
//shader reference
GLSLShader shader;
//vertex array and vertex buffer object IDs
GLuint vaoID;
GLuint vboVerticesID;
GLuint vboIndicesID;
//texture ID
GLuint textureID;
//quad vertices and indices
glm::vec4 vertices[4];
GLushort indices[6];
int main( int argc, const char* argv[] )
{
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) return EXIT_FAILURE;
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
SDL_Window* window = SDL_CreateWindow( "OpenGL + Freetype",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1024, 768,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
SDL_GLContext glcontext = SDL_GL_CreateContext( window );
if( glcontext == nullptr ) return EXIT_FAILURE;
glewExperimental = GL_TRUE;
if( glewInit() != GLEW_OK ) return EXIT_FAILURE;
SDL_GL_SetSwapInterval( 1 );
shader.LoadFromFile( GL_VERTEX_SHADER, "shaders/shader.vert" );
shader.LoadFromFile( GL_FRAGMENT_SHADER, "shaders/shader.frag" );
//compile and link shader
shader.CreateAndLinkProgram();
shader.Use();
shader.AddAttribute( "vVertex" );
shader.AddUniform( "textureMap" );
glUniform1i( shader( "textureMap" ), 0 );
shader.UnUse();
//setup quad geometry
vertices[0] = glm::vec4( -1.0, -1.0, 0, 1 );
vertices[1] = glm::vec4( 1.0, 1.0, 1, 0 );
vertices[2] = glm::vec4( 1.0, -1.0, 1, 1 );
vertices[3] = glm::vec4( -1.0, 1.0, 0, 0 );
//fill quad indices array
GLushort* id = &indices[0];
*id++ = 0;
*id++ = 1;
*id++ = 2;
*id++ = 0;
*id++ = 1;
*id++ = 3;
glGenVertexArrays( 1, &vaoID );
glGenBuffers( 1, &vboVerticesID );
glGenBuffers( 1, &vboIndicesID );
glBindVertexArray( vaoID );
glBindBuffer( GL_ARRAY_BUFFER, vboVerticesID );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), &vertices[0], GL_DYNAMIC_DRAW );
glEnableVertexAttribArray( shader["vVertex"] );
glVertexAttribPointer( shader["vVertex"], sizeof( shader["vVertex"] ), GL_FLOAT, GL_FALSE, 0, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndicesID );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), &indices[0], GL_STATIC_DRAW );
glGenTextures( 1, &textureID );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textureID );
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
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_MIN_FILTER, GL_LINEAR );
FT_Library library;
FT_Face face;
bool error = FT_Init_FreeType( &library );
if( error ) return EXIT_FAILURE;
error = FT_New_Face( library,
"dejavu.ttf",
0,
&face );
if( error ) return EXIT_FAILURE;
error = FT_Set_Pixel_Sizes( face, 0, 16 );
if( error ) return EXIT_FAILURE;
FT_Set_Pixel_Sizes( face, 0, 450 );
FT_UInt glyph_index = FT_Get_Char_Index( face, 282 ); // letter Ě
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
if( error ) return EXIT_FAILURE;
error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );
if( error ) return EXIT_FAILURE;
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGB,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);
bool running = true;
while( running )
{
SDL_Event e;
if( SDL_PollEvent( &e ) )
{
switch( e.type )
{
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
glClearColor( 1, 1, 1, 1 );
glClear( GL_COLOR_BUFFER_BIT );
shader.Use(); // bind shader
glDrawElements( GL_TRIANGLES, sizeof( indices ), GL_UNSIGNED_SHORT, 0 );
shader.UnUse(); // unbind shader
SDL_GL_SwapWindow( window );
}
return 0;
}
FT_RENDER_MODE_NORMAL results in a single-channel bitmap, not RGB:
FT_RENDER_MODE_NORMAL This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps.
Try GL_RED for format in your glTexImage2D() call instead of GL_RGB:
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGB,
face->glyph->bitmap.width,
face->glyph->bitmap.rows,
0,
GL_RED,
GL_UNSIGNED_BYTE,
face->glyph->bitmap.buffer
);

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(...)

Can't draw triangle using Opengl

in this code i want to draw a simple triangle on a blue background using openGL however when i compile and run the code only a window with the blue background appears (without the white triangle that is supposed to be drawn), iam using Xcode
my code
#include <iostream>
#include <string>
#include <GLUT/glut.h>
#include <OpenGL/gl3.h>
#include <fstream>
using namespace std;
// VAO & VBO objects
GLuint VBO;
GLuint VAO;
void display();
// vertex Data (position)
float vertex[] = {-1.0, 0.0 , 1.0,
0.0, 1.0 , 0.0,
0.0, 0.0 , 0.0 };
GLuint Program;
GLuint Vshader;
GLuint Fshader;
// main program
int main (int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("My First GLUT/OpenGL Window");
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
// main display function
void display()
{
// reading the vertex shader
fstream VertexS;
VertexS.open("/Users/hawbashali/Desktop/Project X/BwlbWl/BwlbWl/vertexShader");
if(VertexS.good() == false)
cout << "Error openning the file \n";
if(VertexS.bad() == true)
cout << "Read/writing error on i/o operation \n";
if (VertexS.fail() == true)
cout <<"Logical error on i/o operation \n";
VertexS.seekg(0,ios::end);
int size = (int)VertexS.tellg();
VertexS.clear();
VertexS.seekg(0,ios::beg);
char* vBuffer = new (nothrow) char[size];
VertexS.read(vBuffer,size);
VertexS.close();
// reading fragment shader
fstream FragS;
FragS.open("/Users/hawbashali/Desktop/Project X/BwlbWl/BwlbWl/fragmentShader");
if(FragS.good() == false)
cout << "Error openning the file \n";
if(FragS.bad() == true)
cout << "Read/writing error on i/o operation \n";
if (FragS.fail() == true)
cout <<"Logical error on i/o operation \n";
FragS.seekg(0,ios::end);
int size2 = (int)FragS.tellg();
FragS.clear();
FragS.seekg(0,ios::beg);
char* fBuffer = new (nothrow) char[size2];
FragS.read(fBuffer,size2);
FragS.close();
// creating shaders
Vshader = glCreateShader(GL_VERTEX_SHADER);
Fshader = glCreateShader(GL_FRAGMENT_SHADER);
GLint x = size;
GLint y = size2;
glShaderSource(Vshader, 1,(const char**)&vBuffer, &x);
glShaderSource(Fshader, 1, (const char**)&fBuffer, &y);
glCompileShader(Vshader);
glCompileShader(Fshader);
Program = glCreateProgram();
glAttachShader(Program, Vshader);
glAttachShader(Program, Fshader);
glLinkProgram(Program);
glUseProgram(Program);
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER,9 *sizeof(vertex),vertex, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3,GL_FLOAT, GL_TRUE, 0, 0);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glutSwapBuffers();
glDeleteShader(Vshader);
glDeleteShader(Fshader);
delete [] vBuffer;
delete [] fBuffer;
};
Vertex shader:
#version 320 core
layout(location = 0) in vec4 vPosition;
void
main()
{
gl_Position = vPosition;
}
Fragment Shader
#version 320 core
out vec4 fColor;
void
main()
{
fColor = vec4(0.0, 0.0, 1.0, 1.0);
}
glClearColor(0, 0, 1,1);
...
fColor = vec4(0.0, 0.0, 1.0, 1.0);
You're trying to draw a blue triangle on top of a blue background. You'll have to dial up your contrast pretty high to see that :)
Make one of them a different color, like red.
You're also:
Missing a VAO
Not requesting a Core context
Using #version 320 core instead of #version 150 core
Try this:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <iostream>
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static 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 );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
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 );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
150 core,
layout(location = 0) in vec4 vPosition;
void
main()
{
gl_Position = vPosition;
}
);
const char* frag = GLSL
(
150 core,
out vec4 fColor;
void
main()
{
fColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
// VAO & VBO objects
GLuint VAO;
GLuint VBO;
GLuint prog;
void init()
{
// vertex Data (position)
float vertex[] = { -1.0, -1.0 , 0.0,
1.0, -1.0 , 0.0,
0.0, 1.0 , 0.0 };
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glEnableVertexAttribArray(0);
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutInitContextVersion(3, 2);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("My First GLUT/OpenGL Window");
glewExperimental = GL_TRUE;
if( GLEW_OK != glewInit() )
return -1;
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
EDIT: Ported to GL 2.1:
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
#include <iostream>
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static 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 );
std::vector< char > log( len, 'X' );
if( glIsShader(obj) ) glGetShaderInfoLog( obj, len, NULL, &log[0] );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, len, NULL, &log[0] );
std::cerr << &log[0] << std::endl;
exit( -1 );
}
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 );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
120,
attribute vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
);
const char* frag = GLSL
(
120,
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
);
// VBO objects
GLuint VBO;
GLuint prog;
void init()
{
// vertex Data (position)
float vertex[] = { -1.0, -1.0 , 0.0,
1.0, -1.0 , 0.0,
0.0, 1.0 , 0.0 };
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
int posLoc = glGetAttribLocation( prog, "vPosition" );
glEnableVertexAttribArray( posLoc );
glVertexAttribPointer( posLoc, 3, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor(0, 0, 1,1);
glClear(GL_COLOR_BUFFER_BIT);
// Drawing the triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize(1000, 400);
glutInitWindowPosition(100, 100);
glutCreateWindow("My First GLUT/OpenGL Window");
if( GLEW_OK != glewInit() )
return -1;
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
You have provided invalid buffer size in the following line:
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(vertex), vertex, GL_STATIC_DRAW);
Because sizeof(vertex) should return the total size of the array (e.g 36) not the underlying type, thus no need to multiply by 9. If you still want to use multiplication try following:
9 * sizeof(float)
I have to write this down... You should separate your initialization and draw cycle like in genpfault's answer.