Java 绑定到单个VBO并使用着色器(LWJGL)渲染的多个纹理

Java 绑定到单个VBO并使用着色器(LWJGL)渲染的多个纹理,java,opengl,lwjgl,Java,Opengl,Lwjgl,目前,我有一个OBJ加载程序,可以加载必要的OBJ,解析材质,并在必要时绑定纹理 但是,我需要澄清,当顶点指针在刚刚绑定的VBO中移动时,是否可以绑定多个纹理。我的意思是:我想在一个VBO中跨不同网格放置多个材质。研究告诉我需要使用着色器,但没有指定如何在VBO中间加载它们 我正在尽量减少绘图调用和VBO的数量,同时(希望)尽可能远离多重纹理。非常感谢您的帮助 当前绘图代码: private void Run() { GetInput inputController = new GetI

目前,我有一个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);
}
您需要绘制顶点缓冲区的部分(请参见glDrawArrays的第二个和第三个参数),在每个部分之后,您可以执行状态切换(例如调整绑定纹理、调整着色器),或者您必须对着色器进行编程,以便它可以在不使用“状态切换”的情况下进行渲染。这种可能性的范围完全取决于状态开关的类型和“可编程管道”的当前可能性

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


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

当您说在对象几何体中放置属性时,会是什么样子?你是说第三个坐标是纹理层的texture3吗?这将是一个精确的解释是的。但是如何将该信息提供给着色器?就像任何其他属性一样,使用glVertexAttributePointer()。尝试一个关于着色器和现代opengl的教程,因为您应该能够快速接触到它,并且可以得到更全面的解释。在可编程管道中,GLVERTEXAttributePointer取代了glVertexPointer、glNormalPointer和相关的系列。您可以一次调用GLVERTEXATTRIBCPOINTER来设置位置数据,一次调用来设置法线数据,一次调用来设置uv数据,一次调用来设置图层数据等。请参见(它使用颜色作为示例,而不是法线)。
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));
}