[SOLVED: SEE MY ANSWER BELOW]
Either I'm confused, or they really don't make this easy for beginners. I built some code that's not mine and should be tested and working, but it's not. Upon doing './execname' I get "Segmentation fault".
Eclipse debugging: setting up a debug configuration is strange because it sees no binaries in the project, though the binary is sitting right there in the project. So I have to hunt it down on the filesystem. I set my breakpoint in the corresponding cpp file, but upon debugging I get "No source available for "main() at 0x804a64e"".
Command line debugging: I did 'gdb execname', and it says it's reading symbols from the file I gave it (makes sense). Then I do 'break 273' and it says "No line 273 in file "../Common/InitShader.cpp""?? Why is it looking there?? It's not the file I gave gdb!
Code that gives the segmentation fault:
// rotating cube with two texture objects
// change textures with 1 and 2 keys
#include "Angel.h"
const int NumTriangles = 12; // (6 faces)(2 triangles/face)
const int NumVertices = 3 * NumTriangles;
const int TextureSize = 64;
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
// Texture objects and storage for texture image
GLuint textures[2];
GLubyte image[TextureSize][TextureSize][3];
GLubyte image2[TextureSize][TextureSize][3];
// Vertex data arrays
point4 points[NumVertices];
color4 quad_colors[NumVertices];
vec2 tex_coords[NumVertices];
// Array of rotation angles (in degrees) for each coordinate axis
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 };
GLuint theta;
//----------------------------------------------------------------------------
int Index = 0;
void
quad( int a, int b, int c, int d )
{
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
color4 colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 0.0, 1.0, 1.0, 1.0 ), // white
color4( 1.0, 1.0, 1.0, 1.0 ) // cyan
};
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[b];
tex_coords[Index] = vec2( 0.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[d];
tex_coords[Index] = vec2( 1.0, 0.0 );
Index++;
}
//----------------------------------------------------------------------------
void
colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
void
init()
{
colorcube();
// Create a checkerboard pattern
for ( int i = 0; i < 64; i++ ) {
for ( int j = 0; j < 64; j++ ) {
GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
image[i][j][0] = c;
image[i][j][1] = c;
image[i][j][2] = c;
image2[i][j][0] = c;
image2[i][j][1] = 0;
image2[i][j][2] = c;
}
}
// Initialize texture objects
glGenTextures( 2, textures );
glBindTexture( GL_TEXTURE_2D, textures[0] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glBindTexture( GL_TEXTURE_2D, textures[1] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image2 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textures[0] );
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER,
sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
NULL, GL_STATIC_DRAW );
// Specify an offset to keep track of where we're placing data in our
// vertex array buffer. We'll use the same technique when we
// associate the offsets with vertex attribute pointers.
GLintptr offset = 0;
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
offset += sizeof(points);
glBufferSubData( GL_ARRAY_BUFFER, offset,
sizeof(quad_colors), quad_colors );
offset += sizeof(quad_colors);
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
glUseProgram( program );
// set up vertex arrays
offset = 0;
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(points);
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(quad_colors);
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray( vTexCoord );
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
// Set the value of the fragment shader texture sampler variable
// ("texture") to the the appropriate texture unit. In this case,
// zero, for GL_TEXTURE0 which was previously set by calling
// glActiveTexture().
glUniform1i( glGetUniformLocation(program, "texture"), 0 );
theta = glGetUniformLocation( program, "theta" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
mouse( int button, int state, int x, int y )
{
if ( state == GLUT_DOWN ) {
switch( button ) {
case GLUT_LEFT_BUTTON: Axis = Xaxis; break;
case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break;
case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;
}
}
}
//----------------------------------------------------------------------------
void
idle( void )
{
Theta[Axis] += 0.01;
if ( Theta[Axis] > 360.0 ) {
Theta[Axis] -= 360.0;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int mousex, int mousey )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case '1':
glBindTexture( GL_TEXTURE_2D, textures[0] );
break;
case '2':
glBindTexture( GL_TEXTURE_2D, textures[1] );
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Color Cube" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMouseFunc( mouse );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
You should use the syntax sourcefile:line for breakpoint. Like in main.cpp:72. So the command will be like break main.cpp:72
I thought I had done this already, but I think adding -g (debug option) into the makefile let gdb do what it needed. So now I know where the fault happens, but have no idea why, so this issue is moving to a question about openGL programming.
Related
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).
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying to use glDrawElements , glTexCoordPointer and glTexImage1D to create a 1D texture, render a surface dataset and color the vertices according to their height value.
GLuint tex = 0;
My texture generation:
glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_1D, tex );
unsigned char pixels[] =
{
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
};
glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
vArray is an array which stores the vertices for rendering.
float vArray[12] = {
0.0, 1.0, 0.0,
0.0, 3.0, 1.0,
1.0, 2.0, 0.0,
1.0, 1.0, 1.0,
}
iArray is an array which stores the indices for rendering.
int iSize = 6;
int iArray[6] = {
0, 2, 1,
2, 1, 4,
}
tArray is an array which stores the normalised heights.
GLfloat tArray[4] = {
0.0, 0.3, 1.0, 0.0,
}
My render code:
glEnable(GL_TEXTURE_1D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_1D, tex);
glTexCoordPointer(1, GL_FLOAT, sizeof(GL_FLOAT), tArray);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3 ,GL_FLOAT,0, vArray);
glDrawElements(GL_TRIANGLES, iSize, GL_UNSIGNED_INT, iArray);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_1D);
The final output is not as I expected, hoping somebody can point out my mistakes.
RE: your glTexCoordPointer() call: Tightly-packed arrays usually use 0 for stride.
vArray and tArray only have four elements, not five, so the 4 in iArray will cause OpenGL to read off the ends of those arrays into garbage (if you're lucky) or segfaults (if you're not).
All together:
#include <GL/glew.h>
#include <GL/glut.h>
GLuint tex = 0;
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
float vArray[] =
{
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
-0.5, 0.5,
};
GLfloat tArray[] =
{
0.0, 0.3, 1.0, 0.0,
};
unsigned int iArray[] =
{
0, 1, 2,
2, 3, 0,
};
glEnable( GL_TEXTURE_1D );
glBindTexture( GL_TEXTURE_1D, tex );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 1, GL_FLOAT, 0, tArray );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vArray );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, iArray );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDisable( GL_TEXTURE_1D );
glutSwapBuffers();
}
int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 400, 400 );
glutCreateWindow( "GLUT" );
glewInit();
glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_1D, tex );
unsigned char pixels[] =
{
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
};
glTexImage1D( GL_TEXTURE_1D, 0, GL_RGBA, 3, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
EDIT: 2D version:
#include <GL/glew.h>
#include <GL/glut.h>
GLuint tex = 0;
void display()
{
glClear( GL_COLOR_BUFFER_BIT );
float vArray[] =
{
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
-0.5, 0.5,
};
GLfloat tArray[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
};
unsigned int iArray[] =
{
0, 1, 2,
2, 3, 0,
};
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, tex );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FLOAT, 0, tArray );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, vArray );
glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, iArray );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDisable( GL_TEXTURE_2D );
glutSwapBuffers();
}
int main( int argc, char** argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 400, 400 );
glutCreateWindow( "GLUT" );
glewInit();
glGenTextures( 1, &tex );
glBindTexture( GL_TEXTURE_2D, tex );
unsigned char pixels[] =
{
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
0, 0, 255, 255,
};
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
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_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glutDisplayFunc( display );
glutMainLoop();
return 0;
}
I can compile and run the program but it creates only a white windows with nothing in it when it is run. I've made sure that the shader files are in the same directory and still it produces nothing else than a window with a white background.
//
// Perspective view of a color cube using LookAt() and Frustum()
//
// Colors are assigned to each vertex and then the rasterizer interpolates
// those colors across the triangles.
//
#define _CRT_SECURE_NO_WARNINGS
#include "Angel.h"
typedef Angel::vec4 color4;
typedef Angel::vec4 point4;
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
color4 colors[NumVertices];
// Vertices of a unit cube centered at origin, sides aligned with axes
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
// RGBA olors
color4 vertex_colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 1.0, 1.0, 1.0, 1.0 ), // white
color4( 0.0, 1.0, 1.0, 1.0 ) // cyan
};
// Viewing transformation parameters
GLfloat radius = 1.0;
GLfloat theta = 0.0;
GLfloat phi = 0.0;
const GLfloat dr = 5.0 * DegreesToRadians;
GLuint model_view; // model-view matrix uniform shader variable location
// Projection transformation parameters
GLfloat left = -1.0, right = 1.0;
GLfloat bottom = -1.0, top = 1.0;
GLfloat zNear = 0.5, zFar = 3.0;
GLuint projection; // projection matrix uniform shader variable location
//----------------------------------------------------------------------------
// quad generates two triangles for each face and assigns colors
// to the vertices
int Index = 0;
void
quad( int a, int b, int c, int d )
{
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[b]; points[Index] = vertices[b]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[d]; points[Index] = vertices[d]; Index++;
}
//----------------------------------------------------------------------------
// generate 12 triangles: 36 vertices and 36 colors
void
colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
// OpenGL initialization
void
init()
{
colorcube();
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors),
NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(points), points );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader42.glsl", "fshader42.glsl" );
glUseProgram( program );
// set up vertex arrays
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(0) );
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(sizeof(points)) );
model_view = glGetUniformLocation( program, "model_view" );
projection = glGetUniformLocation( program, "projection" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
//----------------------------------------------------------------------------
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
point4 eye( radius*sin(theta)*cos(phi),
radius*sin(theta)*sin(phi),
radius*cos(theta),
1.0 );
point4 at( 0.0, 0.0, 0.0, 1.0 );
vec4 up( 0.0, 1.0, 0.0, 0.0 );
mat4 mv = LookAt( eye, at, up );
glUniformMatrix4fv( model_view, 1, GL_TRUE, mv );
mat4 p = Frustum( left, right, bottom, top, zNear, zFar );
glUniformMatrix4fv( projection, 1, GL_TRUE, p );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int x, int y )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case 'x': left *= 1.1; right *= 1.1; break;
case 'X': left *= 0.9; right *= 0.9; break;
case 'y': bottom *= 1.1; top *= 1.1; break;
case 'Y': bottom *= 0.9; top *= 0.9; break;
case 'z': zNear *= 1.1; zFar *= 1.1; break;
case 'Z': zNear *= 0.9; zFar *= 0.9; break;
case 'r': radius *= 2.0; break;
case 'R': radius *= 0.5; break;
case 'o': theta += dr; break;
case 'O': theta -= dr; break;
case 'p': phi += dr; break;
case 'P': phi -= dr; break;
case ' ': // reset values to their defaults
left = -1.0;
right = 1.0;
bottom = -1.0;
top = 1.0;
zNear = 0.5;
zFar = 3.0;
radius = 1.0;
theta = 0.0;
phi = 0.0;
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
reshape( int width, int height )
{
glViewport( 0, 0, width, height );
}
//----------------------------------------------------------------------------
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Color Cube" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutReshapeFunc( reshape );
glutMainLoop();
return 0;
}
A few ideas:
Replace your glewInit(); with:
glewExperimental = GL_TRUE; // Added because of http://openglbook.com/glgenvertexarrays-access-violationsegfault-with-glew/
GLint GlewInitResult = glewInit();
if (GlewInitResult != GLEW_OK) {
printf("ERROR: %s\n", glewGetErrorString(GlewInitResult));
}
Also you should check for OpenGL errors using glGetError(). Read more details in my blog post: http://blog.nobel-joergensen.com/2013/01/29/debugging-opengl-using-glgeterror/ .
Some ideas:
you are requesting a context with support of OpenGL 3.2 but from the filenames of the shaders I assume you are #using GLSL 4.2? That could be an issue.
does InitShaders look for (compile-)errors?
Eliminate one possible source of errors after another. Draw a fullscreen-quad instead of your geometry, disable the shaders etc.
I simply want to map images as textures to the faces of a cube and display. Instead of having my images on it, the cube is totally black. My images are both 64x64 jpg's.
My application code is below. Originally it was a program that generated 2 checkerboard textures, displayed 1 at a time on all faces of the cube, allowing the user to switch between them. Instead of a checkerboard on all faces, I want an image. I've commented out their texture generation and texture loading code, replacing it with, most importantly, ilutGLLoadImage() (from DevIL): it's supposed to kill most image-texture loading birds with one stone. This happens in init(). The only console output is "1,2" (from my cout), which implies that the images were loaded and given valid texture ID's. Why is the cube black?
Application code (init() is a good place to start looking):
#include "Angel.h"
#include <IL\config.h>
#include <IL\ilut_config.h>
#include <IL\il.h>
#include <IL\ilu.h>
#include <IL\ilut.h>
#include <iostream>
using namespace std;
const int NumTriangles = 12; // (6 faces)(2 triangles/face)
const int NumVertices = 3 * NumTriangles;
const int TextureSize = 64;
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
// Texture objects and storage for texture image
//GLuint textures[2];
GLuint tex1;
GLuint tex2;
//GLubyte image[TextureSize][TextureSize][3];
//GLubyte image2[TextureSize][TextureSize][3];
// Vertex data arrays
point4 points[NumVertices];
//color4 quad_colors[NumVertices];
vec2 tex_coords[NumVertices];
// Array of rotation angles (in degrees) for each coordinate axis
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 };
GLuint theta;
//----------------------------------------------------------------------------
int Index = 0;
void
quad( int a, int b, int c, int d )
{
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
color4 colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 0.0, 1.0, 1.0, 1.0 ), // white
color4( 1.0, 1.0, 1.0, 1.0 ) // cyan
};
// bottom-left texture coord
// quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
// top-left texture coord
// quad_colors[Index] = colors[a];
points[Index] = vertices[b];
tex_coords[Index] = vec2( 0.0, 1.0 );
Index++;
// top-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
// bottom-left
// quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
// top-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
// bottom-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[d];
tex_coords[Index] = vec2( 1.0, 0.0 );
Index++;
}
//----------------------------------------------------------------------------
void
colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
void
init()
{
colorcube();
ILuint devilError;
ilInit();
iluInit();
ilutInit();
devilError = ilGetError();
if (devilError != IL_NO_ERROR) {
printf ("Devil Error (ilInit: %s\n", iluErrorString(devilError));
exit (2);
}
ilutRenderer(ILUT_OPENGL);
GLuint openglID, openglError;
tex1 = ilutGLLoadImage("test1.jpg");
tex2 = ilutGLLoadImage("test2.jpg");
cout << tex1 << "," << tex2 << endl;
devilError = ilGetError();
if (devilError != IL_NO_ERROR) {
printf ("Error: %s\n", iluGetString (devilError));
exit (2);
}
if (openglError != GL_NO_ERROR) {
printf ("Opengl Error (ilutGLBindTexImage): %s\n", gluGetString (openglError));
exit (2);
}
// // Create a checkerboard pattern
// for ( int i = 0; i < 64; i++ ) {
// for ( int j = 0; j < 64; j++ ) {
// GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
// image[i][j][0] = c;
// image[i][j][1] = c;
// image[i][j][2] = c;
// image2[i][j][0] = c;
// image2[i][j][1] = 0;
// image2[i][j][2] = c;
// }
// }
//
// // Initialize texture objects
//
// // Get unused texture identifiers
// glGenTextures( 2, textures );
//
glBindTexture( GL_TEXTURE_2D, tex1 );
//
// // Specify that 'image' is to be used as a two-dimensional texture
// glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
// GL_RGB, GL_UNSIGNED_BYTE, image );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//
glBindTexture( GL_TEXTURE_2D, tex2 );
// glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
// GL_RGB, GL_UNSIGNED_BYTE, image2 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture( GL_TEXTURE0 );
// Set the current texture object
glBindTexture( GL_TEXTURE_2D, tex1 );
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
// glBufferData( GL_ARRAY_BUFFER,
// sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
// NULL, GL_STATIC_DRAW );
glBufferData( GL_ARRAY_BUFFER,
sizeof(points) + sizeof(tex_coords),
NULL, GL_STATIC_DRAW );
// Specify an offset to keep track of where we're placing data in our
// vertex array buffer. We'll use the same technique when we
// associate the offsets with vertex attribute pointers.
GLintptr offset = 0;
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
offset += sizeof(points);
// glBufferSubData( GL_ARRAY_BUFFER, offset,
// sizeof(quad_colors), quad_colors );
// offset += sizeof(quad_colors);
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
glUseProgram( program );
// set up vertex arrays
offset = 0;
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(points);
// GLuint vColor = glGetAttribLocation( program, "vColor" );
// glEnableVertexAttribArray( vColor );
// glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
// BUFFER_OFFSET(offset) );
// offset += sizeof(quad_colors);
// Pass the texture coordinates as a vertex attribute with the identifier 'vTextCoord'
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray( vTexCoord );
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
// Set the value of the fragment shader texture sampler variable
// ("texture") to the the appropriate texture unit. In this case,
// zero, for GL_TEXTURE0 which was previously set by calling
// glActiveTexture().
glUniform1i( glGetUniformLocation(program, "texture"), 0 );
theta = glGetUniformLocation( program, "theta" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
mouse( int button, int state, int x, int y )
{
if ( state == GLUT_DOWN ) {
switch( button ) {
case GLUT_LEFT_BUTTON: Axis = Xaxis; break;
case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break;
case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;
}
}
}
//----------------------------------------------------------------------------
void
idle( void )
{
Theta[Axis] += 0.01;
if ( Theta[Axis] > 360.0 ) {
Theta[Axis] -= 360.0;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int mousex, int mousey )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case '1':
glBindTexture( GL_TEXTURE_2D, tex1 );
break;
case '2':
glBindTexture( GL_TEXTURE_2D, tex2 );
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Texture Cube" );
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMouseFunc( mouse );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
Vertex shader:
#version 150
in vec4 vPosition;
in vec2 vTexCoord;
out vec4 color;
out vec2 texCoord;
uniform vec3 theta;
void main()
{
const float DegreesToRadians = 3.14159265 / 180.0;
vec3 c = cos( DegreesToRadians * theta );
vec3 s = sin( DegreesToRadians * theta );
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, -s.x, 0.0,
0.0, s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0);
mat4 ry = mat4( c.y, 0.0, s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
-s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
// Workaround for bug in ATI driver
ry[1][0] = 0.0;
ry[1][1] = 1.0;
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
// Workaround for bug in ATI driver
rz[2][2] = 1.0;
texCoord = vTexCoord;
gl_Position = rz * ry * rx * vPosition;
}
Fragment shader:
#version 150
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D texture;
void main()
{
fColor = texture2D( texture, texCoord );
}
My gdb backtrace gives:
(gdb) backtrace
#0 0x00000000 in ?? ()
#1 0x0804a211 in init () at example1.cpp:147
#2 0x0804a6bc in main (argc=1, argv=0xbffff3d4) at example1.cpp:283
Not very informative. Eclipse debugger at least lets me see that it stops on line 3 below:
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
This is a very common block to see in gl programming, and I'm even running other code with the same block with no problem. So I'm baffled.
Build output from running make:
g++ -g -DFREEGLUT_STATIC -DGLEW_STATIC -I../../include example1.cpp ../../Commo/InitShader.o -L/usr/lib/mesa -lGLEW -lglut -lGL -lX11 -lm -o example1
Program containing the problem:
// rotating cube with two texture objects
// change textures with 1 and 2 keys
#include "Angel.h"
const int NumTriangles = 12; // (6 faces)(2 triangles/face)
const int NumVertices = 3 * NumTriangles;
const int TextureSize = 64;
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
// Texture objects and storage for texture image
GLuint textures[2];
GLubyte image[TextureSize][TextureSize][3];
GLubyte image2[TextureSize][TextureSize][3];
// Vertex data arrays
point4 points[NumVertices];
color4 quad_colors[NumVertices];
vec2 tex_coords[NumVertices];
// Array of rotation angles (in degrees) for each coordinate axis
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 };
GLuint theta;
//----------------------------------------------------------------------------
int Index = 0;
void quad( int a, int b, int c, int d )
{
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
color4 colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 0.0, 1.0, 1.0, 1.0 ), // white
color4( 1.0, 1.0, 1.0, 1.0 ) // cyan
};
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[b];
tex_coords[Index] = vec2( 0.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
quad_colors[Index] = colors[a];
points[Index] = vertices[d];
tex_coords[Index] = vec2( 1.0, 0.0 );
Index++;
}
//----------------------------------------------------------------------------
void colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
void init()
{
colorcube();
// Create a checkerboard pattern
for ( int i = 0; i < 64; i++ ) {
for ( int j = 0; j < 64; j++ ) {
GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
image[i][j][0] = c;
image[i][j][1] = c;
image[i][j][2] = c;
image2[i][j][0] = c;
image2[i][j][1] = 0;
image2[i][j][2] = c;
}
}
// Initialize texture objects
glGenTextures( 2, textures );
glBindTexture( GL_TEXTURE_2D, textures[0] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glBindTexture( GL_TEXTURE_2D, textures[1] );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
GL_RGB, GL_UNSIGNED_BYTE, image2 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, textures[0] );
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
glBufferData( GL_ARRAY_BUFFER,
sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
NULL, GL_STATIC_DRAW );
// Specify an offset to keep track of where we're placing data in our
// vertex array buffer. We'll use the same technique when we
// associate the offsets with vertex attribute pointers.
GLintptr offset = 0;
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
offset += sizeof(points);
glBufferSubData( GL_ARRAY_BUFFER, offset,
sizeof(quad_colors), quad_colors );
offset += sizeof(quad_colors);
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
glUseProgram( program );
// set up vertex arrays
offset = 0;
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(points);
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(quad_colors);
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray( vTexCoord );
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
// Set the value of the fragment shader texture sampler variable
// ("texture") to the the appropriate texture unit. In this case,
// zero, for GL_TEXTURE0 which was previously set by calling
// glActiveTexture().
glUniform1i( glGetUniformLocation(program, "texture"), 0 );
theta = glGetUniformLocation( program, "theta" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void mouse( int button, int state, int x, int y )
{
if ( state == GLUT_DOWN ) {
switch( button ) {
case GLUT_LEFT_BUTTON: Axis = Xaxis; break;
case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break;
case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;
}
}
}
//----------------------------------------------------------------------------
void idle( void )
{
Theta[Axis] += 0.01;
if ( Theta[Axis] > 360.0 ) {
Theta[Axis] -= 360.0;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void keyboard( unsigned char key, int mousex, int mousey )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case '1':
glBindTexture( GL_TEXTURE_2D, textures[0] );
break;
case '2':
glBindTexture( GL_TEXTURE_2D, textures[1] );
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Color Cube" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMouseFunc( mouse );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
glewExperimental = GL_TRUE;
glewInit();
Should do the magic
Experimental Drivers
GLEW obtains information on the supported extensions from the graphics
driver. Experimental or pre-release drivers, however, might not report
every available extension through the standard mechanism, in which
case GLEW will report it unsupported. To circumvent this situation,
the glewExperimental global switch can be turned on by setting it to
GL_TRUE before calling glewInit(), which ensures that all extensions
with valid entry points will be exposed.
Works fine for me:
GL_VERSION : 4.1.10750 Compatibility Profile Context
GL_VENDOR : ATI Technologies Inc.
GL_RENDERER : AMD Radeon HD 6500 Series
EDIT: I'm using the latest versions of FreeGLUT (2.8.0 RC2) and GLEW (1.7.0), which may make a difference if you're relying on distro-supplied versions.
Have you tried testing on other systems with different graphics cards? If your code meets the OpenGL spec and it mysteriously crashes inside a function that is correctly called with valid parameters, it could well be a driver bug. If it's a driver bug, you're reduced to guesswork, making shotgun changes, and gradually building up a healthy exasperation that a huge corporation with billions of dollars produce absolutely crap excuses for a graphics card driver. Good luck!
Ubuntu 10.04 for example comes with glew 1.50 which glGenVertexArrays doesn't work without the glewExperimental flag.
so it is glew version dependent