OpenGL Skybox纹理包装工件

发布于 2025-01-25 11:27:47 字数 2469 浏览 0 评论 0原文

我正在尝试使用Opentk和Compute着色器制作路径示踪剂,但是我一直在努力在Skybox的边缘上重复纹理。我跟随 the Learnopengl 教程能够摆脱这些文物。 可以看到边缘重复的纹理“

这是加载Skybox纹理的片段:

private TextureHandle _skyboxTexture;
...
protected override void OnLoad() {
    base.OnLoad();
    GL.Enable(EnableCap.TextureCubeMapSeamless);
    ...
    _skyboxTexture = GL.CreateTexture(TextureTarget.TextureCubeMap);
    GL.BindTexture(TextureTarget.TextureCubeMap, _skyboxTexture);
    foreach (var file in Directory.GetFiles(@"Images\Skybox")) {
        using (var image = SixLabors.ImageSharp.Image.Load(file)) {
            image.Mutate(img => img.Rotate(180)); // without this the textures dont line up
            using (var ms = new MemoryStream()) {
                image.Save(ms, new BmpEncoder());
                GL.TexImage2D(Texture.CubeMapTextureTargetFromString(file), 0, (int)InternalFormat.Rgb, 2048, 2048, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, ms.ToArray());
            }
        }
    }
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
    ...
}

这些是RenderDoc的几个屏幕截图,您可以清楚地看到Skybox纹理中的伪像。在另一张图片中,您可以看到夹紧和无缝设置已正确加载。

此图像在stackoverflow上模糊,但是当您单击它时,它更好。

我认为这不是我的计算着色器中的采样逻辑的问题,因为使用RenderDoc时,我还可以在纹理中看到伪影。我还尝试将图像从内存线保存到.bmp,以检查图像加载过程中是否出了问题,但导出的图像看起来不错。这也不是Skybox纹理的问题,我尝试的所有纹理都会发生。

I am trying to make a path tracer using OpenTK and a compute shader, but I have been struggling with textures repeating on the edges of my skybox. I followed the tutorial from learnopengl and adapted it to work with my compute shader but I have not been able to get rid of these artifacts.
Here you can see the texture repeating on the edges

This is the snippet that loads the skybox texture:

private TextureHandle _skyboxTexture;
...
protected override void OnLoad() {
    base.OnLoad();
    GL.Enable(EnableCap.TextureCubeMapSeamless);
    ...
    _skyboxTexture = GL.CreateTexture(TextureTarget.TextureCubeMap);
    GL.BindTexture(TextureTarget.TextureCubeMap, _skyboxTexture);
    foreach (var file in Directory.GetFiles(@"Images\Skybox")) {
        using (var image = SixLabors.ImageSharp.Image.Load(file)) {
            image.Mutate(img => img.Rotate(180)); // without this the textures dont line up
            using (var ms = new MemoryStream()) {
                image.Save(ms, new BmpEncoder());
                GL.TexImage2D(Texture.CubeMapTextureTargetFromString(file), 0, (int)InternalFormat.Rgb, 2048, 2048, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, ms.ToArray());
            }
        }
    }
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
    GL.TexParameteri(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
    ...
}

These are a couple screenshots from RenderDoc, you can clearly see the artifact in the skybox texture. In the other picture you can see that the clamping and seamless settings are loaded correctly.
Artifact in renderdoc

This image is blurry on stackoverflow but when you click it it's better.
RenderDoc data

I don't think it is an issue with the sampling logic in my compute shader, because when using RenderDoc I can also see the artifact in the texture. I also tried saving the image from the MemoryStream to a .bmp to check if something is going wrong during the loading of the image, but the exported image looks fine. It's also not a problem with the skybox textures, it happens with all textures I try.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对你再特殊 2025-02-01 11:27:47

多亏了 derhass ,我使它起作用。问题在于,位图标头导致纹理不一致。我正在使用ImageSharp进行图像处理,因此我创建了一个实现IImageEncoder的新类,只是将RAW RGB值放入流中。我不需要Alpha频道,所以我省略了它,但是我认为可以很容易地添加它。

public class RawBytesEncoder : IImageEncoder {
    public void Encode<TPixel>(Image<TPixel> image, Stream stream) where TPixel : unmanaged, IPixel<TPixel> {
        for (var y = 0; y < image.Height; y++)
        for (var x = 0; x < image.Width; x++) {
            var target = new Rgba32();
            image[x, y].ToRgba32(ref target);
            stream.WriteByte(target.R);
            stream.WriteByte(target.G);
            stream.WriteByte(target.B);
        }
    }

    public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel<TPixel> {
        throw new NotImplementedException();
    }
}

我还必须在代码的另一部分中更改一些内容。该图像不再需要旋转180度,但需要翻转,并且GlTexImage中的PixelforMat现在再次为RGB。

foreach (var file in Directory.GetFiles(@"Images\Skybox"))
    using (var image = Image.Load(file)) {
        image.Mutate(img => img.Flip(FlipMode.Horizontal));
        using (var ms = new MemoryStream()) {
            image.Save(ms, new RawBytesEncoder());
            GL.TexImage2D(Texture.CubeMapTextureTargetFromString(file), 0, (int)InternalFormat.Rgb, 2048, 2048, 0, PixelFormat.Rgb, PixelType.UnsignedByte, ms.ToArray());
        }
    }
}

Thanks to derhass, I got it working. The problem was that the bitmap header caused a misalignment in the textures. I am using ImageSharp for image processing, so I created a new class that implements IImageEncoder and just puts the raw rgb values in the stream. I don't need the alpha channel so I omitted it but it can be added easily I think.

public class RawBytesEncoder : IImageEncoder {
    public void Encode<TPixel>(Image<TPixel> image, Stream stream) where TPixel : unmanaged, IPixel<TPixel> {
        for (var y = 0; y < image.Height; y++)
        for (var x = 0; x < image.Width; x++) {
            var target = new Rgba32();
            image[x, y].ToRgba32(ref target);
            stream.WriteByte(target.R);
            stream.WriteByte(target.G);
            stream.WriteByte(target.B);
        }
    }

    public Task EncodeAsync<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel<TPixel> {
        throw new NotImplementedException();
    }
}

I also had to change some stuff in the other part of my code. The image no longer needed to be rotated 180 degrees but needs to be flipped now, and the PixelFormat in glTexImage is Rgb again now.

foreach (var file in Directory.GetFiles(@"Images\Skybox"))
    using (var image = Image.Load(file)) {
        image.Mutate(img => img.Flip(FlipMode.Horizontal));
        using (var ms = new MemoryStream()) {
            image.Save(ms, new RawBytesEncoder());
            GL.TexImage2D(Texture.CubeMapTextureTargetFromString(file), 0, (int)InternalFormat.Rgb, 2048, 2048, 0, PixelFormat.Rgb, PixelType.UnsignedByte, ms.ToArray());
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文