【问题标题】:LWJGL texture rendering/indexingLWJGL 纹理渲染/索引
【发布时间】:2020-12-17 23:04:03
【问题描述】:

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

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

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

主要:

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

渲染类:

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

【问题讨论】:

  • 您的代码中缺少最重要的部分。在哪里指定顶点属性,尤其是在哪里指定元素缓冲区。
  • @Rabbid76 该信息位于我的网格类中。这是顶点属性起作用的函数: private int storeData(FloatBuffer buffer, int index, int size){ int bufferID = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferID); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, 缓冲区, GL15.GL_STATIC_DRAW); GL20.glVertexAttribPointer(index, size, GL11.GL_FLOAT, false, 0, 0); GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);返回缓冲区ID; }
  • @Rabbid 元素缓冲区也在网格类中指定,在其中,我给它这个信息: IntBuffer indicesBuffer = MemoryUtil.memAllocInt(indices.length); indicesBuffer.put(indices).flip(); ibo = GL15.glGenBuffers(); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo); GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW); GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo);
  • GL_ELEMENT_ARRAY_BUFFER 是顶点数组对象中的状态。在绑定GL_ELEMENT_ARRAY_BUFFER (GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ...)) 之前是否绑定了 VAO (glBindVertexArray)?
  • @Rabbid76 当 EBO 是 VAO 的一部分时,为什么我要在 EBO 之前绑定 VAO?

标签: java opengl glsl textures lwjgl


【解决方案1】:

必须为纹理采样器统一设置的值是纹理单元的索引,而不是纹理单元常量(例如: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();
}

【讨论】:

  • 感谢您的帮助,您提供的信息非常有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
相关资源
最近更新 更多