gpt4 book ai didi

c# - 将 OpenGL GLTexSubImage2D 用于 NOT Textures 会导致伪影

转载 作者:太空宇宙 更新时间:2023-11-03 10:39:52 28 4
gpt4 key购买 nike

我在 C# 中通过 OpenTK 使用 OpenGL,并尝试从通用位图中加载纹理。我的驱动程序不支持 NPOT 纹理,所以我所做的是使用 GL.TexImage2D 分配一个 POT 纹理,并通过 GL.TexSubImage2D 用我的位图填充它。但是我在绘制这些纹理时有伪影。看起来,它还在纹理的底部和右侧绘制了一个额外的像素。我应该只从比率中减去像素还是有其他错误?

创建代码:

GL.BindTexture(TextureTarget.Texture2D, t.Name);

GL.PixelStore(PixelStoreParameter.PackAlignment, 1);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texture.W2, texture.H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);

GL.BindTexture(TextureTarget.Texture2D, 0);

绘图代码:

GL.BindTexture(TextureTarget.Texture2D, t.Name);

float x1 = 0;
float x2 = texture.WidthRatio;
float y1 = 0;
float y2 = texture.HeightRatio;

float rx1 = rect.X;
float rx2 = rect.X + rect.W;
float ry1 = rect.Y;
float ry2 = rect.Y + rect.H;

GL.Begin(BeginMode.Quads);

GL.TexCoord2(x1, y1);
GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);

GL.TexCoord2(x1, y2);
GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);

GL.TexCoord2(x2, y2);
GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);

GL.TexCoord2(x2, y1);
GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);

GL.End();

GL.Disable(EnableCap.Blend);
GL.BindTexture(TextureTarget.Texture2D, 0);

其中texture.WidhtRatio = DataSize.Width/W2;

最佳答案

这都与纹理的边缘情况有关。当您第一次了解 GL 中的纹理时,大多数教程都会介绍以下内容:

  1. 过滤(纹素之间发生的事情)

    • 最近的
    • 线性

    下图可以看出区别。

  2. Wrap Modes(纹理边界之后发生的事情)

    请注意颜色的环绕,即使纹理坐标不在 -1 到 1 之外 --- 线性过滤和重复环绕模式的组合。

需要说的另一件重要的事情是样本被放置在像素和纹理元素的中间。这就是为什么 gl_FragCoord.xy 总是有分数 .5(直到你进行多重/ super 采样等)。这可以在下图中看到。我怀疑这就是问题所在。您可能希望调整纹理坐标以对纹理的插图进行采样,以避免相邻像素的插值(即 x+0.5x+width-0.5)。

enter image description here


Mipmaps 将包含来自更大区域的颜色,因此简单地更改坐标是行不通的。要重新创建 GL_CLAMP_TO_EDGE 的行为,您确实需要手动挤出子图像边框。或者,在上传之前清除纹理会简单得多。一种快速的方法是将纹理附加到 FBO 和 glClear:

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glDeleteFramebuffers(1, &fbo);

为了进一步挤压纹理,我将上传子图像,然后在子图像和所需边框上绘制一个四边形。在片段着色器中,丢弃子图像内的像素并逐字调用 coord = clamp(coord, imageMin, imageMax)。为避免双重缓冲,read while drawing .如果你有多个子图像,你可以在这里使用 z-buffer 并绘制方形金字塔而不是四边形,允许深度测试像最小距离到任一子图像一样工作(就像 drawing voronoi cells with cones )

关于c# - 将 OpenGL GLTexSubImage2D 用于 NOT Textures 会导致伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25823327/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com