为什么我的模型没有在 LWJGL 中使用着色器和 VBO 渲染任何东西
why is my model not rendering anything using shader and VBO in LWJGL
我正在开发一款简单的类似 Minecraft 的游戏,但我曾经使用过一些旧的着色器系统,我想开始使用现代着色器,但我在使用渲染时遇到了困难,屏幕上什么也没有出现...
我尝试过不同的东西:
- glGetError() return 0
- 我试图在片段着色器中 return vec4(1,0,1,1) 但它没有用所以我认为这是顶点着色器中的一个错误...
那么你能帮我弄清楚我的错误在哪里吗?
代码如下:https://pastebin.com/dWJQkFZu
这是我的渲染循环:
public void render(){
//check for resize
if(Display.wasResized()){
glViewport(0, 0, Display.getWidth(), Display.getHeight());
guiManager.recalculate();
}
//create perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective(Camera.fov, (float)Display.getWidth()/(float)Display.getHeight(), 0.1f, 1000000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
cam.render();
world.render();
skybox.render(cam.player.position);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
if(Camera.debug){
FontManager.getDefaultFont().drawString(0, 0, "Debug - SaintsCube v-A0.5");
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()+1, "x: "+Math.floor(player.position.x));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*2+2, "y: "+Math.floor(player.position.y));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*3+3, "z: "+Math.floor(player.position.z));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*4+4, "yaw: "+Math.floor(player.rotation.x*-1));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*5+5, "pitch: "+Math.floor(player.rotation.y));
}
guiManager.render();
glDisable(GL_ALPHA_TEST);
}
我的着色器:
chunk.vs:
#version 330
in vec3 position;
in vec2 texcoord;
in vec4 color;
uniform mat4 MVP;
out vec2 pass_texcoord;
out vec4 pass_color;
void main() {
pass_texcoord = texcoord;
pass_color = color;
gl_Position = MVP * vec4(position, 1.0);
}
chunk.fs:
#version 330
out vec4 fragcolor;
uniform sampler2D sampler;
in vec2 pass_texcoord;
in vec4 pass_color;
void main() {
vec4 texturecolor = texture(sampler, pass_texcoord) * pass_color;
if(texturecolor.a <= 0.5){
discard;
}
fragcolor = texturecolor;
}
请帮帮我:)
如果你想开始使用现代着色器方式,你不能使用立即方法。一切都将在着色器中计算(你必须自己编写,没有 opengl 预定义的优点)。所以不是调用
glTranslate3f(x, y, z);
你必须创建你自己的模型矩阵,它被发送到着色器,在那里它被应用到模型顶点的位置。现代 OpenGL 的重点是最小化与它的交互。不是让 CPU 和 GPU 携手工作(GPU 希望 运行 更快,CPU 是瓶颈),而是让 CPU 做一些数学运算,完成后推送一口气传给GPU。
虽然你的顶点着色器已经在期待矩阵,但它没有得到它,因为它在你的 Java 代码中丢失,你从未传递任何矩阵。
统一 mat4 MVP;
大例子:
顶点着色器代码:
#version 330 core
in vec4 position;
in vec4 color;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec4 vertexColor;
void main() {
// Just pass the color down to the fragment shader
vertexColor = color;
// Calculate the Model, View, Projection matrix into one ( in this order, right to left )
mat4 mvp = projection * view * model;
// Calculate the position of the vertex
gl_Position = mvp * vec4(position.xyz,1);
}
片段着色器代码:
#version 330 core
in vec4 vertexColor;
out vec4 fragColor;
void main() {
fragColor = vec4(vertexColor.xyz,1);
}
我没有看到你的着色器编译代码,但我假设它是正确的...(生成着色器 ID,将源代码放入着色器,编译,生成程序并将两个着色器附加到它)
编译后你必须告诉 OpenGL 输出颜色去哪里:
glBindFragDataLocation(program, 0, "fragColor");
加载模型时,您还需要切换到现代 Vertex Buffer A 阵列的。默认一个VBA可以存储16个Vertex Buffer Object's可以包含几乎所有你想为顶点存储的数据(位置、颜色、纹理坐标、如果你愿意的话可以给它们命名...)
对于这个加载部分,我使用一个浮点数组(后来是一个 VBO)按排序顺序保存所有数据(有关如何存储数据的更多信息,请参阅 https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices)
在这个例子中,我只会给一个顶点 3 个浮点数作为位置,3 个浮点数作为颜色。您还需要指定一个 Index Buffer Object
float[] data = {
// x, y, z, r, g, b
-1f, 1f, 0f, 1f, 0f, 0f,// Left top , red , ID: 0
-1f, -1f, 0f, 0f, 1f, 0f,// Left bottom, blue , ID: 1
1f, -1f, 0f, 0f, 0f, 1f,// Right bottom, green, ID: 2
1f, 1f, 0f, 1f, 1f, 1f // Right left , white, ID: 3
};
byte[] indices = {
0, 1, 2,// Left bottom triangle
2, 3, 0 // Right top triangle
};
现在您要加载数据,并指定数据的位置。
// You have to use LWJGL3's way of memory management which is off-heap
// more info: https://blog.lwjgl.org/memory-management-in-lwjgl-3/
try(MemoryStack stack = MemoryStack.stackPush()){
FloatBuffer dataBuffer = stack.mallocFloat(data.length);
dataBuffer.put(data);
dataBuffer.flip();
indicesCount = indices.length; // Store for later use ( needed for rendering )
ByteBuffer indicesBuffer = stack.malloc(indicesCount);
indicesBuffer.put(indices);
indicesBuffer.flip();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
// Vectors
int program_in_position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(program_in_position);
glVertexAttribPointer(program_in_position, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), alreadyTakenBytes);
// Colors
int colorAttPos= glGetAttribLocation(program, "color");
glEnableVertexAttribArray(colorAttPos);
glVertexAttribPointer(colorAttPos, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), 3*(Float.SIZE / Byte.SIZE));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Now the Index VBO
indexVBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
现在渲染:
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
(是的,真的已经是了)
开个玩笑,是的,那是一堆代码,学习它,喜欢它。我们甚至没有在着色器中使用任何矩阵,但这真的很简单。每次您想使用 UniformLocation
将矩阵(以 FloatBuffer 的形式)推送到着色器时
// This needs to happen only ONCE ( position stays the same )
int uniModel = glGetUniformLocation(program, "model");
// Create a Matrix
Matrix4f model = Matrix4f.translate(0, 0, -10);
// Create Float Buffer from Matrix4f
FloatBuffer fb = model.toBuffer();
// Push FloatBuffer to Shader
glUniformMatrix4fv(uniModel, false, fb);
唯一的问题是,您需要一个 Matrix4f Class 以及您需要的所有功能...这又是您自己的工作,没有花哨的 OpenGL 调用。不要气馁,那里有几个数学库(示例:https://github.com/SilverTiger/lwjgl3-tutorial/blob/master/src/silvertiger/tutorial/lwjgl/math/Matrix4f.java)
我正在开发一款简单的类似 Minecraft 的游戏,但我曾经使用过一些旧的着色器系统,我想开始使用现代着色器,但我在使用渲染时遇到了困难,屏幕上什么也没有出现...
我尝试过不同的东西:
- glGetError() return 0
- 我试图在片段着色器中 return vec4(1,0,1,1) 但它没有用所以我认为这是顶点着色器中的一个错误...
那么你能帮我弄清楚我的错误在哪里吗?
代码如下:https://pastebin.com/dWJQkFZu
这是我的渲染循环:
public void render(){
//check for resize
if(Display.wasResized()){
glViewport(0, 0, Display.getWidth(), Display.getHeight());
guiManager.recalculate();
}
//create perspective
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLU.gluPerspective(Camera.fov, (float)Display.getWidth()/(float)Display.getHeight(), 0.1f, 1000000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
cam.render();
world.render();
skybox.render(cam.player.position);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
if(Camera.debug){
FontManager.getDefaultFont().drawString(0, 0, "Debug - SaintsCube v-A0.5");
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()+1, "x: "+Math.floor(player.position.x));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*2+2, "y: "+Math.floor(player.position.y));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*3+3, "z: "+Math.floor(player.position.z));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*4+4, "yaw: "+Math.floor(player.rotation.x*-1));
FontManager.getDefaultFont().drawString(0, FontManager.getDefaultFont().getLineHeight()*5+5, "pitch: "+Math.floor(player.rotation.y));
}
guiManager.render();
glDisable(GL_ALPHA_TEST);
}
我的着色器:
chunk.vs:
#version 330
in vec3 position;
in vec2 texcoord;
in vec4 color;
uniform mat4 MVP;
out vec2 pass_texcoord;
out vec4 pass_color;
void main() {
pass_texcoord = texcoord;
pass_color = color;
gl_Position = MVP * vec4(position, 1.0);
}
chunk.fs:
#version 330
out vec4 fragcolor;
uniform sampler2D sampler;
in vec2 pass_texcoord;
in vec4 pass_color;
void main() {
vec4 texturecolor = texture(sampler, pass_texcoord) * pass_color;
if(texturecolor.a <= 0.5){
discard;
}
fragcolor = texturecolor;
}
请帮帮我:)
如果你想开始使用现代着色器方式,你不能使用立即方法。一切都将在着色器中计算(你必须自己编写,没有 opengl 预定义的优点)。所以不是调用
glTranslate3f(x, y, z);
你必须创建你自己的模型矩阵,它被发送到着色器,在那里它被应用到模型顶点的位置。现代 OpenGL 的重点是最小化与它的交互。不是让 CPU 和 GPU 携手工作(GPU 希望 运行 更快,CPU 是瓶颈),而是让 CPU 做一些数学运算,完成后推送一口气传给GPU。
虽然你的顶点着色器已经在期待矩阵,但它没有得到它,因为它在你的 Java 代码中丢失,你从未传递任何矩阵。
统一 mat4 MVP;
大例子:
顶点着色器代码:
#version 330 core
in vec4 position;
in vec4 color;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
out vec4 vertexColor;
void main() {
// Just pass the color down to the fragment shader
vertexColor = color;
// Calculate the Model, View, Projection matrix into one ( in this order, right to left )
mat4 mvp = projection * view * model;
// Calculate the position of the vertex
gl_Position = mvp * vec4(position.xyz,1);
}
片段着色器代码:
#version 330 core
in vec4 vertexColor;
out vec4 fragColor;
void main() {
fragColor = vec4(vertexColor.xyz,1);
}
我没有看到你的着色器编译代码,但我假设它是正确的...(生成着色器 ID,将源代码放入着色器,编译,生成程序并将两个着色器附加到它)
编译后你必须告诉 OpenGL 输出颜色去哪里:
glBindFragDataLocation(program, 0, "fragColor");
加载模型时,您还需要切换到现代 Vertex Buffer A 阵列的。默认一个VBA可以存储16个Vertex Buffer Object's可以包含几乎所有你想为顶点存储的数据(位置、颜色、纹理坐标、如果你愿意的话可以给它们命名...)
对于这个加载部分,我使用一个浮点数组(后来是一个 VBO)按排序顺序保存所有数据(有关如何存储数据的更多信息,请参阅 https://www.khronos.org/opengl/wiki/Vertex_Specification_Best_Practices)
在这个例子中,我只会给一个顶点 3 个浮点数作为位置,3 个浮点数作为颜色。您还需要指定一个 Index Buffer Object
float[] data = {
// x, y, z, r, g, b
-1f, 1f, 0f, 1f, 0f, 0f,// Left top , red , ID: 0
-1f, -1f, 0f, 0f, 1f, 0f,// Left bottom, blue , ID: 1
1f, -1f, 0f, 0f, 0f, 1f,// Right bottom, green, ID: 2
1f, 1f, 0f, 1f, 1f, 1f // Right left , white, ID: 3
};
byte[] indices = {
0, 1, 2,// Left bottom triangle
2, 3, 0 // Right top triangle
};
现在您要加载数据,并指定数据的位置。
// You have to use LWJGL3's way of memory management which is off-heap
// more info: https://blog.lwjgl.org/memory-management-in-lwjgl-3/
try(MemoryStack stack = MemoryStack.stackPush()){
FloatBuffer dataBuffer = stack.mallocFloat(data.length);
dataBuffer.put(data);
dataBuffer.flip();
indicesCount = indices.length; // Store for later use ( needed for rendering )
ByteBuffer indicesBuffer = stack.malloc(indicesCount);
indicesBuffer.put(indices);
indicesBuffer.flip();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
// Vectors
int program_in_position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(program_in_position);
glVertexAttribPointer(program_in_position, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), alreadyTakenBytes);
// Colors
int colorAttPos= glGetAttribLocation(program, "color");
glEnableVertexAttribArray(colorAttPos);
glVertexAttribPointer(colorAttPos, 3, GL_FLOAT, false, 6*(Float.SIZE / Byte.SIZE), 3*(Float.SIZE / Byte.SIZE));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Now the Index VBO
indexVBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
现在渲染:
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
(是的,真的已经是了) 开个玩笑,是的,那是一堆代码,学习它,喜欢它。我们甚至没有在着色器中使用任何矩阵,但这真的很简单。每次您想使用 UniformLocation
将矩阵(以 FloatBuffer 的形式)推送到着色器时// This needs to happen only ONCE ( position stays the same )
int uniModel = glGetUniformLocation(program, "model");
// Create a Matrix
Matrix4f model = Matrix4f.translate(0, 0, -10);
// Create Float Buffer from Matrix4f
FloatBuffer fb = model.toBuffer();
// Push FloatBuffer to Shader
glUniformMatrix4fv(uniModel, false, fb);
唯一的问题是,您需要一个 Matrix4f Class 以及您需要的所有功能...这又是您自己的工作,没有花哨的 OpenGL 调用。不要气馁,那里有几个数学库(示例:https://github.com/SilverTiger/lwjgl3-tutorial/blob/master/src/silvertiger/tutorial/lwjgl/math/Matrix4f.java)