LWJGL 纹理 rendering/indexing

LWJGL texture rendering/indexing

我目前在尝试通过单个顶点和片段着色器将两个纹理渲染到两个完全独立的对象时遇到问题。问题似乎在于尝试索引两个纹理并将其绑定到它们自己的对象上。在尝试索引和绑定纹理时,较小的索引将始终出现在两个对象上。

有人可以帮助我,或者至少将我推向正确的方向吗?

这是我的主要 class、渲染器和片段着色器的代码。 (随时请求更多代码)

主要内容:

import Engine.IO.Image;
import Engine.IO.Input;
import Engine.IO.Window;
import Engine.graphics.*;
import Engine.maths.Vector2f;
import Engine.maths.Vector3f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL13;

public class Main implements Runnable {
    public Thread game;
    public  Window window;
    public Renderer renderer;
    public Shader shader;
    public  final int WIDTH = 1280, HEIGHT = 720;
    private String[] textureImageNames = {"nice_dude.jpg", "color.jpg", "pepe.jpg"};

    public GameObject thing1 = new GameObject(new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
            new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
            new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
            new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
            new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
    }, new int[]{
            0, 1, 2, 0, 3, 2
    }), new Material(textureImageNames[0]));

    public GameObject thing2 = new GameObject(new Vector3f(1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
            new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
            new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
            new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
            new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
    }, new int[]{
            0, 1, 2, 0, 3, 2
    }), new Material(textureImageNames[2]));

    public Camera camera = new Camera(new Vector3f(0, 0, 1), new Vector3f(0, 0,0));

    public void start(){
        game = new Thread(this,"game");
        game.start();
    }

    public void init(){
        System.out.println("Initializing Game!");
        window = new Window(WIDTH, HEIGHT, "Game");
        shader = new Shader("/shaders/mainVertex.glsl", "/shaders/mainFragment.glsl");
        window.setBackgroundColor(0.0f, 0.5f, 0.0f);
        window.create();
        thing1.getMesh().create();
        thing2.getMesh().create();
        thing1.getMaterial().create(new Image());
        thing2.getMaterial().create(new Image());
        shader.create();
        renderer = new Renderer(window, shader);
        renderer.renderMesh();
        renderer.enableShaderProgram();
        renderer.bindVAO(thing1);
        renderer.bindVAO(thing2);
        renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0);
        renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1);
    }

    public void run(){
        init();
        while(!window.shouldClose() && !Input.isKeyDown(GLFW.GLFW_KEY_ESCAPE)){
            update();
            render();
            if(Input.isKeyDown(GLFW.GLFW_KEY_F11)){window.setFullscreen(!window.isFullscreen());}
        }
        close();
    }

    private void update(){
        //System.out.println("updating Game!");
        window.update();
        camera.update();
    }

    private void render(){
        renderer.updateRenderer(thing1);
        renderer.updateRenderer(thing2);
        renderer.renderCamera(camera);
        window.swapBuffers();
    }

    private void close(){
        window.destroy();
        thing1.getMesh().destroy();
        thing1.destroyMaterial();
        thing2.getMesh().destroy();
        thing2.destroyMaterial();
        shader.destroy();
        renderer.destroyRenderer();
    }

    public static void main(String[] args){
        new Main().start();
    }
}

渲染 class:

package Engine.graphics;

import Engine.IO.Window;
import Engine.maths.Matrix4f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.opengl.*;

public class Renderer {
    private Shader shader;
    private Window window;

    public Renderer(Window window, Shader shader){
        this.shader = shader;
        this.window = window;
    }

    public void renderMesh() {
        GL30.glEnableVertexAttribArray(0);
        GL30.glEnableVertexAttribArray(1);
        GL30.glEnableVertexAttribArray(2);
    }

    public void enableShaderProgram(){
        shader.bind();
    }

    public void bindVAO(GameObject object){
        GL30.glBindVertexArray(object.getMesh().getVAO());
    }

    public void setUniformIndex(GameObject object, String textureName, int index){
        GL13.glActiveTexture(index);
        shader.setUniform(textureName, index);
        GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
    }

    public void updateRenderer(GameObject object){
        GL11.glDrawElements(GL11.GL_TRIANGLES, object.getMesh().getIndices().length, GL11.GL_UNSIGNED_INT, 0);

        shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale()));
        shader.setUniform("projection", window.getProjectionMatrix());
    }

    public void renderCamera(Camera camera){
        shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation()));
    }

    public void destroyRenderer(){
        shader.unBind();
        GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        GL30.glDisableVertexAttribArray(0);
        GL30.glDisableVertexAttribArray(1);
        GL30.glDisableVertexAttribArray(2);
        GL30.glBindVertexArray(0);
    }
}

片段着色器:

#version 460 core

in vec3 passColor;
in vec2 passTextureCoord;

out vec4 outColor;

uniform sampler2D tex;
uniform sampler2D tex2;

void main(){
    outColor = texture(tex, passTextureCoord);
    outColor = texture(tex2, passTextureCoord);
}

必须设置为纹理采样器统一的值是纹理单元的索引而不是纹理单元常量(例如:GL13.GL_TEXTURE0 为 0,GL13.GL_TEXTURE1 为 1):

public void setUniformIndex(GameObject object, String textureName, int unit, int index){
    shader.setUniform(textureName, index);
    GL13.glActiveTexture(unit);
    GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
}

OpenGL 是一个状态引擎。绑定 VAO 和/或纹理对象会更改全局状态。不可能一次绑定 2 个对象。只说明最后一个绑定的对象。您必须在绘制调用之前绑定顶点数组对象和纹理对象:

private void render(){
        
    renderer.bindVAO(thing1);
    renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0, 0);
    renderer.updateRenderer(thing1);
    
    renderer.bindVAO(thing2);
    renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1, 1);
    renderer.updateRenderer(thing2);
    
    renderer.renderCamera(camera);
    window.swapBuffers();
}