0

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 );
}
Rooster
  • 1,267
  • 3
  • 15
  • 23
  • Possible duplicate? http://stackoverflow.com/questions/10707230/loading-textures-in-c-opengl-using-devil Looks like it could be a bug in ilutGLLoadImage. – John Lyon Nov 12 '12 at 03:04
  • @jozzas I just added GL error checking, as he had done. I indeed have an error: 1280, GL_INVALID_ENUM. Different error than his, and I don't understand what the cause is. Perhaps a bug after all? – Rooster Nov 12 '12 at 03:58
  • Hmm might not be a bug in ilutGLLoadImage. I tried the function given here http://r3dux.org/2010/11/single-call-opengl-texture-loader-in-devil/#comments. Still getting a black cube. – Rooster Nov 12 '12 at 04:51
  • did you see his [revised version of that post](http://r3dux.org/2011/09/simple-texture-loading-with-devil-revisited/)? Perhaps use his source there as a reference and see what you can get working. – John Lyon Nov 12 '12 at 06:22
  • Thanks I just checked it out. I'm trying to follow it as closely as is applicable, such as the ordering of calls. I added his output that lets me know my image is loaded with correct properties. The biggest differences between our codes are that I use a) programmable shaders (see my orig. post) and b) GLUT. He doesn't. – Rooster Nov 12 '12 at 19:04

0 Answers0