1

我正在尝试为每个面绘制一个具有不同纹理的立方体。我遇到过许多教程,其中指出在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);

这一切对我来说都很有意义。然而,当我填充缓冲区时(例如,当我加载我的模型数据时),我如何确定我指的是哪个纹理并不重要。谢谢克里斯

4

3 回答 3

2

您正在寻找的是一个立方体贴图。在 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);

哇!那是很多。我有遗漏什么吗?

于 2011-02-07T18:14:41.187 回答
1

然而,当我填充缓冲区时(例如,当我加载我的模型数据时),我如何确定我指的是哪个纹理并不重要。

您指的是您最后使用最近的 ActiveTexture 调用指定的任何纹理——该调用实际上并没有做任何事情,它只是设置一个隐藏状态,该状态会影响所有对纹理做任何事情的后续调用。

于 2011-02-07T17:25:58.117 回答
0

在 openGL 上通常很难在每个面的基础上选择纹理(除了一些最近可以索引纹理数组的卡片,例如使用 EXT_texture_array)。这个问题通常可以通过将所有纹理打包成一个来避免,就像这样

但是,在您非常具体的情况下,立方体贴图是完美的 - 如果您真的确定您只会拥有立方体而没有其他任何东西。

于 2011-02-09T13:39:54.640 回答