Единицы текстуры и вершинные массивы в OpenGL - PullRequest
1 голос
/ 07 февраля 2011

Я пытаюсь нарисовать один куб с разными текстурами для каждого лица.Я сталкивался со многими учебниками, в которых говорится, что в подпрограммах display() вам необходимо включить все текстурные блоки перед вызовом glDrawElements().Я делаю это мое призвание:

gl.glClientActiveTexture(GL.GL_TEXTURE0);
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getTexCoordBufferObject());
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);

gl.glClientActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId+1);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getTexCoordBufferObject());
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);

...

gl.glClientActiveTexture(GL.GL_TEXTURE5);
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId+5);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getTexCoordBufferObject());
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);

Это все имеет смысл для меня.Однако не то, как я определяю, на какую текстуру я ссылаюсь, когда заполняю буферы (например, когда я загружаю данные модели).Спасибо Крис

Ответы [ 3 ]

2 голосов
/ 07 февраля 2011

То, что вы ищете, это карта куба . В OpenGL вы можете определить шесть текстур одновременно (представляющих стороны размера куба) и отобразить их, используя координаты 3D-текстуры вместо общих координат 2D-текстуры. Для простого куба координаты текстуры будут такими же, как и соответствующие нормали вершин. (Если вы будете таким образом текстурировать только плоские кубы, вы также можете объединить нормали и координаты текстур в своем вершинном шейдере!) Карты кубов намного проще, чем пытаться одновременно связать шесть различных текстур, как вы делаете сейчас.

GLuint mHandle;
glGenTextures(1, &mHandle); // create your texture normally

// Note the target being used instead of GL_TEXTURE_2D!
glTextParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTextParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glBindTexture(GL_TEXTURE_CUBE_MAP, mHandle);

// Now, load in your six distinct images. They need to be the same dimensions!
// Notice the targets being specified: the six sides of the cube map.
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data1);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data2);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data3);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data4);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data5);
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, width, height, 0,
    format, GL_UNSIGNED_BYTE, data6);

glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
glTextParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

// And of course, after you are all done using the textures...
glDeleteTextures(1, &mHandle);

Теперь, когда вы делаете свои шейдеры, вам нужен вершинный шейдер, чтобы принимать и / или передавать 3D-координаты (vec3) вместо 2D-координат (vec2).

// old GLSL style
attribute vec3 inTextureCoordinate;
varying vec3 vTextureCoordinate;

// more recent GLSL
in vec3 inTextureCoordinate;
out vec3 vTextureCoordinate;

В этом примере ваш вершинный шейдер просто назначит vTextureCoordinate = inTextureCoordinate. Затем ваш фрагментный шейдер должен принять эту текстурную координату и сэмплировать форму карты куба.

uniform samplerCube cubeMap;
...
gl_FragColor = textureCube(cubeMap, vTextureCoordinate);

Уф! Это было много. Я что-нибудь пропустил?

1 голос
/ 07 февраля 2011

Однако не то, как я определяю, к какой текстуре я обращаюсь, когда заполняю буферы (например, когда я загружаю данные модели).

Вы имеете в виду любую текстуру, которую вы указали последним с помощью самого последнего вызова ActiveTexture - этот вызов на самом деле ничего не делает, он просто устанавливает скрытое состояние, которое влияет на все последующие вызовы, которые что-либо делают с текстурами.

0 голосов
/ 09 февраля 2011

Выбор текстуры для каждого лица обычно труден для openGL (за исключением некоторых последних карт, которые могут индексировать массив текстур, например, с помощью EXT_texture_array). Эту проблему обычно избегают, упаковав все текстуры в одну, например this .

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

...