LWJGL:无法使用 nvidia gpu 绘制纹理
LWJGL: Unable to draw textures using nvidia gpu
所以我们正在 Java 中使用 LWJGL 与 GLFW 和 OpenGL 3.3 开发一个简单的游戏。
在 AMD 和 Intel 上运行良好,但在 Nvidia 上运行不佳。屏幕只是黑色(来自 glClearColor 的值),既没有 Java-exceptions 也没有 OpenGL-Errors.
我们做错了什么?
Main.java:
public class Main {
Shader defaultShader;
boolean running = false;
long window;
int width = 1000;
int height = 1000;
String title = "pain";
int vao;
public static void main(String[] args){
var pain = new Pain();
pain.init();
pain.run();
}
public void init() throws RuntimeException {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new RuntimeException("glfw.init.failed");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
this.window = glfwCreateWindow(this.width, this.height, this.title, 0, 0);
if (window == NULL) throw new RuntimeException("glfw.window.failed");
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
GL.createCapabilities();
glEnable(GL_TEXTURE_2D);
this.vao = glGenVertexArrays();
glBindVertexArray(vao);
this.defaultShader = new Shader("main");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void run() {
this.running = true;
glfwShowWindow(window);
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer data = null;
try {
data = stbi_load_from_memory(BufferCreator.createByteBuffer(FileHandler.readFileAsBytes("fuckoff/" + "heal_powerup.png")), width, height, comp, 4);
} catch (IOException ignored) {}
if (data == null) throw new RuntimeException("texture.load.failed");
int id = glGenTextures();
int twidth = width.get();
int theight = height.get();
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
int vid;
int tid;
int dc;
int arg4;
int[] indices = {0, 1, 2, 2, 3, 0};
dc = indices.length;
vid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
100.0f, 0.0f,
100.0f, 100.0f,
0.0f, 100.0f
}), GL_DYNAMIC_DRAW);
arg4 = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferCreator.createIntBuffer(indices), GL_STATIC_DRAW);
tid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, tid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
}), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
while(this.running) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
defaultShader.bind();
glBindTexture(GL_TEXTURE_2D, id);
this.defaultShader.setUniform("sampler", 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vid);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, tid);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glDrawElements(GL_TRIANGLES, dc, GL_UNSIGNED_INT, 0);
//Unbind buffers
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Disable
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
if (glfwWindowShouldClose(window)) shutdown();
System.out.println(glGetError());
}
glfwFreeCallbacks(this.window);
glfwDestroyWindow(this.window);
glfwTerminate();
glfwSetErrorCallback(null).free();
}
void shutdown(){
this.running = false;
}
}
Shader.java:
public class Shader {
private int program, vs, fs;
public Shader(String name) {
try {
this.program = glCreateProgram();
this.vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this.vs, FileHandler.readFile("shaders/" + name + ".vs"));
glCompileShader(this.vs);
if (glGetShaderi(this.vs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed\n" + glGetShaderInfoLog(vs));
this.fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this.fs, FileHandler.readFile("shaders/" + name + ".fs"));
glCompileShader(this.fs);
if (glGetShaderi(this.fs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed" + glGetShaderInfoLog(fs));
glAttachShader(this.program, this.vs);
glAttachShader(this.program, this.fs);
glBindAttribLocation(this.program, 0, "vertices");
glBindAttribLocation(this.program, 1, "textures");
glLinkProgram(this.program);
if (glGetProgrami(this.program, GL_LINK_STATUS) != 1) throw new RuntimeException("shader.link.failed");
glValidateProgram(this.program);
if (glGetProgrami(this.program, GL_VALIDATE_STATUS) != 1) throw new RuntimeException("shader.validation.failed");
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != 1) {
glUniform2f(location, 1000, 1000);
}
}
public void setUniform(String name, int value) {
int location = glGetUniformLocation(this.program, name);
if (location != -1) {
glUniform1i(location, value);
}
}
public void bind() {
glUseProgram(this.program);
this.updateShaderParameters();
}
}
顶点着色器:
#version 330 core
layout (location = 0) in vec2 vertices;
layout (location = 1) in vec2 textures;
uniform vec2 windowSize;
out vec2 tex_coords;
void main() {
tex_coords = textures;
gl_Position = vec4(2.0/windowSize.x * vertices.x - 1.0, (2.0/windowSize.y * vertices.y - 1.0) * -1.0, 1, 1);
}
片段着色器:
#version 330 core
uniform sampler2D sampler;
out vec4 FragColor;
in vec2 tex_coords;
void main() {
if (texture(sampler, tex_coords).a != 1.0f) {
discard;
}
FragColor = texture(sampler, tex_coords);
}
BufferCreator.java 和 FileHandler.java 是简单的实用程序-类 似乎工作得很好。
我假设,它与采样器有关,因为当我删除片段着色器中的 if...discard 语句并将 FragColor 设置为一些随机值时,它被绘制了。
在您的 updateShaderParameters() 方法中,您检查 !=1
它应该是 !=-1
,因为 windowSize 位置将为 1。
如果您检查 1,它将永远不会被设置.
最后这可能是疏忽或错误输入。发生在我们最好的人身上。
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != -1) {
glUniform2f(location, 1000, 1000);
}
}
所以我们正在 Java 中使用 LWJGL 与 GLFW 和 OpenGL 3.3 开发一个简单的游戏。
在 AMD 和 Intel 上运行良好,但在 Nvidia 上运行不佳。屏幕只是黑色(来自 glClearColor 的值),既没有 Java-exceptions 也没有 OpenGL-Errors.
我们做错了什么?
Main.java:
public class Main {
Shader defaultShader;
boolean running = false;
long window;
int width = 1000;
int height = 1000;
String title = "pain";
int vao;
public static void main(String[] args){
var pain = new Pain();
pain.init();
pain.run();
}
public void init() throws RuntimeException {
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) throw new RuntimeException("glfw.init.failed");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
this.window = glfwCreateWindow(this.width, this.height, this.title, 0, 0);
if (window == NULL) throw new RuntimeException("glfw.window.failed");
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
GL.createCapabilities();
glEnable(GL_TEXTURE_2D);
this.vao = glGenVertexArrays();
glBindVertexArray(vao);
this.defaultShader = new Shader("main");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
public void run() {
this.running = true;
glfwShowWindow(window);
IntBuffer width = BufferUtils.createIntBuffer(1);
IntBuffer height = BufferUtils.createIntBuffer(1);
IntBuffer comp = BufferUtils.createIntBuffer(1);
ByteBuffer data = null;
try {
data = stbi_load_from_memory(BufferCreator.createByteBuffer(FileHandler.readFileAsBytes("fuckoff/" + "heal_powerup.png")), width, height, comp, 4);
} catch (IOException ignored) {}
if (data == null) throw new RuntimeException("texture.load.failed");
int id = glGenTextures();
int twidth = width.get();
int theight = height.get();
glBindTexture(GL_TEXTURE_2D, id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
int vid;
int tid;
int dc;
int arg4;
int[] indices = {0, 1, 2, 2, 3, 0};
dc = indices.length;
vid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
100.0f, 0.0f,
100.0f, 100.0f,
0.0f, 100.0f
}), GL_DYNAMIC_DRAW);
arg4 = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, BufferCreator.createIntBuffer(indices), GL_STATIC_DRAW);
tid = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, tid);
glBufferData(GL_ARRAY_BUFFER, BufferCreator.createFloatBuffer(new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
}), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
while(this.running) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
defaultShader.bind();
glBindTexture(GL_TEXTURE_2D, id);
this.defaultShader.setUniform("sampler", 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vid);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, tid);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arg4);
glDrawElements(GL_TRIANGLES, dc, GL_UNSIGNED_INT, 0);
//Unbind buffers
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Disable
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
if (glfwWindowShouldClose(window)) shutdown();
System.out.println(glGetError());
}
glfwFreeCallbacks(this.window);
glfwDestroyWindow(this.window);
glfwTerminate();
glfwSetErrorCallback(null).free();
}
void shutdown(){
this.running = false;
}
}
Shader.java:
public class Shader {
private int program, vs, fs;
public Shader(String name) {
try {
this.program = glCreateProgram();
this.vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(this.vs, FileHandler.readFile("shaders/" + name + ".vs"));
glCompileShader(this.vs);
if (glGetShaderi(this.vs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed\n" + glGetShaderInfoLog(vs));
this.fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(this.fs, FileHandler.readFile("shaders/" + name + ".fs"));
glCompileShader(this.fs);
if (glGetShaderi(this.fs, GL_COMPILE_STATUS) != 1) throw new RuntimeException("shader.compile.failed" + glGetShaderInfoLog(fs));
glAttachShader(this.program, this.vs);
glAttachShader(this.program, this.fs);
glBindAttribLocation(this.program, 0, "vertices");
glBindAttribLocation(this.program, 1, "textures");
glLinkProgram(this.program);
if (glGetProgrami(this.program, GL_LINK_STATUS) != 1) throw new RuntimeException("shader.link.failed");
glValidateProgram(this.program);
if (glGetProgrami(this.program, GL_VALIDATE_STATUS) != 1) throw new RuntimeException("shader.validation.failed");
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != 1) {
glUniform2f(location, 1000, 1000);
}
}
public void setUniform(String name, int value) {
int location = glGetUniformLocation(this.program, name);
if (location != -1) {
glUniform1i(location, value);
}
}
public void bind() {
glUseProgram(this.program);
this.updateShaderParameters();
}
}
顶点着色器:
#version 330 core
layout (location = 0) in vec2 vertices;
layout (location = 1) in vec2 textures;
uniform vec2 windowSize;
out vec2 tex_coords;
void main() {
tex_coords = textures;
gl_Position = vec4(2.0/windowSize.x * vertices.x - 1.0, (2.0/windowSize.y * vertices.y - 1.0) * -1.0, 1, 1);
}
片段着色器:
#version 330 core
uniform sampler2D sampler;
out vec4 FragColor;
in vec2 tex_coords;
void main() {
if (texture(sampler, tex_coords).a != 1.0f) {
discard;
}
FragColor = texture(sampler, tex_coords);
}
BufferCreator.java 和 FileHandler.java 是简单的实用程序-类 似乎工作得很好。
我假设,它与采样器有关,因为当我删除片段着色器中的 if...discard 语句并将 FragColor 设置为一些随机值时,它被绘制了。
在您的 updateShaderParameters() 方法中,您检查 !=1
它应该是 !=-1
,因为 windowSize 位置将为 1。
如果您检查 1,它将永远不会被设置.
最后这可能是疏忽或错误输入。发生在我们最好的人身上。
public void updateShaderParameters() {
this.setUniform("sampler", 0);
int location = glGetUniformLocation(this.program, "windowSize");
if (location != -1) {
glUniform2f(location, 1000, 1000);
}
}