(LWJGL3) 使用 glTexSubImage3D 上传图像数据后,OpenGL 2D 纹理数组保持为空
(LWJGL3) OpenGL 2D Texture Array stays empty after uploading image data with glTexSubImage3D
所以我目前正在尝试用 2D 纹理阵列替换我的旧纹理图集拼接器,以便稍后通过各向异性过滤和贪婪网格化使生活更简单。
我正在使用 stb 加载 png 文件,我知道缓冲区已正确填充,因为如果我在上传之前导出即将成为地图集的每一层,它就是正确的 png 文件。
我的设置是这样的:
我正在用 stb 加载我的 jar 文件中的每个纹理,并用它创建一个对象,在其中存储宽度、高度、图层和像素数据。
加载每个纹理时,我会寻找最大的纹理并将每个较小的纹理缩放到与最大的纹理相同的大小,因为我知道 2D 纹理阵列只有在每一层都具有相同大小的情况下才有效。
然后我像这样初始化二维纹理数组:
public void init(int layerCount, boolean supportsAlpha, int textureSize) {
this.textureId = glGenTextures();
this.maxLayer = layerCount;
int internalFormat = supportsAlpha ? GL_RGBA8 : GL_RGB8;
this.format = supportsAlpha ? GL_RGBA : GL_RGB;
glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, textureSize, textureSize, layerCount, 0, this.format, GL_UNSIGNED_BYTE, 0);
}
之后,我浏览我的 textureLayer 对象地图并像这样上传它们中的每一个:
public void upload(ITextureLayer textureLayer) {
if (textureLayer.getLayer() >= this.maxLayer) {
LOGGER.error("Tried uploading a texture with a too big layer.");
return;
} else if (this.textureId == 0) {
LOGGER.error("Tried uploading texture layer to uninitialized texture array.");
return;
}
glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);
// Tell openGL how to unpack the RGBA bytes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Tell openGL to not blur the texture when it is stretched
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Upload the texture data
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(), textureLayer.getWidth(), textureLayer.getHeight(), 0, this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());
int errorCode = glGetError();
if (errorCode != 0) LOGGER.error("Error while uploading texture layer {} to graphics card. {}", textureLayer.getLayer(), GLHelper.errorToString(errorCode));
}
我的每一层的错误代码都是 0,所以我认为一切顺利。但是当我使用 RenderDoc 调试游戏时,我可以看到在每一层上每一位都是 0,因此它只是一个具有正确宽度和高度的透明纹理。
我不知道我做错了什么,因为 openGL 告诉我一切顺利。对我来说重要的是我只使用 openGL 3.3 和更低版本,因为我希望游戏也能在旧电脑上玩,所以用 glTexStorage3D
预分配内存不是一个选项。
glTexSubImage3D
的第8个参数应该是1(depth
)。
注意,层的大小为textureLayer.getWidth()
、textureLayer.getHeight()
、1
:
glTexSubImage3D(
GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(),
textureLayer.getWidth(), textureLayer.getHeight(), 1, // depth is 1
this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());
将 0 的 width
、height
或 depth
传递给 glTexSubImage3D
不是错误,但不会对纹理产生任何影响对象数据存储。
所以我目前正在尝试用 2D 纹理阵列替换我的旧纹理图集拼接器,以便稍后通过各向异性过滤和贪婪网格化使生活更简单。
我正在使用 stb 加载 png 文件,我知道缓冲区已正确填充,因为如果我在上传之前导出即将成为地图集的每一层,它就是正确的 png 文件。
我的设置是这样的:
我正在用 stb 加载我的 jar 文件中的每个纹理,并用它创建一个对象,在其中存储宽度、高度、图层和像素数据。
加载每个纹理时,我会寻找最大的纹理并将每个较小的纹理缩放到与最大的纹理相同的大小,因为我知道 2D 纹理阵列只有在每一层都具有相同大小的情况下才有效。
然后我像这样初始化二维纹理数组:
public void init(int layerCount, boolean supportsAlpha, int textureSize) {
this.textureId = glGenTextures();
this.maxLayer = layerCount;
int internalFormat = supportsAlpha ? GL_RGBA8 : GL_RGB8;
this.format = supportsAlpha ? GL_RGBA : GL_RGB;
glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalFormat, textureSize, textureSize, layerCount, 0, this.format, GL_UNSIGNED_BYTE, 0);
}
之后,我浏览我的 textureLayer 对象地图并像这样上传它们中的每一个:
public void upload(ITextureLayer textureLayer) {
if (textureLayer.getLayer() >= this.maxLayer) {
LOGGER.error("Tried uploading a texture with a too big layer.");
return;
} else if (this.textureId == 0) {
LOGGER.error("Tried uploading texture layer to uninitialized texture array.");
return;
}
glBindTexture(GL_TEXTURE_2D_ARRAY, this.textureId);
// Tell openGL how to unpack the RGBA bytes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Tell openGL to not blur the texture when it is stretched
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// Upload the texture data
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(), textureLayer.getWidth(), textureLayer.getHeight(), 0, this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());
int errorCode = glGetError();
if (errorCode != 0) LOGGER.error("Error while uploading texture layer {} to graphics card. {}", textureLayer.getLayer(), GLHelper.errorToString(errorCode));
}
我的每一层的错误代码都是 0,所以我认为一切顺利。但是当我使用 RenderDoc 调试游戏时,我可以看到在每一层上每一位都是 0,因此它只是一个具有正确宽度和高度的透明纹理。
我不知道我做错了什么,因为 openGL 告诉我一切顺利。对我来说重要的是我只使用 openGL 3.3 和更低版本,因为我希望游戏也能在旧电脑上玩,所以用 glTexStorage3D
预分配内存不是一个选项。
glTexSubImage3D
的第8个参数应该是1(depth
)。
注意,层的大小为textureLayer.getWidth()
、textureLayer.getHeight()
、1
:
glTexSubImage3D(
GL_TEXTURE_2D_ARRAY, 0, 0, 0, textureLayer.getLayer(),
textureLayer.getWidth(), textureLayer.getHeight(), 1, // depth is 1
this.format, GL_UNSIGNED_BYTE, textureLayer.getPixels());
将 0 的 width
、height
或 depth
传递给 glTexSubImage3D
不是错误,但不会对纹理产生任何影响对象数据存储。