【问题标题】:Multiple Textures bound to single VBO and Rendered With Shaders (LWJGL)多个纹理绑定到单个 VBO 并使用着色器渲染 (LWJGL)
【发布时间】:2014-04-04 22:14:58
【问题描述】:

目前,我有一个 OBJ 加载器,可以加载必要的 OBJ,解析材质,并在必要时绑定纹理。

但是,我需要澄清一下,当顶点指针在您刚刚绑定的 VBO 中移动时,您是否可以绑定多个纹理。我的意思是:我想在一个 VBO 中将多种材质放在不同的网格中。研究告诉我我需要使用着色器,但没有指定如何在 VBO 中途加载它们。

我正在尝试尽量减少绘图调用和 VBO 的数量,同时(希望)尽可能远离多重纹理。非常感谢任何帮助!

当前绘制代码:

private void Run() {
    GetInput inputController = new GetInput();
    while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
        CalculateFPS();
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        //Get Input
        GL11.glLoadIdentity();
        inputController.GetMouse();
        inputController.GetKeyboard();
        //Rotate
        GL11.glRotated(inputController.mousey, 1, 0, 0);
        GL11.glRotated(inputController.mousex, 0, 1, 0);
        //Move
        GL11.glTranslated(inputController.position.x, inputController.position.y, inputController.position.z);
        //Draw
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY); //Allow vertex arrays
        GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY); //Allow normal arrays
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBO_OBJ.vertexVBO); //Bind vertexVBO for drawing
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);  //Setup vertexPointer for drawing
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, VBO_OBJ.normalVBO); //Bind normalVBO for drawing
        GL11.glNormalPointer(GL11.GL_FLOAT, 0, 0L); //Setup normalPointer for drawing
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, VBO_OBJ.totalVertices); //Draw!
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); //Unbind
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
        //Update Display
        Display.update();
        Display.sync(1000);
    }
    System.exit(0);
}

【问题讨论】:

    标签: java opengl lwjgl


    【解决方案1】:

    您需要绘制部分(参见 glDrawArrays 的第二个和第三个参数),在每个部分之后,您可以执行状态切换(例如调整绑定的纹理,调整着色器),或者您必须对着色器进行编程,以便它可以在没有“状态开关”的情况下进行渲染。这可能的扩展完全取决于状态开关的类型和“可编程管道”的当前可能性。

    例如,如果您当前拥有的唯一状态开关是纹理。您可以将纹理放在纹理数组(或采样器数组)中;在您的对象几何体中,您需要添加一个属性来确定使用哪个“纹理层”进行采样。由于属性必须存储在您的顶点缓冲区中,因此它也成为一个复杂的问题,即使其可批处理消耗多少空间与净性能增益。 p>

    Original:
    sampler2d texture;
    varying vec2 uv;
    void main()
    {
        vec4 color = texture2D(texture, uv);
    }
    
    Array of samplers:
    sampler2d texture[32];
    varying vec2 uv;
    varying float layer;
    
    void main()
    {
        vec4 color = texture2D(texture[layer], uv);
    }
    
    Texture Array version:
    sampler2dArray texture;
    varying vec2 uv;
    varying float layer;
    
    void main()
    {
        vec4 color = texture3D(texture, vec3(uv, layer));
    }
    

    请注意,上面的代码只是粗略的伪代码。

    【讨论】:

    • 当你说在你的对象几何中放置一个属性时,那会是什么样子?你的意思是第 3 个坐标是纹理层的纹理 3 吗?
    • 那将是一个准确的解释是的。
    • 你如何将这些信息提供给你的着色器?
    • 就像任何其他属性一样,使用 glVertexAttribPointer (khronos.org/opengles/sdk/docs/man/xhtml/…)。尝试有关着色器和现代 opengl 的教程,因为您应该快速接触它并且可以更彻底地解释。
    • 在可编程管道中,glVertexAttribPointer 取代了 glVertexPointer、glNormalPointer 和相关家族。您可以调用 glVertexAttribPointer 来设置位置数据,调用来设置法线数据,调用来设置 uv 数据,调用来设置层数据等。请参阅arcsynthesis.org/gltut/Basics/Tut02%20Vertex%20Attributes.html(它使用颜色作为示例而不是法线)。
    猜你喜欢
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多