OpenGL中的纹理单元和顶点数组

时间:2011-02-07 16:28:01

标签: opengl textures multitexturing

我正在尝试为每个脸部绘制一个具有不同纹理的立方体。我遇到过许多教程,声明在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 个答案:

答案 0 :(得分:2)

您要找的是cube map。在OpenGL中,您可以一次定义六个纹理(表示立方体的大小边)并使用3D纹理坐标而不是常见的2D纹理坐标来映射它们。对于简单的立方体,纹理坐标将与顶点的相应法线相同。 (如果您只是以这种方式对平面立方体进行纹理化,您也可以在顶点着色器中合并法线和纹理坐标!)立方体贴图比尝试以您现在的方式同时绑定六个不同的纹理要简单得多。 / p>

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 :(得分:1)

  

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

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

答案 2 :(得分:0)

在openGL上选择纹理通常很难(除了一些最近可以索引纹理数组的卡,例如使用EXT_texture_array)。通常将所有纹理打包在一个中来避免这个问题,例如this

在你非常具体的情况下,立方体贴图是完美的 - 如果你真的确定你只有立方体而没有别的。