【问题标题】:Texture units and vertex arrays in OpenGLOpenGL中的纹理单元和顶点数组
【发布时间】:2011-02-07 16:28:01
【问题描述】:

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

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

【问题讨论】:

    标签: opengl textures multitexturing


    【解决方案1】:

    您正在寻找的是cube map。在 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);
    

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

    【讨论】:

    • 好的,我正在发布关于您其他问题的更新,我猜...?我也会在这里发布。
    • 感谢您的回复。现在它变得更有意义了。然而,为了简单起见,我只是使用了一个立方体的例子,我试图加载的模型实际上有 30 多个纹理。您能否建议对您的解决方案进行扩展以允许更多纹理?
    • 那么你有几个选择。一种是按纹理组织几何图形,并使用适当的纹理单独渲染每个块。另一种常见的技术是将所有纹理放在一个纹理表上,然后简单地使用适当的坐标来抓取正确的纹理。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        相关资源
        最近更新 更多