添加3D模型时,纹理映射消失

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了添加3D模型时,纹理映射消失相关的知识,希望对你有一定的参考价值。

我正在尝试使用SOIL_load_OGL_texture制作背景但是当我添加我的3D模型时,纹理消失了。 3D模型的代码与纹理代码分开,但是当我将它组合时,背景变为黑色,我的3D模型面向后方。这是问题,因为协调?

Before & after

我预计输出将是面向前方的3D模型,它位于纹理的前面。

#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "SOIL2.h"

GLuint myTexture;
const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };

static int head = 0, rear = -90, lear = -90, body = 0, lleg = -90, rleg = -90, ball = 0, stage = 0;
GLfloat ballRadius = 0.1f;


void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3d(0.5, 0.85, 0.9);  // head
    glPushMatrix();
    glTranslated(0, 0.25, 0.15);
    glRotated((GLfloat)head, 0, 1, 0);
    glutSolidSphere(0.2, 40, 50);
    glPopMatrix();

    glPushMatrix();         //ear
    glTranslated(0.11, 0.3, 0.18);
    glRotated((GLfloat)rear, 1, 0, 0);
    glutSolidCone(0.08, 0.2, 16, 16);
    glPopMatrix();

    glPushMatrix();         //ear
    glTranslated(-0.11, 0.3, 0.18);
    glRotated((GLfloat)lear, 1, 0, 0);
    glutSolidCone(0.08, 0.2, 16, 16);
    glPopMatrix();

    glColor3d(0.0, 0.0, 0.0);  //eyes
    glPushMatrix();
    glTranslated(0.07, 0.3, 0.33);
    glRotated(-5, 0, 0, 1);
    glScalef(0.5, 0.1, 0.1);
    glutSolidCube(0.1);
    glPopMatrix();

    glPushMatrix();      //eyes
    glTranslated(-0.07, 0.3, 0.33);
    glRotated(-5, 0, 0, -1);
    glScalef(0.5, 0.1, 0.1);
    glutSolidCube(0.1);
    glPopMatrix();

    glPushMatrix();      //mouth
    glTranslated(0.0, 0.25, 0.35);
    glRotated(0, 0, 0, 0);
    glScalef(1, 0.1, 0.1);
    glutSolidCube(0.1);
    glPopMatrix();

    glColor3d(1.0, 1.0, 1.0);
    glPushMatrix();   // teeth
    glTranslated(-0.045, 0.255, 0.34);
    glRotated(-90, 1, 0, 0);
    glutSolidCone(0.01, 0.02, 16, 16);
    glPopMatrix();

    glPushMatrix();   // teeth
    glTranslated(0.045, 0.255, 0.34);
    glRotated(-90, 1, 0, 0);
    glutSolidCone(0.01, 0.02, 16, 16);
    glPopMatrix();

    glColor3d(0.5, 0.85, 0.88);  // body
    glTranslatef(0, 0, 0.1);
    glPushMatrix();
    glRotated((GLfloat)body, 1, 0, 0);
    glutSolidSphere(0.3, 40, 50);
    glPopMatrix();


    glPushMatrix();
    glTranslatef(0, 0.7, 0.0);
    glRotatef((GLfloat)stage, 0.0, 1.0, 0.0);
    glTranslatef(1.0, 0.0, 0.0);
    glPushMatrix();
    glScalef(2.0, 0.4, 1.0);
    glutWireCube(1.0);
    glPopMatrix();

    //glFlush();

    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); 

    glBindTexture(GL_TEXTURE_2D, myTexture);

    glEnable(GL_TEXTURE_2D); 
    glBegin(GL_QUADS);

    /*glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); */

    glNormal3f(0.0, 1.0f, 0.0f);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-2.5f, -2.5f, 2.5f);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(2.5f, -2.5f, 2.5f);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(2.5f, -2.5f, -2.5f);
    glTexCoord2f(0.0f, 1.0f);
    glVertex3f(-2.5f, -2.5f, -2.5f);

    glEnd();

    glDisable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, 0); 

    glutSwapBuffers();


}

void reshape(int width, int height)
{
    if (height == 0) height = 1;                // To prevent divide by 0
    GLfloat aspect = (GLfloat)width / (GLfloat)height;
    glViewport(0, 0, width, height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
    //gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}


int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
    glutCreateWindow("SOIL test");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);   

    myTexture = SOIL_load_OGL_texture("background.png", 0, 1, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_INVERT_Y);
    if (!myTexture)
    {
        printf("soil failed to load texture
");
    }
    glEnable(GL_TEXTURE_2D);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHT0);
    glEnable(GL_NORMALIZE);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);

    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);

    glutMainLoop();
    return EXIT_SUCCESS;
}
答案

如果你想在背面绘制背景图像,那么你首先要绘制背景,但是禁用Depth Test(之前必须清除深度缓冲区)。 这导致其他几何体覆盖背景。

当绘制背景时,没有设置投影矩阵,投影矩阵是单位矩阵。所以背景的z坐标必须在[-1,1]中,否则它将被近或远平面剪切。

如果启用了纹理,则默认情况下,纹素的颜色乘以当前颜色,因为默认情况下纹理环境模式(GL_TEXTURE_ENV_MODE)是GL_MODULATE。见glTexEnv

这会导致纹理纹素的颜色被glColor3d设置的最后一种颜色“混合”。

在渲染纹理之前设置“白色”:

glColor3d(1.0, 1.0, 1.0);

注意,OpenGL是一个状态引擎。如果设置了颜色,颜色将保持不变,直到再次更改,甚至超出帧。所以这可能不是第一帧中的问题,但它会在更多帧中。

固定功能灯模型也应用于背景。使用固定功能gouraud灯模型会导致外观不佳。我建议在绘制背景之前禁用光照。

glDisable(GL_LIGHTING);

并在绘制几何图形之前启用光照

glEnable(GL_LIGHTING);

函数display可能如下所示:

void display(void)
{
    // clear color buffer and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // prepare for drawing the back ground
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glColor3d(1.0, 1.0, 1.0);

    // projection and model view for the background
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); 

    // draw the background
    glBindTexture(GL_TEXTURE_2D, myTexture);

    glEnable(GL_TEXTURE_2D); 
    glBegin(GL_QUADS);

    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);

    glEnd();

    // prepare for drawing the geometry
    glDisable(GL_TEXTURE_2D); 
    glBindTexture(GL_TEXTURE_2D, 0); 

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    // projection and model view for the geoemtry
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    //glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
    //gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // draw geometry
    glColor3d(0.5, 0.85, 0.9);  // head

    // ...

    glFlush();
    glutSwapBuffers();
    glutPostRedisplay();
}

以上是关于添加3D模型时,纹理映射消失的主要内容,如果未能解决你的问题,请参考以下文章

我的渲染技术进阶之旅解决显示3D模型时因为使用stb_image库或者opencv库加载纹理时未翻转y轴导致模型纹理映射出错的问题

将纹理 3d 模型和纹理从搅拌机导出到 xna 4.0

为 3D 模型的某些部分添加纹理

DirectX11第六篇 纹理映射

使用fabric js canvas作为threejs 3d模型纹理

OpenGL的纹理映射问题