Использование нескольких текстур в 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);
}

///// оригинальный вопрос

Я делаю уникальное задание, в котором мне придется рисовать некоторые объекты с текстурами (и я должен быть в состоянии перемещаться по сцене и прочим вещам, но я перейду этот мост, когда доберусь до него). У меня есть учебник в качестве основы, который будет рисовать объект из одного массива вершин и одного файла текстуры, из файла .obj (я написал парсер для предыдущего урока).

В задании используются файлы collada, поэтому я написал анализатор collada. Это была действительно тяжелая работа! Мой анализатор collada создает карту, содержащую объекты Material, которые имеют множество переменных name и id (они не используются в main.cpp, они предназначены только для связывания элементов между частями файла collada), переменную m_TgaFile, которая содержит файл текстуры name как строка, и переменная m_Mesh, которая содержит вектор объектов Vertex, который является объектом, который имеет только два плавающих массива, m_Positions и m_Textures для хранения позиций и текстовых координат.

Итак, что я смог сделать до сих пор, так это нарисовать все биты, зацикливаясь на карте и просто используя первый файл текстуры на карте (он падает через несколько минут, но я пойму это позже, я просто счастлив что то появилось на экране). Я попытался вызвать 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();
}

функция инициализации:

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 (гораздо больше, где он на самом деле открывает файл и читает биты и т. Д.)

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

Решение

Нет хорошего способа переключения текстур в середине рендеринга. Вам нужно разделить сетки по текстуре (материалу), нарисовать их отдельно и переключать текстуру (и, возможно, однородные значения для материала) между вызовами рисования с помощью glBindTexture(GL_TEXTURE_2D, id),

0

Другие решения

Поздравляю с вашим анализатором Collada; это сложная задача наверняка; Есть сторонние инструменты, которые вы можете использовать, которые делают это для вас, но я уверен, что это было хорошей практикой и учиться делать это самостоятельно.

Что касается ваших текстур, одним из вариантов является использование текстурного атласа, в котором вы объединяете свои текстуры в одну текстуру, тогда вам нужно всего лишь связать ее один раз и использовать разные текстурные координаты, что позволит вам рисовать все ваши объекты без каких-либо изменений текстуры. Поиск текстурного атласа.

0