OpenGL - 在一个函数中加载多个纹理
Posted
技术标签:
【中文标题】OpenGL - 在一个函数中加载多个纹理【英文标题】:OpenGL - Load mutliple texures in one function 【发布时间】:2019-11-25 18:00:21 【问题描述】:我已经用glutSolidCube()
构建了一个 15x15 的立方体网格。然后我有一个菜单处理程序,当我单击“开始游戏”时,将我使用的纹理加载到所有立方体,调用自定义 glutSolidCube
并在每个顶点声明之前有 glTexCoord2d
,因为我们不能我认为后者的纹理。为了从图像上传纹理,我使用了STB_IMAGE_IMPLEMENTATION
实现,其中还包含一个头文件。函数loadTextureFromFile(const char *filename)
负责加载部分。
如何上传更多纹理(我想要更多 2 个,最好在同一个 loadTextureFromFile()
函数中)以及如何使用 glTexCoord2d()
处理每个纹理?
这是我的完整代码:
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/gl.h> // openGL header
#include <GL/glu.h> // glut header
#include <GL/glut.h> // glut header
#define STB_IMAGE_IMPLEMENTATION
/////////////////////////////////////Textures==============================================/////////////////////////////////////
#include "stb_image.h"
GLuint texture; //the array for our texture
void loadTextureFromFile(const char *filename)
glClearColor(0.0, 0.0, 0.0, 0.0);
//glShadeModel(GL_FLAT);
//glEnable(GL_DEPTH_TEST);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load and generate the texture
int width, height, nrChannels;
unsigned char *data = stbi_load("paper.bmp", &width, &height, &nrChannels, 0);
if (data)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//glGenerateMipmap(GL_TEXTURE_2D);
else
std::cout << "Failed to load texture" << std::endl;
stbi_image_free(data);
void FreeTexture(GLuint texture)
glDeleteTextures(1, &texture);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void
drawBox(GLfloat size, GLenum type)
static GLfloat n[6][3] =
-1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
0.0, -1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, -1.0
;
static GLint faces[6][4] =
0, 1, 2, 3,
3, 2, 6, 7,
7, 6, 5, 4,
4, 5, 1, 0,
5, 6, 2, 1,
7, 4, 0, 3
;
GLfloat v[8][3];
GLint i;
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
for (i = 5; i >= 0; i--)
glBegin(type);
glNormal3fv(&n[i][0]);
glTexCoord2d(0.0,0.0);
glVertex3fv(&v[faces[i][0]][0]);
glTexCoord2d(0.0,1.0);
glVertex3fv(&v[faces[i][1]][0]);
glTexCoord2d(1.0,1.0);
glVertex3fv(&v[faces[i][2]][0]);
glTexCoord2d(1.0,0.0);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
void APIENTRY
myglutSolidCube(GLdouble size)
drawBox(size, GL_QUADS);
//int red_color[]=255,0,0;
//int blue_colot[]=0,0,255;
//////////////////////////////=========MENU============/////////////
enum MENU_TYPE //menu options-values
MENU_START,
MENU_EXIT,
;
//create the menu - Prototype
void my_createmenu(void);
// Menu handling function declaration - Prototype
void menu(int);
void init()
//for 3d lighting
glEnable(GL_DEPTH_TEST); //depth test
glEnable(GL_LIGHTING); //enable light from a single source
glEnable(GL_LIGHT0); //enable white light , diffuse and specular components
glEnable(GL_COLOR_MATERIAL); //track the current color
void display()
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Black and opaque
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//define the projection matrix just once and use the modelview matrix all other times
glMatrixMode(GL_PROJECTION); //Applies subsequent matrix operations to the projection matrix stack
glLoadIdentity();//Reset
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport); //The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height
double aspect = (double)viewport[2] / (double)viewport[3]; // y/width would be 1.0
gluPerspective(60,aspect, 1, 100); //using perspective projection
//gluOrtho2D(0.0,600.0,-60.0,600.0);
glMatrixMode(GL_MODELVIEW); //for trasformations - Applies subsequent matrix operations to the texture matrix stack
glLoadIdentity();
// move back a bit for viewer , cause of gluPerspective
glTranslatef( 0, 0, -35 );
float e=0,f=0;
//construct the grid with reference the central cube
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
glColor3ub(245, 245, 220); //Beige
glutSolidCube(2.25);
glPopMatrix();
f += -2.63;
f=0;
e+=2.63;
glutSwapBuffers(); //implicit glFlush
//for the second part of program
void display_game()
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Black and opaque
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//define the projection matrix just once and use the modelview matrix all other times
glMatrixMode(GL_PROJECTION); //Applies subsequent matrix operations to the projection matrix stack
glLoadIdentity();//Reset
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport); //The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height
double aspect = (double)viewport[2] / (double)viewport[3]; // y/width would be 1.0
gluPerspective(60,aspect, 1, 100); //using perspective projection
//glOrtho(0.0f, 600.0f, 600.0f, 0.0f, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW); //for trasformations - Applies subsequent matrix operations to the texture matrix stack
glLoadIdentity();
// move back a bit for viewer , cause of gluPerspective
glTranslatef( 0, 0, -35 );
float e=0,f=0;
glEnable(GL_TEXTURE_2D);
//construct the grid with reference the central cube
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
//glColor3ub(245, 245, 220); //Beige
//glColor3ub( rand()%255,rand()%255, rand()%255 );
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
//glColor3ub( rand()%255,rand()%255, rand()%255 );
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
f += -2.63;
f=0;
e+=2.63;
//SEED to some constant value for 2nd part of the program. If it is not used , cubes would change color in runtime
//srand(0x98765432);
glutSwapBuffers(); //implicit glFlush
glDisable(GL_TEXTURE_2D);
void reshape(GLsizei width, GLsizei height)
// GLsizei for non-negative integer // Compute aspect ratio of the new window
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height; // Set the viewport to cover the new window
glViewport(0, 0, width, height); // Set the aspect ratio of the clipping volume glMatrixMode(GL_PROJECTION); // To operate on the Projection matrix
glLoadIdentity(); // Reset // Enable perspective projection with fovy, aspect, zNear and zFar
gluPerspective(45.0f, aspect, 0.1f, 100.0f);
void timer(int extra)
glutPostRedisplay();
glutTimerFunc(16, timer, 0);
void mouseEscape( int button, int state, int x, int y )
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN &&button==MENU_EXIT)
int windowID = glutCreateWindow("CUBES");
glutDestroyWindow(windowID);
exit(0);
glutPostRedisplay();
//for loading the texture
const char* filename = "salt_on_spoon.bmp";
int main(int argc, char **argv)
glutInit(&argc, argv);
glutInitWindowSize(600,600);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE| GLUT_MULTISAMPLE);
glEnable(GL_MULTISAMPLE); //anti-alliasing
glutCreateWindow("CUBES");
//create and handle the menu
my_createmenu();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 0);
init();
//glEnable(GL_TEXTURE_2D); //for texture
//glutMouseFunc(mouseEscape);
//glutKeyboardFunc(keyEscape);
//Load our texture
//loadTextureFromFile(filename);
glutMainLoop();
//Free our texture
//FreeTexture(texture);
return 0;
//create the menu-entries
void my_createmenu(void)
// Create a menu
glutCreateMenu(menu);
// Add menu items
glutAddMenuEntry("Start Game", MENU_START);
glutAddMenuEntry("Exit", MENU_EXIT);
// Associate a mouse button with menu
glutAttachMenu(GLUT_RIGHT_BUTTON);
// Menu handling function-what to do in each value
void menu(int item)
switch (item)
case MENU_START:
//glEnable(GL_TEXTURE_2D); //for texture
//Load our texture
loadTextureFromFile(filename);
glutDisplayFunc(display_game);
break;
case MENU_EXIT:
int windowID = glutCreateWindow("CUBES"); //exit game
glutDestroyWindow(windowID);
exit(0);
break;
default:
/* Nothing */
break;
glutPostRedisplay();
return;
我正在菜单功能中进行纹理加载部分。我将如何处理三种纹理?最终目标是同时调用要在立方体上渲染的三个纹理。
我还有两张图:第一张:节目开始的时候:
第二个:点击“星际游戏”后,您可以看到所有立方体中渲染的纹理:
目标是更多 2 种类型的纹理,并且所有这些纹理都呈现在随机立方体中。
【问题讨论】:
【参考方案1】:您可以创建多个纹理对象。
glBindTexture
将命名纹理绑定到纹理目标,即全局状态。 glTexImage2D
为纹理指定二维纹理图像,当前绑定到指定目标。 glTexParameter
给纹理对象设置参数。
我建议编写一个函数,将文件中的纹理加载到给定的纹理对象(名称 id):
void loadTextureFromFile(const char *filename, unsigned int texture)
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load and generate the texture
int width, height, nrChannels;
unsigned char *data = stbi_load(filename, &width, &height, &nrChannels, 0);
if (data)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
GL_RGB, GL_UNSIGNED_BYTE, data);
//glGenerateMipmap(GL_TEXTURE_2D);
else
std::cout << "Failed to load texture" << std::endl;
stbi_image_free(data);
const char* filename1 = "salt_on_spoon.bmp";
const char* filename2 = ...;
const char* filename3 = ...;
unsigned int tob[3];
int main(int argc, char **argv)
// [...]
glGenTextures(3, &tob[0]);
loadTextureFromFile(filename1, tob[0]);
loadTextureFromFile(filename2, tob[1]);
loadTextureFromFile(filename3, tob[2]);
// [...]
启用二维纹理后,当前绑定到目标GL_TEXTURE_2D
的纹理对象的图像将包裹在网格上。
在绘制几何图形之前,您必须绑定正确的纹理对象。例如:
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
glBindTexture(GL_TEXTURE_2D, tob[0]);
glPushMatrix();
glTranslatef(0.0f+e,0.0f+f,0.0f); //right and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[1]);
glPushMatrix();
glTranslatef(0.0f-e,0.0f+f,0.0f); //left and below
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[2]);
glPushMatrix();
glTranslatef(0.0f+e,0.0f-f,0.0f); //right and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, tob[0]);
glPushMatrix();
glTranslatef(0.0f-e,0.0f-f,0.0f); //left and up
glRotatef(20.0f,1.0f,-2.0f,0.0f); //looking 3d
myglutSolidCube(2.25);
glPopMatrix();
f += -2.63;
f=0;
e+=2.63;
注意,纹理的分布只是一个例子。您必须确保 unsigned int tob[3];
之前在全局命名空间中声明。
【讨论】:
也是 main 中的部分,glGenTextures(3, &tob);应该类似于 glGenTextures(3, &tob[3]);对吧? 我收到一个错误:错误:无法将参数 '2' 的 'unsigned int ()[3]' 转换为 'GLuint aka unsigned int*' void glGenTextures(GLsizei, GLuint*)' glGenTextures(3, &tob);我使用的编译参数是: g++ -fpcc-struct-return -I/usr/include -g main.cpp -L/usr/lib/ -lGLU -lGL -lglut -lm -o main @DavidDunn 它必须是glGenTextures(3, &tob[0]);
(第一个数组元素的地址)。但是glGenTextures(3, tob);
也应该可以工作。以上是关于OpenGL - 在一个函数中加载多个纹理的主要内容,如果未能解决你的问题,请参考以下文章
在 openGL 纹理中加载图像(使用它们的 RGB(A) 像素数据)