简体   繁体   English

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

[英]Texture units and vertex arrays in OpenGL

I'm trying to draw one cube with different textures for each face. 我正在尝试为每个面孔绘制一个具有不同纹理的立方体。 I've come across many tutorials which state that in the display() routines, you need to enable all texture units before calling glDrawElements() . 我遇到过许多教程,其中指出在display()例程中,需要在调用glDrawElements()之前启用所有纹理单元。 I do this my calling: 我打电话给我:

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);

This all makes sense to me. 这一切对我来说都是有意义的。 What doesn't however is how I determine which texture I am referring to when I populate the buffers (eg when I load my model data). 但是,当填充缓冲区时(例如,当加载模型数据时),我将如何确定要引用的纹理。 Thanks Chris 谢谢克里斯

What you are looking for is a cube map . 您正在寻找的是一个立方体贴图 In OpenGL, you can define six textures at once (representing the size sides of a cube) and map them using 3D texture coordinates instead of the common 2D texture coordinates. 在OpenGL中,您可以一次定义六个纹理(代表一个立方体的大小边),并使用3D纹理坐标而不是普通的2D纹理坐标进行映射。 For a simple cube, the texture coordinates would be the same as the vertices' respective normals. 对于简单的立方体,纹理坐标将与顶点各自的法线相同。 (If you will only be texturing plane cubes in this manner, you can consolidate normals and texture coordinates in your vertex shader, too!) Cube maps are much simpler than trying to bind six distinct textures simultaneously the way you are doing right now. (如果仅以这种方式对平面立方体进行纹理化,则也可以在顶点着色器中合并法线和纹理坐标!)立方体贴图比尝试同时绑定六个不同的纹理要简单得多。

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);

Now, when doing your shaders, you need the vertex shader to accept and/or pass 3D coordinates (vec3) instead of 2D coordinates (vec2). 现在,在进行着色器处理时,您需要顶点着色器接受和/或传递3D坐标(vec3)而不是2D坐标(vec2)。

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

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

In this example, your vertex shader would simply assign vTextureCoordinate = inTextureCoordinate. 在此示例中,您的顶点着色器将简单地分配vTextureCoordinate = inTextureCoordinate。 Your fragment shader then needs to accept that texture coordinate and sample the cube map uniform. 然后,片段着色器需要接受该纹理坐标并对立方体贴图统一采样。

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

Whew! 呼! That was a lot. 好多 Did I leave anything out? 我有遗漏什么吗?

What doesn't however is how I determine which texture I am referring to when I populate the buffers (eg when I load my model data). 但是,当填充缓冲区时(例如,当加载模型数据时),我将如何确定要引用的纹理。

You are referring to whichever texture you last specified with the most recent ActiveTexture call -- that call doesn't actually do anything, it justs sets a hidden state which affects all subsequent calls that do anything with textures. 您所指的是您最近一次用ActiveTexture调用最后指定的纹理-该调用实际上不执行任何操作,它只是设置一个隐藏状态,该状态会影响以后对纹理执行任何操作的所有调用。

Selecting a texture on a per-face basis is usually hard on openGL (except for some recent cards that can index an array of textures, for instance with EXT_texture_array). 在openGL上,通常很难按面选择纹理(除了一些最近的卡片可以索引纹理数组,例如使用EXT_texture_array)。 The problem is usually avoided by packing all textures in one, like this . 这样通常可以通过将所有纹理打包在一个纹理中来避免此问题

In your very specific case, though, a cubemap is perfect - if you're really sure you'll just have cubes and nothing else. 但是,在您的特定情况下,立方体贴图是完美的-如果您确实确定只有立方体,则别无选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM