我尝试渲染一个三角形,看看LWJGL是如何工作的。每一帧,我重置顶点数据ByteBuffer
,并直接向其中写入3个顶点。然后我调用buffer.flip()
,准备将数据上传到GPU,并调用glBufferData(...)
,最后调用glDrawArrays(...)
。但是没有三角形显示。使用调试程序RenderDoc,我可以查看应该上传的顶点数据,它看起来肯定不正确。
正如您所看到的,每个位置都非常小(就像.
后面的41个零)。我没有看到任何错误,即使设置了GLFW错误回调和调试上下文。
所有Java代码:
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GLUtil;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class MinimalExample {
private static void debugPrintErrors() {
System.out.println("-> DEBUG PRINT ERRORS");
int error;
while ((error = GL30.glGetError()) != GL30.GL_NO_ERROR) {
StringBuilder b = new StringBuilder(" ");
switch (error) {
case GL30.GL_INVALID_ENUM -> b.append("INVALID_ENUM");
case GL30.GL_INVALID_VALUE -> b.append("INVALID_VALUE");
case GL30.GL_INVALID_OPERATION -> b.append("INVALID_OP");
case GL30.GL_INVALID_FRAMEBUFFER_OPERATION -> b.append("INVALID_FB_OP");
}
System.out.println(b);
}
}
private static String readResource(String res) {
try {
InputStream is = MinimalExample.class.getResourceAsStream(res);
String s = new String(is.readAllBytes(), StandardCharsets.UTF_8);
is.close();
return s;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
// vertex data buffer
private static final ByteBuffer buf = ByteBuffer.allocateDirect(4096);
// shader program
static int program;
// render objects
static int vao;
static int vbo;
public static void main(String[] args) {
// set buffer limit
buf.limit(4096).position(0);
// init glfw and create window
GLFW.glfwInit();
long window = GLFW.glfwCreateWindow(500, 500, "Hello", 0, 0);
// create GL
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
GLUtil.setupDebugMessageCallback(System.out);
GLFW.glfwSetErrorCallback(GLFWErrorCallback.createPrint(System.out));
// create vertex objects
vao = GL30.glGenVertexArrays();
vbo = GL30.glGenBuffers();
GL30.glBindVertexArray(vao);
GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, vbo);
GL30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 7 * 4, 0);
GL30.glVertexAttribPointer(1, 4, GL30.GL_FLOAT, false, 7 * 4, 7 * 3);
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
// compile and link shaders
int vertexShader = GL30.glCreateShader(GL30.GL_VERTEX_SHADER);
int fragmentShader = GL30.glCreateShader(GL30.GL_FRAGMENT_SHADER);
GL30.glShaderSource(vertexShader, readResource("/test.vsh"));
GL30.glShaderSource(fragmentShader, readResource("/test.fsh"));
GL30.glCompileShader(vertexShader);
GL30.glCompileShader(fragmentShader);
program = GL30.glCreateProgram();
GL30.glAttachShader(program, vertexShader);
GL30.glAttachShader(program, fragmentShader);
GL30.glLinkProgram(program);
// render loop
while (!GLFW.glfwWindowShouldClose(window)) {
// poll events
GLFW.glfwPollEvents();
// clear screen
GL30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL30.glClear(GL30.GL_COLOR_BUFFER_BIT);
// render
render();
// swap buffers
GLFW.glfwSwapBuffers(window);
}
}
static void render() {
// put vertex data
// manual to simulate graphics library
putVec3(0.25f, 0.25f, 1f); putVec4(1.0f, 0.0f, 0.0f, 1.0f);
putVec3(0.75f, 0.25f, 1f); putVec4(0.0f, 1.0f, 0.0f, 1.0f);
putVec3(0.50f, 0.75f, 1f); putVec4(0.0f, 0.0f, 1.0f, 1.0f);
buf.flip();
// bind program
GL30.glUseProgram(program);
// bind vertex array
GL30.glBindVertexArray(vao);
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
// upload graphics data and draw
GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, vbo);
GL30.glBufferData(GL30.GL_ARRAY_BUFFER, buf, GL30.GL_STATIC_DRAW);
GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, 3);
// reset vertex data buffer
buf.position(0);
buf.limit(buf.capacity());
}
//////////////////////////////////////////
static void putVec3(float x, float y, float z) {
buf.putFloat(x);
buf.putFloat(y);
buf.putFloat(z);
}
static void putVec4(float x, float y, float z, float w) {
buf.putFloat(x);
buf.putFloat(y);
buf.putFloat(z);
buf.putFloat(w);
}
}
所有着色器代码(为方便起见合并为一个块,实际上是两个文件):
/*
test.vsh
*/
#version 330 core
in layout(location = 0) vec3 position;
in layout(location = 1) vec4 col;
out layout(location = 0) vec4 fColor;
void main() {
gl_Position = vec4(position * 1000, 1);
fColor = col;
}
/*
test.fsh
*/
#version 330 core
in layout(location = 0) vec4 fColor;
out vec4 outColor;
void main() {
outColor = fColor;
}
**编辑:**我知道ByteBuffer
的内容是正确的,检查每一帧会产生:
[ 0.25, 0.25, 1.0, 1.0, 0.0, 0.0, 1.0, 0.75, 0.25, 1.0, 0.0, 1.0, 0.0, 1.0, 0.5, 0.75, 1.0, 0.0, 0.0, 1.0, 1.0, ]
1条答案
按热度按时间rqcrx0a61#
有3个问题。
第一个问题是
buf
。ByteBuffer::allocateDirect
分配了一个BIG_ENDIAN缓冲区,但OpenGL是一个C库,它是LITTLE_ENDIAN。因此它必须分配BufferUtils::createByteBuffer
或MemoryUtil::memAlloc
。第二个问题是
glVertexAttribPointer
的偏移量。对于3个浮点数,它应该是4 * 3
。第三个问题是你的顶点着色器。输入位置被乘以1000,这是在视口之外。为了避免这个问题,你只需要删除乘法或使用投影矩阵。
顺便说一句,我建议使用
ByteBuffer::clear
来重置顶点数据缓冲区,因为它是一个内置的方法。修复的Java代码: