问题描述
我目前在尝试通过单个顶点和片段着色器将两个纹理渲染到两个完全独立的对象上时遇到问题。问题似乎在于试图建立索引,并将两个纹理绑定到它们自己的对象上。在尝试索引和绑定纹理时,较小的索引将始终出现在两个对象上。
有人可以帮助我,或者至少将我推向正确的方向吗?
这是我的主类,渲染器和片段着色器的代码。 (随时要求提供更多代码)
主要:
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),new Vector3f(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,new Vector2f(1.0f,-0.5f,1.0f)),new Vertex(new Vector3f(-0.5f,1.0f))
},new int[]{
0,2,3,2
}),new Material(textureImageNames[0]));
public GameObject thing2 = new GameObject(new Vector3f(1,new Material(textureImageNames[2]));
public Camera camera = new Camera(new Vector3f(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.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);
}
解决方法
必须设置为纹理采样器统一的值是纹理单位的索引,而不是纹理单位常数(例如: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();
}