在OpenGL中使用多个纹理

时间:2013-04-21 03:02:32

标签: c++ opengl textures collada

更新:我现在可以绘制多个纹理,我弄清楚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);     
}

/////原始问题

我正在做一个单一的任务,我将不得不用纹理绘制一些对象(我必须能够在场景和东西周围移动但是当我到达它时我将穿过那座桥)。我有一个教程作为基础,它将从.obj文件(我编写前一个教程的解析器)中从单个顶点数组和单个纹理文件中绘制一个对象。

该作业使用了collada文件,因此我编写了一个collada解析器。这真的很辛苦!我的collada解析器生成一个包含Material对象的map,它有很多名称和id变量(不在main.cpp中使用,它们只用于关联collada文件各部分之间的东西),一个保存纹理文件的m_TgaFile变量name作为一个字符串,一个m_Mesh变量,它包含一个Vertex对象的向量,它是一个只有两个float数组的对象,m_Positions和m_Textures来保存position和tex坐标。

所以到目前为止我能够做的是通过循环遍历地图并使用地图中的第一个纹理文件来绘制所有位(它在几分钟后崩溃但我稍后会想到,我我很高兴屏幕上出现了一些东西。我尝试调用loadTextures()(并在材质中发送)我在地图上循环,所以我可以使用每个材质的纹理文件,但根本没有任何东西(白色屏幕)。那么如何为每个绘图位加载每个纹理?

我已经尝试过研究它,并提出了我需要使用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();
}

init函数:

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++;

2 个答案:

答案 0 :(得分:0)

在渲染过程中切换纹理没有好方法。您需要做的是通过纹理(材质)分离网格,单独绘制它们并在glBindTexture(GL_TEXTURE_2D, id)的绘制调用之间切换纹理(可能是材质的统一值)。

答案 1 :(得分:0)

祝贺你的Collada解析器;这肯定是一项复杂的任务;您可以使用第三方工具为您做到这一点,但我确信这是一种很好的做法并且学会自己动手。

关于你的纹理,一个选项是使用纹理图集,你将纹理组合成一个纹理,然后你只需要绑定一次并使用不同的纹理坐标,这样你就可以绘制所有的对象,而不需要任何纹理纹理变化。查找纹理图集。