为什么我在 OpenGL (3) 中的三角形不使用 lwjgl 渲染?
Why does my triangle in OpenGL (3) doesn't render using lwjgl?
所以我最近开始学习 lwjgl,并很快意识到我需要在 OpenGL 方面进行改进才能继续。我按照教程 here 并尝试使用 java 和 lwjgl 实现相同的代码(教程中的代码使用 C++)。我成功地使用 lwjgl api 从教程中复制了 OpenGL 调用,但是当我启动我的程序时,我只看到黑屏,没有其他任何东西 =( 没有三角形,什么都没有。控制台以太没有错误。
我的 Window.java class 我在其中执行 OpenGL 渲染(没关系 Spring 注释,我只是使用 IoC 容器来管理对象,方法 run()
在 Spring 上下文创建之后被调用):
import com.gitlab.cvazer.dnd.map.desktop.ashlesy.Orchestrator;
import com.gitlab.cvazer.dnd.map.desktop.render.Camera;
import com.gitlab.cvazer.dnd.map.desktop.util.Shaders;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Objects;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.NULL;
@Slf4j
@Component
public class Window {
private @Autowired Shaders shaders;
private @Getter long window;
//START HERE!
public void run() {
new Thread(() -> {
log.info("Hello LWJGL " + Version.getVersion() + "!");
init();
try {
loop();
} catch (IOException e) {
e.printStackTrace();
}
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
Objects.requireNonNull(glfwSetErrorCallback(null)).free();
}).start();
}
private void init() {
GLFWErrorCallback.createPrint(System.err).set();
if ( !glfwInit() ) throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_SAMPLES, 8);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(800, 600, "Hello World!", NULL, NULL);
if ( window == NULL ) throw new RuntimeException("Failed to create the GLFW window");
callbacks();
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() throws IOException {
GL.createCapabilities();
int vertexArray = glGenVertexArrays();
glBindVertexArray(vertexArray);
int vertexBuffer = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
float[] data = {-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f};
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
int program = shaders.loadShaders("vertex.glsl", "fragment.glsl");
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
long lastTime = System.currentTimeMillis();
while ( !glfwWindowShouldClose(window) ) {
long delta = System.currentTimeMillis() - lastTime;
lastTime = System.currentTimeMillis();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0,3,GL_FLOAT, false, 0, vertexBuffer);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window); // swap the color buffers
glfwPollEvents();
}
}
}
Shaders.java class:
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.lwjgl.opengl.GL30.*;
@Slf4j
@Service
public class Shaders {
public int loadShaders(String vertexFilePath, String fragmentFilePath) throws IOException {
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
String vertexCode = Files.lines(Paths.get(vertexFilePath))
.collect(Collectors.joining("\n"));
String fragmentCode = Files.lines(Paths.get(fragmentFilePath))
.collect(Collectors.joining("\n"));
compileShader(vertexShader, vertexCode);
compileShader(fragmentShader, fragmentCode);
int program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
private void compileShader(int shader, String code){
glShaderSource(shader, code);
glCompileShader(shader);
String slog = glGetShaderInfoLog(shader);
if (slog.contentEquals("")) return;
log.info(slog);
}
}
vertex.glsl 文件:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
fragment.glsl 文件:
#version 330 core
out vec3 color;
void main(){
color = vec3(1,0,0);
}
我遵循了本教程的第 1 部分(编码 OpenGL 调用)和第 2 部分(编码 GLSL 着色器,加载它们),但是添加着色器并没有解决我的问题
我不认为进一步谷歌搜索可以给我答案,因为几乎所有关于 lwjgl 主题的在线教程都使用 OpenGL 1 进行渲染。
我怎样才能让它工作?
问题是行
glVertexAttribPointer(0,3,GL_FLOAT, false, 0, vertexBuffer);
如果绑定了命名缓冲区对象,则 glVertexAttribPointer
的最后一个参数将被视为缓冲区对象数据存储中的字节偏移量。
当您使用 glVertexAttribPointer
时,您不必通过参数指定顶点缓冲区。该函数将顶点属性关联到缓冲区对象,该对象当前绑定到目标 GL_ARRAY_BUFFER
.
必须是:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
另见 Java Code Examples for org.lwjgl.opengl.GL20.glVertexAttribPointer()
所以我最近开始学习 lwjgl,并很快意识到我需要在 OpenGL 方面进行改进才能继续。我按照教程 here 并尝试使用 java 和 lwjgl 实现相同的代码(教程中的代码使用 C++)。我成功地使用 lwjgl api 从教程中复制了 OpenGL 调用,但是当我启动我的程序时,我只看到黑屏,没有其他任何东西 =( 没有三角形,什么都没有。控制台以太没有错误。
我的 Window.java class 我在其中执行 OpenGL 渲染(没关系 Spring 注释,我只是使用 IoC 容器来管理对象,方法 run()
在 Spring 上下文创建之后被调用):
import com.gitlab.cvazer.dnd.map.desktop.ashlesy.Orchestrator;
import com.gitlab.cvazer.dnd.map.desktop.render.Camera;
import com.gitlab.cvazer.dnd.map.desktop.util.Shaders;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Objects;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.system.MemoryUtil.NULL;
@Slf4j
@Component
public class Window {
private @Autowired Shaders shaders;
private @Getter long window;
//START HERE!
public void run() {
new Thread(() -> {
log.info("Hello LWJGL " + Version.getVersion() + "!");
init();
try {
loop();
} catch (IOException e) {
e.printStackTrace();
}
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
glfwTerminate();
Objects.requireNonNull(glfwSetErrorCallback(null)).free();
}).start();
}
private void init() {
GLFWErrorCallback.createPrint(System.err).set();
if ( !glfwInit() ) throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_SAMPLES, 8);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(800, 600, "Hello World!", NULL, NULL);
if ( window == NULL ) throw new RuntimeException("Failed to create the GLFW window");
callbacks();
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() throws IOException {
GL.createCapabilities();
int vertexArray = glGenVertexArrays();
glBindVertexArray(vertexArray);
int vertexBuffer = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
float[] data = {-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f};
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW);
int program = shaders.loadShaders("vertex.glsl", "fragment.glsl");
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
long lastTime = System.currentTimeMillis();
while ( !glfwWindowShouldClose(window) ) {
long delta = System.currentTimeMillis() - lastTime;
lastTime = System.currentTimeMillis();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0,3,GL_FLOAT, false, 0, vertexBuffer);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(window); // swap the color buffers
glfwPollEvents();
}
}
}
Shaders.java class:
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.lwjgl.opengl.GL30.*;
@Slf4j
@Service
public class Shaders {
public int loadShaders(String vertexFilePath, String fragmentFilePath) throws IOException {
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
String vertexCode = Files.lines(Paths.get(vertexFilePath))
.collect(Collectors.joining("\n"));
String fragmentCode = Files.lines(Paths.get(fragmentFilePath))
.collect(Collectors.joining("\n"));
compileShader(vertexShader, vertexCode);
compileShader(fragmentShader, fragmentCode);
int program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
private void compileShader(int shader, String code){
glShaderSource(shader, code);
glCompileShader(shader);
String slog = glGetShaderInfoLog(shader);
if (slog.contentEquals("")) return;
log.info(slog);
}
}
vertex.glsl 文件:
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
fragment.glsl 文件:
#version 330 core
out vec3 color;
void main(){
color = vec3(1,0,0);
}
我遵循了本教程的第 1 部分(编码 OpenGL 调用)和第 2 部分(编码 GLSL 着色器,加载它们),但是添加着色器并没有解决我的问题
我不认为进一步谷歌搜索可以给我答案,因为几乎所有关于 lwjgl 主题的在线教程都使用 OpenGL 1 进行渲染。
我怎样才能让它工作?
问题是行
glVertexAttribPointer(0,3,GL_FLOAT, false, 0, vertexBuffer);
如果绑定了命名缓冲区对象,则 glVertexAttribPointer
的最后一个参数将被视为缓冲区对象数据存储中的字节偏移量。
当您使用 glVertexAttribPointer
时,您不必通过参数指定顶点缓冲区。该函数将顶点属性关联到缓冲区对象,该对象当前绑定到目标 GL_ARRAY_BUFFER
.
必须是:
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
另见 Java Code Examples for org.lwjgl.opengl.GL20.glVertexAttribPointer()