[英]Using multiple textures in OpenGL
更新:我现在可以绘制多个纹理,弄清楚glGenTextures等如何工作,并重写了loadtextures()函数和其他东西。 但是,只绘制了汽车的一些零件。 方向盘,一个轮毂盖和后灯(也许还有一些小东西)。 在collada文件中,一些材质永远不会与纹理文件关联。 我不认为这是问题所在,因为在我第一次尝试时,我便将列表中的纹理与前两个多列表关联起来(5个,总共有80个),并且我得到了一辆看起来像是在使用正确的纹理,只是缺少轮胎,也许还有一些我没有注意到的小东西。 我认为也许与平铺的纹理有关? 无论如何,我想用红色替换所有没有纹理文件的网格,但是我不确定该怎么做。 我在本教程中开始使用代码:
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-4-a-colored-cube/
我做了一个颜色缓冲区,将它绑定等等,但是后来我意识到我需要编辑着色器文件,但我不确定该怎么做。
一:
attribute vec3 vPosition;
attribute vec2 vTextureCoord;
varying vec2 vTexCoord;
uniform mat4 modelview_matrix;
void main(void)
{
vTexCoord = vTextureCoord;
gl_Position = modelview_matrix*vec4(vPosition,1.0);
}
另一个:
varying vec2 vTexCoord;
uniform sampler2D myTexture;
void main (void)
{
gl_FragColor = texture2D(myTexture, vTexCoord);
}
/////原始问题
我正在做一个uni作业,其中我将不得不绘制一些带有纹理的对象(而且我必须能够在场景和东西周围移动,但是当我到达它时,我将越过那座桥)。 我有一个教程作为基础,它将从单个顶点数组和单个纹理文件(从.obj文件)绘制对象(我为上一教程编写了解析器)。
该作业使用collada文件,因此我编写了collada解析器。 这真的很辛苦! 我的collada解析器生成了一个包含Material对象的映射,该对象具有很多名称和id变量(在main.cpp中未使用,它们仅用于在collada文件的各个部分之间关联内容),一个m_TgaFile变量,用于保存纹理文件名称为字符串,以及一个m_Mesh变量,该变量保存一个Vertex对象的矢量,该对象只有两个浮点数组,即m_Positions和m_Textures,用于保存位置和tex坐标。
因此,到目前为止,我能够做的是通过遍历地图并仅使用地图中的第一个纹理文件来绘制所有位(几分钟后崩溃,但我会发现以后很高兴屏幕上出现了一些东西)。 我尝试在地图上循环调用loadTextures()(并发送一个Material),以便可以使用每个Material的纹理文件,但一点都没画(白屏)。 那么,如何为绘图的每一位加载每种纹理?
我已经尝试研究它,并且得出一个事实,我需要使用glBindTexture,glTexImage2D和我不记得的另一个。 前两个在我的教程随附的TgaParser中。 在绘图代码中再次使用glBindTexture,第二个参数为零。 根据我的收集,这意味着使用已加载的默认纹理。 我无法弄清楚如何在需要时加载每个纹理,我不了解纹理名称的含义以及将其与纹理数据关联的方式。
哦,我尝试过在OpenGl主函数中进行循环,并将pMaterial作为变量发送到显示函数,但它不是那样的,我认为它不会起作用,但我认为我至少会尝试。
这是一些代码。
OpenGL主要功能:
int main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(screenWidth, screenHeight);
glutCreateWindow("Intro to shading");
glewInit();
init();
glutDisplayFunc(forward_display);
glutIdleFunc(forward_animate);
glutMainLoop();
/*
DONT DO THINGS HERE
*/
return 0;
}
绘图功能:
void forward_display()
{
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//glScalef(0.5,0.5,0.5);
glScalef(0.005,0.005,0.005);
glRotatef(timeGetTime()*0.01,0,1,0);
GLfloat m[16];
glGetFloatv (GL_MODELVIEW_MATRIX, m);
glUniformMatrix4fv(gvModelMatrixHandle,1,false,m);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
colladaObject->m_MaterialMap.StartIterator ();
while(!colladaObject->m_MaterialMap.IsEOM ())
{
shared_ptr<Material> pMaterial = colladaObject->m_MaterialMap.Get ();
if(pMaterial->m_Mesh.size () != 0)
{
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &pMaterial->m_Mesh[0].m_Positions);//v[0].pos
glEnableVertexAttribArray(gvPositionHandle);
glVertexAttribPointer(gvTextureCoordhandle, 2, GL_FLOAT, GL_FALSE,sizeof(Vertex), &pMaterial->m_Mesh[0].m_Textures);//&v[0].texCoords
glEnableVertexAttribArray(gvTextureCoordhandle);
glDrawArrays(GL_TRIANGLES, 0, pMaterial->m_Mesh.size());
}
colladaObject->m_MaterialMap.MoveNext ();
}
glutSwapBuffers();
}
初始化函数:
void init()
{
char * vertexShaderBuffer = readFileData("../resources/shaders/IntroToShaders.vs");
char * pixelShaderBuffer = readFileData("../resources/shaders/IntroToShaders.ps");
gProgram = createProgram(vertexShaderBuffer, pixelShaderBuffer);
//We have finished compiling the shader now delete the char arrays with the source code
delete [] vertexShaderBuffer;
delete [] pixelShaderBuffer;
gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
gvTextureCoordhandle = glGetAttribLocation(gProgram, "vTextureCoord");
gvModelMatrixHandle = glGetUniformLocation(gProgram, "modelview_matrix");
if (gvPositionHandle==-1)
printf("gvPositionHandle is bad\n");
if (gvTextureCoordhandle==-1)
printf("gvTextureCoordhandle is bad\n");
if (gvModelMatrixHandle==-1)
printf("gvModelMatrixHandle is bad\n");
glUseProgram(gProgram);
//cube = new ObjParser("../resources/mesh/cube.obj");
colladaObject = new ColladaParser("../resources/mesh/car.dae");
loadTextures();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
loadTextures函数:
void loadTextures ()
{
//just try loading the first texture to make sure all the other code changes work before playing with this one.
colladaObject->m_MaterialMap.StartIterator ();
shared_ptr<Material> pMaterial = colladaObject->m_MaterialMap.Get ();
while(pMaterial->m_TgaFile == "")
{
colladaObject->m_MaterialMap.MoveNext ();
pMaterial = colladaObject->m_MaterialMap.Get ();
}
char tgafile [100];
strcpy(tgafile, "../resources/textures/");
strcat(tgafile, pMaterial->m_TgaFile.c_str ());
TgaParser explosion(tgafile);
}
TgaParser构造函数的END(实际上还有很多地方可以打开文件并读取位等)
unsigned char * imageData = (unsigned char*)getData (fp, size, imageBits);
myId=id;
glBindTexture (GL_TEXTURE_2D, id);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/* glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); */
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D (GL_TEXTURE_2D, 0, texFormat, imageWidth, imageHeight, 0, texFormat, GL_UNSIGNED_BYTE, imageData);
/* release data, its been uploaded */
free (imageData);
fclose(fp);
id++;
在渲染过程中没有很好的方法来切换纹理。 您需要做的是按纹理(材质)分开网格,分别绘制它们,并使用glBindTexture(GL_TEXTURE_2D, id)
在绘制调用之间切换纹理(以及材质的均匀值glBindTexture(GL_TEXTURE_2D, id)
。
恭喜您的Collada解析器; 当然,这是一项复杂的任务; 您可以使用第三方工具为您做到这一点,但是我敢肯定,这是一种很好的做法,需要您自己学习。
关于纹理,一种选择是使用纹理图集,将纹理组合成单个纹理,然后只需绑定一次并使用不同的纹理坐标,这将使您绘制所有对象而无需进行任何纹理更改。 查找纹理图集。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.