OpenGL 数组纹理根本不渲染
OpenGL array textures not rendering at all
我目前正在努力将一个项目从使用纹理图集转换为数组纹理,但对于我来说,我无法让它工作。
关于我的环境的一些注意事项:
- 我在 GLSL 3.30 版中使用 OpenGL 3.3 核心环境
- 纹理都是 128x128,并且在使用图集时渲染得非常好(除了说服我切换的边缘伪影)
我认为我已经排除的问题:
- 分辨率问题 - 128x128,是 2 的幂,应该没问题
- 纹理加载(它和以前一样完美工作)
- 不完整的纹理(mipmap 问题)- 我已经解决了有关 mipmap 的常见问题,我认为 OpenGL 不应该期待它们
这是我创建数组纹理的代码:
public void createTextureArray() {
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int handle = glGenTextures();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, handle);
glPixelStorei(GL_UNPACK_ROW_LENGTH, Texture.SIZE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, Texture.SIZE, Texture.SIZE, textures.size());
try {
int layer = 0;
for (Texture tex : textures.values()) {
// Next few lines are just for loading the texture. They've been ruled out as the issue.
PNGDecoder decoder = new PNGDecoder(ImageHelper.asInputStream(tex.getImage()));
ByteBuffer buffer = BufferUtils.createByteBuffer(decoder.getWidth() * decoder.getHeight() * 4);
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
buffer.flip();
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, decoder.getWidth(), decoder.getHeight(), 1,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
tex.setLayer(layer);
layer++;
}
} catch (IOException ex) {
ex.printStackTrace();
System.err.println("Failed to create/load texture array");
System.exit(-1);
}
}
创建VAO/VBO的代码:
private static int prepareVbo(int handle, FloatBuffer vbo) {
IntBuffer vaoHandle = BufferUtils.createIntBuffer(1);
glGenVertexArrays(vaoHandle);
glBindVertexArray(vaoHandle.get());
glBindBuffer(GL_ARRAY_BUFFER, handle);
glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, GraphicsMain.TEXTURE_REGISTRY.atlasHandle);
glEnableVertexAttribArray(positionAttrIndex);
glEnableVertexAttribArray(texCoordAttrIndex);
glVertexAttribPointer(positionAttrIndex, 3, GL_FLOAT, false, 24, 0);
glVertexAttribPointer(texCoordAttrIndex, 3, GL_FLOAT, false, 24, 12);
glBindVertexArray(0);
vaoHandle.rewind();
return vaoHandle.get();
}
片段着色器:
#version 330 core
uniform sampler2DArray texArray;
varying vec3 texCoord;
void main() {
gl_FragColor = texture(texArray, texCoord);
}
(texCoord
工作正常;它从顶点着色器正确传递。)
我快没思路了,所以对于现代 OpenGL 还是有些陌生,我想知道我的代码是否有明显的错误。
一些注意事项:
- 你不再需要拥有两个纹理的力量
- 确保每一层的 levels/mipmaps 数量与 wiki says
相同
- 前四个
glTexParameteri
会影响当时 GL_TEXTURE_2D_ARRAY
绑定的内容 ,因此您最好将它们移到 [=12= 之后]
- 如何指定要使用
glGenTextures()
创建多少个纹理?如果您有更具体的方法的可能性,请使用它
GL_UNPACK_ROW_LENGTH
如果大于 0,则定义一行中的像素数。我想 Texture.SIZE
并不是真正的纹理大小,而是一侧的尺寸(在您的情况下为 128)。反正你不需要设置,你可以跳过它
- 仅当您的行长是它的倍数时才将
GL_UNPACK_ALIGNMENT
设置为 4。大多数时候人们在加载纹理之前将其设置为 1 以避免任何麻烦,然后在完成后将其设置回 4
glTexStorage3D
的最后一个参数预计是层数,我希望 textures.size()
更好 returns 而不是大小 (128x128)
glActiveTexture
和 prepareVbo
里面的 glBindTexture
没用,它们不是 vao 的一部分
- 不要在 glsl 中使用
varying
,它已被弃用,改用简单的 in out
- 您可能想从 this sample
中汲取灵感
- 使用采样器,它们给你更多的灵活性
- 如果可用,请使用 Debug Output,否则
glGetError()
,渲染输出可能无法明确地看到一些静默错误
- 你称它为
prepareVbo
但你确实在其中初始化了 vao 和 vbo
我目前正在努力将一个项目从使用纹理图集转换为数组纹理,但对于我来说,我无法让它工作。
关于我的环境的一些注意事项:
- 我在 GLSL 3.30 版中使用 OpenGL 3.3 核心环境
- 纹理都是 128x128,并且在使用图集时渲染得非常好(除了说服我切换的边缘伪影)
我认为我已经排除的问题:
- 分辨率问题 - 128x128,是 2 的幂,应该没问题
- 纹理加载(它和以前一样完美工作)
- 不完整的纹理(mipmap 问题)- 我已经解决了有关 mipmap 的常见问题,我认为 OpenGL 不应该期待它们
这是我创建数组纹理的代码:
public void createTextureArray() {
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int handle = glGenTextures();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, handle);
glPixelStorei(GL_UNPACK_ROW_LENGTH, Texture.SIZE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, Texture.SIZE, Texture.SIZE, textures.size());
try {
int layer = 0;
for (Texture tex : textures.values()) {
// Next few lines are just for loading the texture. They've been ruled out as the issue.
PNGDecoder decoder = new PNGDecoder(ImageHelper.asInputStream(tex.getImage()));
ByteBuffer buffer = BufferUtils.createByteBuffer(decoder.getWidth() * decoder.getHeight() * 4);
decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
buffer.flip();
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, decoder.getWidth(), decoder.getHeight(), 1,
GL_RGBA, GL_UNSIGNED_BYTE, buffer);
tex.setLayer(layer);
layer++;
}
} catch (IOException ex) {
ex.printStackTrace();
System.err.println("Failed to create/load texture array");
System.exit(-1);
}
}
创建VAO/VBO的代码:
private static int prepareVbo(int handle, FloatBuffer vbo) {
IntBuffer vaoHandle = BufferUtils.createIntBuffer(1);
glGenVertexArrays(vaoHandle);
glBindVertexArray(vaoHandle.get());
glBindBuffer(GL_ARRAY_BUFFER, handle);
glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, GraphicsMain.TEXTURE_REGISTRY.atlasHandle);
glEnableVertexAttribArray(positionAttrIndex);
glEnableVertexAttribArray(texCoordAttrIndex);
glVertexAttribPointer(positionAttrIndex, 3, GL_FLOAT, false, 24, 0);
glVertexAttribPointer(texCoordAttrIndex, 3, GL_FLOAT, false, 24, 12);
glBindVertexArray(0);
vaoHandle.rewind();
return vaoHandle.get();
}
片段着色器:
#version 330 core
uniform sampler2DArray texArray;
varying vec3 texCoord;
void main() {
gl_FragColor = texture(texArray, texCoord);
}
(texCoord
工作正常;它从顶点着色器正确传递。)
我快没思路了,所以对于现代 OpenGL 还是有些陌生,我想知道我的代码是否有明显的错误。
一些注意事项:
- 你不再需要拥有两个纹理的力量
- 确保每一层的 levels/mipmaps 数量与 wiki says 相同
- 前四个
glTexParameteri
会影响当时GL_TEXTURE_2D_ARRAY
绑定的内容 ,因此您最好将它们移到 [=12= 之后] - 如何指定要使用
glGenTextures()
创建多少个纹理?如果您有更具体的方法的可能性,请使用它 GL_UNPACK_ROW_LENGTH
如果大于 0,则定义一行中的像素数。我想Texture.SIZE
并不是真正的纹理大小,而是一侧的尺寸(在您的情况下为 128)。反正你不需要设置,你可以跳过它- 仅当您的行长是它的倍数时才将
GL_UNPACK_ALIGNMENT
设置为 4。大多数时候人们在加载纹理之前将其设置为 1 以避免任何麻烦,然后在完成后将其设置回 4 glTexStorage3D
的最后一个参数预计是层数,我希望textures.size()
更好 returns 而不是大小 (128x128)glActiveTexture
和prepareVbo
里面的glBindTexture
没用,它们不是 vao 的一部分
- 不要在 glsl 中使用
varying
,它已被弃用,改用简单的in out
- 您可能想从 this sample 中汲取灵感
- 使用采样器,它们给你更多的灵活性
- 如果可用,请使用 Debug Output,否则
glGetError()
,渲染输出可能无法明确地看到一些静默错误 - 你称它为
prepareVbo
但你确实在其中初始化了 vao 和 vbo