Как я могу добавить несколько текстур в мою программу openGL? - PullRequest
1 голос
/ 22 апреля 2019

Я пишу программу openGL, и в среду меняются несколько моделей, но я не знаю, как применять разные текстуры к каждой из этих моделей, поэтому на данный момент все они имеют одинаковую текстуру.Я читал, что мне нужно добавить несколько текстурных блоков в программу или использовать текстурный атлас.Текстурный атлас кажется более сложным, поэтому я пытаюсь добавить текстурные блоки.

Я думал, что этот процесс работает так:

  1. Создание двух текстурных блоков с помощью glGenTextures.
  2. Свяжите данные первого изображения с первым текстурным блоком с помощью glBindTexture и glTexImage2D.
  3. Сделайте то же самое со вторым изображением.

Отсюда, я думал, чтомог бы сказать openGL, какой текстурный модуль я хочу использовать, используя glActiveTexture.Кажется, что это работает только с одной текстурой (то есть пропустить шаг 3), но не с двумя или более.

Я уверен, что что-то упустил, так что кто-то может указать мне правильное направление?

//Generate textures
int texturec=2;
int w[texturec],h[texturec];
unsigned char *data[texturec];
data[0]=getImage(&w[0],&h[0],"resources/a.png");
data[1]=getImage(&w[1],&h[1],"resources/b.png");

//Apply textures
GLuint textures[texturec];
glGenTextures(texturec, textures);

//Bind a.png to the first texture unit
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[0], h[0], 0, GL_RGB, GL_UNSIGNED_BYTE, data[0]);

//Bind b.png to the second texture unit
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[1], h[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data[1]);

glActiveTexture(GL_TEXTURE0);

//Not super clear on what this does, but it needs to be here.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

А вот мои шейдеры:

Фрагмент:

#version 330 core

in vec2 UV;
out vec3 color;

uniform sampler2D textureSampler;

void main(){
    color=texture(textureSampler,UV).rgb;
}

Вершина:

#version 330 core

layout(location=0) in vec3 vertexPos;
layout(location=1) in vec2 vertexUV;

out vec2 UV;

uniform mat4 MVP;

void main(){
    gl_Position=MVP*vec4(vertexPos,1);
    UV=vertexUV;
}

Редактировать:

Вотмой новый код после применения предложений Rabid76:

//Generate textures
int texturec=2;
int w[texturec],h[texturec];
unsigned char *data[texturec];
data[0]=getImage(&w[0],&h[0],"resources/a.png");
data[1]=getImage(&w[1],&h[1],"resources/b.png");

//Apply textures
GLuint textures[texturec];
glGenTextures(texturec, textures);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[0], h[0], 0, GL_RGB, GL_UNSIGNED_BYTE, data[0]);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[1], h[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data[1]);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

//Shaders
programID=loadShaders("shaders/vertex.shader","shaders/fragment.shader");
glUseProgram(programID);

//Use texture unit 1
glActiveTexture(GL_TEXTURE1);
GLint texLoc=glGetUniformLocation(programID, "textureSampler");
glUniform1i(texLoc, 1);

1 Ответ

3 голосов
/ 22 апреля 2019
  1. Создание двух текстурных блоков с помощью glGenTextures.

Нет. glGenTextures не генерирует текстурный блок.

glGenTextures резервирует имя (имена), которые могут использоваться для объектов текстуры.

glBindTexture привязывает именованную текстуру к цели текстурирования. Когда вызывается эта функция, объект текстуры привязывается к текущему текстурному блоку.
Текущий текстурный блок можно установить с помощью glActiveTexture:

, например

GLuint textures[texturec];
glGenTextures(texturec, textures);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
// [...]

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
// [...]

Значение имени текстурных объектов и единица текстуры - это совершенно разные вещи.
Единица текстуры - это точка привязки между объектом текстуры и программой шейдера.
С одной стороны, объект текстуры должен быть привязан к единице текстуры, с другой стороны, для единицы текстуры должен быть установлен равномерный образец текстуры. Таким образом, текстурный блок является «связью» между ними.

Начиная с версии 4.2 GLSL, текстурный блок может быть установлен с помощью Qualifier Layout (GLSL) внутри шейдера. Точка привязки соответствует единице текстуры. например binding = 1 означает текстурный блок 1:

layout(binding = 1) uniform sampler2D textureSampler;

В качестве альтернативы индекс единицы текстуры можно присвоить униформе сэмплера текстуры с помощью glUniform1i:

GLint texLoc = glGetUniformLocation(programID, "textureSampler");
glUniform1i(texLoc, 1);

Если шейдерная программа использует 1 равномерный сэмплер текстуры

uniform sampler2D textureSampler;

тогда достаточно связать соответствующий объект текстуры перед вызовом отрисовки:

glActiveTexture(GL_TEXTURE0); // this is default 
glBindTexture(GL_TEXTURE_2D, textures[0]);

Но если шейдерная программа использует несколько форм текстурного сэмплера (одной и той же цели), то разные объекты текстуры должны быть связаны с разными единицами текстуры:

, например

layout(binding = 3) uniform sampler2D textureSampler1;
layout(binding = 4) uniform sampler2D textureSampler2;
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, textures[1]);

соответственно

layout(location = 7) uniform sampler2D textureSampler1;
layout(location = 8) uniform sampler2D textureSampler2;
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, textures[1]);

glUseProgram(programID);
glUniform1i(7, 3); // location = 7 <- texture unit 3
glUniform1i(8, 4); // location = 8 <- texture unit 4
...