3
votes

So, I'm using GLFW for window management, and I have GLEW in for extension management. I'm trying to write a cross-platform game that my brother came up with. It's a card game. But, to get the basics of texture mapping and rendering on 3D surfaces, I am trying to get some card textures to show on the sides of a cube. My first issue was with glfw's TGA loader, where only the first texture to be loaded would be displayable (though it would display properly on every surface I was trying to texture), despite having used the GLuint pointer array for glGenTextures. Then, I found http://home.comcast.net/~mlyn7576/OpenGL-TGA/, and it also seems to work, but now only the last loaded texture will be displayed, and it displays the one texture on all faces, even though I only reference the GL name of it once. So what am I doing wrong? I can't understand why only one loaded texture is being displayed.

Here's my main header:

#ifndef _RPSEVOLVED_H_
#define _RPSEVOLVED_H_
#endif

#include <iostream>
#include <math.h>

#include <gl\glew.h>
#include <gl\glfw.h>
#include <stdint.h>

using namespace std;

class RPSEvolved
{
private:
    bool Running;

public:
    static RPSEvolved* instance;
    RPSEvolved();
    int OnExecute();
    GLuint cardBackId;
    GLuint bgId;
    GLuint airCardId;
    GLuint earthCardId;
    GLuint fireCardId;
    GLuint lightningCardId;
    GLuint waterCardId;

public:
    bool OnInit();
    void OnEvent(/*SDL_Event* ev*/);
    void OnLoop();
    void OnRender();
    void OnCleanup();

    //callbacks
    static void GLFWCALL OnKeyCB(int key, int action);
    static void OnWindowCloseCB();
    static RPSEvolved* GetInstance();
    void GLFWCALL OnCharCB(int key, int action);
    void GLFWCALL OnMouseWheelCB(int pos);
    void GLFWCALL OnMouseMoveCB(int x, int y);
    void GLFWCALL OnMouseButtonCB(int button, int action);
};

Here's my init code:

#include "RPSEvolved.h"
#include "RPSE_TGA.h"

bool RPSEvolved::OnInit()
{
    if(glfwInit() == GL_FALSE)
    {
        cout << "Error initializing GLFW";
        return false;
    }

    if(glfwOpenWindow(1024, 768, 8, 8, 8, 8, 32, 32, GLFW_WINDOW) == GL_FALSE)
    {
        cout << "Error initializing GLFW";
        return false;
    }

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_NORMALIZE); //Automatically normalize normals
    glShadeModel(GL_SMOOTH);

    glMatrixMode(GL_PROJECTION);
    gluPerspective(45, 1024/768, 1, 100);
    glMatrixMode(GL_MODELVIEW);

    glfwDisable(GLFW_AUTO_POLL_EVENTS);
    glClearColor(0, 0, 0, 255);

    glfwSetWindowCloseCallback((GLFWwindowclosefun)OnWindowCloseCB);
    glfwSetKeyCallback(OnKeyCB);

    cardBackId = load_texture_TGA("images\\cardBack.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    bgId = load_texture_TGA("images\\bg.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    airCardId = load_texture_TGA("images\\airCard.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    earthCardId = load_texture_TGA("images\\earthCard.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    fireCardId = load_texture_TGA("images\\fireCard.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    lightningCardId = load_texture_TGA("images\\lightningCard.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);
    waterCardId = load_texture_TGA("images\\waterCard.tga", NULL, NULL, GL_CLAMP, GL_CLAMP);

    return true;
}

And my display code:

#include "RPSEvolved.h"

void RPSEvolved::OnRender()
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    gluLookAt(0.0f, 5.0f, 30.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

    static float _angle = 0.0f; _angle -= 0.3f;

    glEnable(GL_TEXTURE_2D);

    glRotatef(_angle, 0.0f, 1.0f, 0.0f);

    glColor4f(1.0f, 1.0f, 1.0f, 0.0f);

    glBegin(GL_QUADS);

    glBindTexture(GL_TEXTURE_2D, cardBackId);
    glNormal3f(0.0f, 0.0f, 1.0f); // front
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-3.0f, -5.0f, 3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(3.0f, -5.0f, 3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(3.0f, 5.0f, 3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-3.0f, 5.0f, 3.0f);

    glBindTexture(GL_TEXTURE_2D, airCardId);

    glNormal3f(1.0f, 0.0f, 0.0f); // right
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(3.0f, -4.0f, 3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(3.0f, -4.0f, -3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(3.0f, 4.0f, -3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(3.0f, 4.0f, 3.0f);

    glBindTexture(GL_TEXTURE_2D, earthCardId);

    glNormal3f(0.0f, 0.0f, -1.0f); // back
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(3.0f, 4.0f, -3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-3.0f, 4.0f, -3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-3.0f, -4.0f, -3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(3.0f, -4.0f, -3.0f);

    glBindTexture(GL_TEXTURE_2D, fireCardId);

    glNormal3f(-1.0f, 0.0f, 0.0f); // left
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-3.0f, 4.0f, -3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-3.0f, 4.0f, 3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-3.0f, -4.0f, 3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-3.0f, -4.0f, -3.0f);

    glBindTexture(GL_TEXTURE_2D, lightningCardId);

    glNormal3f(0.0f, 1.0f, 0.0f); // top
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(3.0f, 4.0f, 3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(-3.0f, 4.0f, 3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(-3.0f, 4.0f, -3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(3.0f, 4.0f, -3.0f);

    glBindTexture(GL_TEXTURE_2D, waterCardId);

    glNormal3f(0.0f, -1.0f, 0.0f); // top
    glTexCoord2f(0.0f, 0.0f);   glVertex3f(-3.0f, -4.0f, 3.0f);
    glTexCoord2f(1.0f, 0.0f);   glVertex3f(3.0f, -4.0f, 3.0f);
    glTexCoord2f(1.0f, 1.0f);   glVertex3f(3.0f, -4.0f, -3.0f);
    glTexCoord2f(0.0f, 1.0f);   glVertex3f(-3.0f, -4.0f, -3.0f);

    glEnd();

    glfwSwapBuffers();
}

Note that if I were to replace the calls to load_texture_TGA in OnInit() with calls to glfwLoadTexture2D(), that's where I would then get the problem of only the first texture displaying. What is going on that the textures don't all display like they're supposed to?

P.S. Sorry if this is really long, I'm in the habit of giving all information I could think of as pertinent when asking for help in coding.

1

1 Answers

3
votes

I think you'll need to do each face in a separate batch:

glBindTexture(GL_TEXTURE_2D, cardBackId);
glBegin(GL_QUADS);
// front vertices..
glEnd();

glBindTexture(GL_TEXTURE_2D, airCardId);
glBegin(GL_QUADS);
// Right vertices..
glEnd();

// Other faces...

There are a couple of alternatives that would allow you to render the cube in a single batch:

  • Generate a single texture with all faces of the cube in it. And then supply appropriate texture coordinates for the vertices of the cube. You could either use a 2d texture or a 3d texture for this.
  • Bind all of the textures in different texture unit registers and write a pixel shader.