OpenTK 从 dds 纹理手动上传 mipmap 不起作用
OpenTK manual upload of mipmaps from dds texture doesn't work
我有一些 dds 纹理将完全生成 mipmaps(通常是 10 个级别)。据了解,我刚刚加载了第一个基础级别,并且我正在使用 GL.GenerateMipmap(GenerateMipmapTarget.Texture2D)
生成 mipmap,效果非常好。
因为我已经保存了 mipmap 数据,所以我想将它们手动加载到其余级别,而不是调用 - 非常昂贵的 - 回调。
这是对应的代码
//Upload to GPU
bufferID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, bufferID);
//Temp Variables
int w = width;
int h = height;
int mm_count = ddsImage.header.dwMipMapCount;
int temp_size = ddsImage.header.dwPitchOrLinearSize;
int offset = 0;
for (int i=0; i < ddsImage.header.dwMipMapCount; i++)
{
if (w == 0 || h == 0)
continue;
byte[] tex_data = new byte[temp_size];
Array.Copy(ddsImage.bdata, offset, tex_data, 0, temp_size);
GL.CompressedTexImage2D(TextureTarget.Texture2D, i, this.pif, w, h, 0, temp_size, tex_data);
//Console.WriteLine(GL.GetError());
offset += temp_size;
temp_size /= 4;
w = w >> 1;
h = h >> 1;
}
Console.WriteLine(GL.GetError());
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureLodBias, -0.2f);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear);
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); //Generate Mipmaps from the base level
//Console.WriteLine(GL.GetError());
int max_level = 0;
GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMaxLevel, out max_level);
int base_level = 0;
GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureBaseLevel, out base_level);
int maxsize = Math.Max(height, width);
int p = (int) Math.Floor(Math.Log(maxsize, 2)) + base_level;
int q = Math.Min(p, max_level);
#if(DEBUG)
//Get all mipmaps
temp_size = ddsImage.header.dwPitchOrLinearSize;
for (int i = 0; i < q; i++)
{
//Get lowest calculated mipmap
byte[] pixels = new byte[temp_size];
//Save to disk
GL.GetCompressedTexImage(TextureTarget.Texture2D, i, pixels);
File.WriteAllBytes("Temp\level" + i.ToString(), pixels);
temp_size = Math.Max(temp_size / 4, 16);
}
#endif
ddsImage = null;
ddsImage
是一个保存dds图像信息和所有像素数据的对象
这些纹理呈现为完全黑色。如果我取消注释 mipmap generation 的行,一切都会像魅力一样工作。此外,当我转储 mipmap 级别数据时,它们没有损坏。我有一种感觉,我需要以某种方式告诉 opengl 我定义了多少个 mipmap,但这里的大问题是为什么即使是基本级别也不起作用。至少这个应该有用。
好吧,根据 https://www.khronos.org/opengl/wiki/Common_Mistakes#Legacy_Generation
,事实证明我创建的纹理确实可能不完整
我按照这些步骤操作,发现我需要在上传纹理数据之前设置 MAX_LEVEL 和 BASE_LEVEL 参数,这种方式非常有效。
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 8);
最大级别的值应该是 mips - 1
。但出于某种原因,当我尝试使用图像的所有 mipmap 时,纹理再次变黑。我还没有彻底测试它,但我认为我应该完全忽略 2x2 和 1x1 mipmap 的上传。如果我对此进行测试,我会更新答案。
我有一些 dds 纹理将完全生成 mipmaps(通常是 10 个级别)。据了解,我刚刚加载了第一个基础级别,并且我正在使用 GL.GenerateMipmap(GenerateMipmapTarget.Texture2D)
生成 mipmap,效果非常好。
因为我已经保存了 mipmap 数据,所以我想将它们手动加载到其余级别,而不是调用 - 非常昂贵的 - 回调。
这是对应的代码
//Upload to GPU
bufferID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, bufferID);
//Temp Variables
int w = width;
int h = height;
int mm_count = ddsImage.header.dwMipMapCount;
int temp_size = ddsImage.header.dwPitchOrLinearSize;
int offset = 0;
for (int i=0; i < ddsImage.header.dwMipMapCount; i++)
{
if (w == 0 || h == 0)
continue;
byte[] tex_data = new byte[temp_size];
Array.Copy(ddsImage.bdata, offset, tex_data, 0, temp_size);
GL.CompressedTexImage2D(TextureTarget.Texture2D, i, this.pif, w, h, 0, temp_size, tex_data);
//Console.WriteLine(GL.GetError());
offset += temp_size;
temp_size /= 4;
w = w >> 1;
h = h >> 1;
}
Console.WriteLine(GL.GetError());
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureLodBias, -0.2f);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear);
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); //Generate Mipmaps from the base level
//Console.WriteLine(GL.GetError());
int max_level = 0;
GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureMaxLevel, out max_level);
int base_level = 0;
GL.GetTexParameter(TextureTarget.Texture2D, GetTextureParameter.TextureBaseLevel, out base_level);
int maxsize = Math.Max(height, width);
int p = (int) Math.Floor(Math.Log(maxsize, 2)) + base_level;
int q = Math.Min(p, max_level);
#if(DEBUG)
//Get all mipmaps
temp_size = ddsImage.header.dwPitchOrLinearSize;
for (int i = 0; i < q; i++)
{
//Get lowest calculated mipmap
byte[] pixels = new byte[temp_size];
//Save to disk
GL.GetCompressedTexImage(TextureTarget.Texture2D, i, pixels);
File.WriteAllBytes("Temp\level" + i.ToString(), pixels);
temp_size = Math.Max(temp_size / 4, 16);
}
#endif
ddsImage = null;
ddsImage
是一个保存dds图像信息和所有像素数据的对象
这些纹理呈现为完全黑色。如果我取消注释 mipmap generation 的行,一切都会像魅力一样工作。此外,当我转储 mipmap 级别数据时,它们没有损坏。我有一种感觉,我需要以某种方式告诉 opengl 我定义了多少个 mipmap,但这里的大问题是为什么即使是基本级别也不起作用。至少这个应该有用。
好吧,根据 https://www.khronos.org/opengl/wiki/Common_Mistakes#Legacy_Generation
,事实证明我创建的纹理确实可能不完整我按照这些步骤操作,发现我需要在上传纹理数据之前设置 MAX_LEVEL 和 BASE_LEVEL 参数,这种方式非常有效。
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 8);
最大级别的值应该是 mips - 1
。但出于某种原因,当我尝试使用图像的所有 mipmap 时,纹理再次变黑。我还没有彻底测试它,但我认为我应该完全忽略 2x2 和 1x1 mipmap 的上传。如果我对此进行测试,我会更新答案。