在OpenGL立方体上显示多个纹理,使用c++ GLFW。

3
所以,我正在使用GLFW进行窗口管理,并且我已经引入了GLEW进行扩展管理。我正在尝试编写一个跨平台的游戏,这是我兄弟想出来的。这是一款纸牌游戏。但是,为了在3D表面上得到纹理映射和渲染的基础知识,我正在尝试让一些纸牌纹理显示在立方体的侧面上。我的第一个问题出现在glfw的TGA加载器上,只有第一个加载的纹理可以显示(虽然它在我试图给每个表面贴纹理时会正确地显示),尽管我已经使用了GLuint指针数组来进行glGenTextures。然后,我找到了http://home.comcast.net/~mlyn7576/OpenGL-TGA/,它似乎也可以工作,但现在只有最后加载的纹理将被显示,并且它在所有面上都显示同一张纹理,尽管我只引用了它的GL名称一次。那么我做错了什么?我不明白为什么只有一个加载的纹理被显示。
以下是我的主要头文件:
#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);
};

这是我的初始化代码:

#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;
}

而我的显示代码:

#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();
}

请注意,如果我在OnInit()中用glfwLoadTexture2D()替换load_texture_TGA的调用,那么我会遇到只显示第一个纹理的问题。为什么纹理不像它们应该的那样全部显示?
附注:如果这太长了,请原谅,我在编码时习惯提供我认为相关的所有信息来寻求帮助。
1个回答

4

我认为你需要将每个面单独处理:

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

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

// Other faces...

有几种替代方案可以让您在单个批处理中呈现立方体:

  • 生成一个包含立方体所有面的单个纹理。然后为立方体的顶点提供适当的纹理坐标。 您可以使用2D纹理或3D纹理。
  • 将所有纹理绑定到不同的纹理单元寄存器上并编写像素着色器。

1
非常感谢您的帮助。我尝试过使用glEnd()..glBegin()部分,但出于某种原因,我从未尝试在其中放置glBindTexture调用。现在它终于可以工作了!现在我只需要弄清楚如何防止纹理在表面的两侧被打印即可... - Malkierian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接