简体   繁体   English

在OpenGL中使用多个纹理

[英]Using multiple textures in OpenGL

Update: I can draw multiple textures now, I figured out how glGenTextures etc works, and rewrote my loadtextures () function and stuff. 更新:我现在可以绘制多个纹理,弄清楚glGenTextures等如何工作,并重写了loadtextures()函数和其他东西。 However only a few parts of the car are drawn; 但是,只绘制了汽车的一些零件。 the steering wheel, one hub cap and the back lights (and maybe a few smaller things). 方向盘,一个轮毂盖和后灯(也许还有一些小东西)。 In the collada file a few materials don't ever get associated with a texture file. 在collada文件中,一些材质永远不会与纹理文件关联。 I don't think this is the problem because on my first go I associated the textures in the list with the first couple of polylists (5, there are like 80 total), and I got a nice car that looked like it was using the right textures, just missing tires and maybe some small things I didn't notice. 我不认为这是问题所在,因为在我第一次尝试时,我便将列表中的纹理与前两个多列表关联起来(5个,总共有80个),并且我得到了一辆看起来像是在使用正确的纹理,只是缺少轮胎,也许还有一些我没有注意到的小东西。 I think maybe it has something to do with textures that get tiled? 我认为也许与平铺的纹理有关? Anyway I wanted to replace all the meshes that have no texture files with the colour red, but I am not sure how to do that. 无论如何,我想用红色替换所有没有纹理文件的网格,但是我不确定该怎么做。 I started using code in this tutorial: 我在本教程中开始使用代码:

http://www.opengl-tutorial.org/beginners-tutorials/tutorial-4-a-colored-cube/ http://www.opengl-tutorial.org/beginners-tutorials/tutorial-4-a-colored-cube/

I made a colour buffer, bound it, etc, but then I realised I would need to edit the shader files and I am not sure how to do that. 我做了一个颜色缓冲区,将它绑定等等,但是后来我意识到我需要编辑着色器文件,但我不确定该怎么做。

One: 一:

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

The other: 另一个:

varying  vec2 vTexCoord; 
uniform sampler2D myTexture;
void main (void)  
{  
   gl_FragColor =  texture2D(myTexture, vTexCoord);     
}

/////original question /////原始问题

I am doing a uni assignment where I will have to draw some objects with textures (and I'll have to be able to move around the scene and stuff but I'll cross that bridge when I get to it). 我正在做一个uni作业,其中我将不得不绘制一些带有纹理的对象(而且我必须能够在场景和东西周围移动,但是当我到达它时,我将越过那座桥)。 I have a tutorial as a base which will draw an object from a single array of vertices and a single texture file, from a .obj file (I wrote the parser for the previous tutorial). 我有一个教程作为基础,它将从单个顶点数组和单个纹理文件(从.obj文件)绘制对象(我为上一教程编写了解析器)。

The assignment uses collada files, so I have written a collada parser. 该作业使用collada文件,因此我编写了collada解析器。 It was REALLY hard work! 这真的很辛苦! My collada parser produces a map that contains Material objects, which have lots of name and id variables (not used in main.cpp, they are just for associating stuff between parts of of the collada file), an m_TgaFile variable which holds the texture file name as a string, and an m_Mesh variable which holds a vector of Vertex objects, which is an object that just has two float arrays, m_Positions and m_Textures to hold the positions and tex co-ordinates. 我的collada解析器生成了一个包含Material对象的映射,该对象具有很多名称和id变量(在main.cpp中未使用,它们仅用于在collada文件的各个部分之间关联内容),一个m_TgaFile变量,用于保存纹理文件名称为字符串,以及一个m_Mesh变量,该变量保存一个Vertex对象的矢量,该对象只有两个浮点数组,即m_Positions和m_Textures,用于保存位置和tex坐标。

So what I have been able to do so far is draw all the bits by looping over the map and just using the first texture file in the map (it crashes after a few minutes but I'll figure that out later, I am just happy that something appeared on screen). 因此,到目前为止,我能够做的是通过遍历地图并仅使用地图中的第一个纹理文件来绘制所有位(几分钟后崩溃,但我会发现以后很高兴屏幕上出现了一些东西)。 I tried calling loadTextures () (and sending in a Material) where I am looping over the map so I could use each Material's texture file but nothing drew at all (white screen). 我尝试在地图上循环调用loadTextures()(并发送一个Material),以便可以使用每个Material的纹理文件,但一点都没画(白屏)。 So how do I load each texture for each bit of drawing? 那么,如何为绘图的每一位加载每种纹理?

I have tried researching it, and have come up with the fact I need to use glBindTexture, glTexImage2D, and another one I can't remember. 我已经尝试研究它,并且得出一个事实,我需要使用glBindTexture,glTexImage2D和我不记得的另一个。 The first two are in the TgaParser which came with my tutorial. 前两个在我的教程随附的TgaParser中。 glBindTexture is used again in the drawing code, with a second parameter of zero. 在绘图代码中再次使用glBindTexture,第二个参数为零。 From what I gather this means use the default texture that was loaded. 根据我的收集,这意味着使用已加载的默认纹理。 I can't figure out though how to load each texture when I want it, I don't understand what texture names means and how that gets associated with texture data. 我无法弄清楚如何在需要时加载每个纹理,我不了解纹理名称的含义以及将其与纹理数据关联的方式。

Oh and I have tried doing the looping in the OpenGl main function and sending pMaterial as a variable to the display function but it didn't like that, I didn't think it would work but I thought I'd at least try. 哦,我尝试过在OpenGl主函数中进行循环,并将pMaterial作为变量发送到显示函数,但它不是那样的,我认为它不会起作用,但我认为我至少会尝试。

Here is some code. 这是一些代码。

The OpenGL main function: 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;
}

Drawing function: 绘图功能:

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

the init function: 初始化函数:

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

The loadTextures function: 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);
}

The END of the TgaParser constructor (there is lots more where it actually opens the file and reads through the bits etc) 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++;

There is no good way to switch textures in the middle of rendering. 在渲染过程中没有很好的方法来切换纹理。 What you need to do is separate the meshes by texture (material), draw them separately and switch the texture (and possibly uniform values for the material) between draw calls with glBindTexture(GL_TEXTURE_2D, id) . 您需要做的是按纹理(材质)分开网格,分别绘制它们,并使用glBindTexture(GL_TEXTURE_2D, id)在绘制调用之间切换纹理(以及材质的均匀值glBindTexture(GL_TEXTURE_2D, id)

Congrats on your Collada parser; 恭喜您的Collada解析器; that's a complex task for sure; 当然,这是一项复杂的任务; there are third-party tools you can use that do that for you, but I'm sure it was good practice and learning to do it yourself. 您可以使用第三方工具为您做到这一点,但是我敢肯定,这是一种很好的做法,需要您自己学习。

Regarding your textures, one option is to use a texture atlas where you combine your textures into a single texture, then you only have to bind it once and use different texture coordinates, which would let you draw all your objects without making any texture changes. 关于纹理,一种选择是使用纹理图集,将纹理组合成单个纹理,然后只需绑定一次并使用不同的纹理坐标,这将使您绘制所有对象而无需进行任何纹理更改。 Lookup texture atlas. 查找纹理图集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM