如何解决OpenTK屏幕外帧缓冲区变形并且使用相同的材质渲染不正确?
我正在尝试实现阴影映射:将所有相关对象的深度渲染为屏幕外的纹理,然后在主通道中使用该纹理来找出光源遮挡了哪些碎片。
但是在此之前,我只是试图正确地获取任何形式的帧缓冲区。我创建了一个FBO,其中包含2056x2056 4通道图像,然后是另一个不带纹理的图像,仅表示并绑定回默认的帧缓冲区(opentk窗口)。
我正在使用一个简单的着色器,该着色器在屏幕外缓冲区上使用uvs作为R,G颜色,在主屏幕纹理上使用phong着色器,并且我将发送相同的制服。唯一的区别是我没有清除屏幕外缓冲区,也没有深度附件。但是出于某种原因,屏幕外的帧缓冲区变得超扭曲并且很小,就像它仅占用纹理大小的1/4一样,它扭曲了,并且还有一些怪异的嘈杂剪辑。
任何帮助/见解都将非常感谢。 谢谢!
我的FBO班。
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div class="d-flex justify-content-center" style="margin-bottom: 50px;">
<h1 style="text-align:center;">PHP-ohjelmointi<br>Loppuharjoitus</h1>
</div>
<div class="d-flex justify-content-center">
<div id="formi" style="width: 500px;" >
<form action="rajapinta.php" method="post">
<input type="text" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm" name="nimi" v-model="name" placeholder="Tuotteen nimi">
<input type="text" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm" name="kategoria" v-model="name" placeholder="Tuotteen kategoria">
<input type="number" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm" name="tuoteid" v-model="name" placeholder="Tuoteid">
<input type="number" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm" name="hinta" v-model="name" placeholder="Hinta alle (€)">
<input type="number" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm" name="paino" v-model="name" placeholder="Paino alle (kg)">
<input style="margin-top: 20px;" type="submit" value="Lähetä">
</form>
</div>
</div>
</body>
</html>
我的Texture类(fbo包含)
namespace MaterialRelated
{
public class FBO : ITypeID
{
public readonly int Handle = 0;
public readonly CreateFBOs.FBOType Type;
public Texture Texture { get; private set; }
public FBO(CreateFBOs.FBOType type,int width,int height,FramebufferAttachment attachment,PixelInternalFormat internalFormat,TextureUnit textureUnit)
{
Handle = GL.GenFramebuffer();
Type = type;
Use();
AssignTexture(Texture.Empty(width,height,internalFormat,textureUnit),attachment);
var fboStatus = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
if (fboStatus != FramebufferErrorCode.FramebufferComplete)
throw new Exception($"Frame Buffer Exception! {fboStatus}");
}
/// <summary>
/// Creates default fbo
/// </summary>
public FBO()
{
Type = CreateFBOs.FBOType.Default;
Handle = 0;
Texture = null;
}
public void Use()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer,Handle);
}
public void SetDrawingStates()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer,Handle);
}
public static void UseDefaultBuffer()
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer,0);
}
public void AssignTexture(Texture texture,FramebufferAttachment attachment)
{
Texture = texture;
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,attachment,TextureTarget.Texture2D,texture.Handle,0); //todo fix assign tex
}
public int GetTypeID() => (int) Type;
}
}
我在其中设置了两个fbo(好吧……更多是一个接口)
namespace MaterialRelated
{
public class Texture
{
public TextureUnit TextureUnit { get; private set; }
public PixelInternalFormat InternalPixelFormat { get; private set; }
public readonly int Handle;
public byte[] Colors; //todo make array for perf
public Image<Rgba32> LaborsImage;
public int Width { get; private set; }
public int Height { get; private set; }
public Texture()
{
Handle = GL.GenTexture();
}
/// <summary>
/// loads file using sixlabors library... turn cookOnLoad off if you're going to manipulate image on cpu before uploading to openGL
/// </summary>
public static Texture FromFile(string fileName,TextureUnit textureUnit) //turn cookOnLoad off if you're going to manipulate image on cpu before uploading to openGL
{
var texture = new Texture();
texture.InternalPixelFormat = PixelInternalFormat.Rgba;
texture.TextureUnit = textureUnit;
texture.Use();
texture.ApplyTextureSettings();
texture.LoadImage(fileName);
texture.CookSixLaborsImageToByteArray();
texture.UploadToShader();
return texture;
}
public static Texture Empty(int width,TextureUnit textureUnit)
{
var texture = new Texture();
texture.InternalPixelFormat = internalFormat;
texture.TextureUnit = textureUnit;
texture.Use();
texture.ApplyTextureSettings();
texture.Width = width;
texture.Height = height;
texture.CreateEmptyByteArray();
texture.UploadToShader();
return texture;
}
public void LoadImage(string fileName)
{
string path = SerializationManager.TexturePath + fileName;
LaborsImage = Image.Load<Rgba32>(path);
LaborsImage.Mutate(x => x.Flip(FlipMode.Vertical)); //ImageSharp loads from the top-left pixel,whereas OpenGL loads from the bottom-left,causing the texture to be flipped vertically.
Width = LaborsImage.Width;
Height = LaborsImage.Height;
}
public void CreateEmptyByteArray()
{
int area = Width * Height;
Colors = new byte[area * 4];
}
public void CookSixLaborsImageToByteArray()
{
if (!LaborsImage.TryGetSinglePixelSpan(out var tempPixels))
throw new Exception("Image Loading Error: Is Texture Corrupt?");
int area = Width * Height;
if (Colors == null || Colors.Length != area * 4) //init colors to proper length if not already
Colors = new byte[area * 4];
for (int i = 0; i < tempPixels.Length; i++)
{
int indexStart = i * 4;
Colors[indexStart + 0] = tempPixels[i].R;
Colors[indexStart + 1] = tempPixels[i].G;
Colors[indexStart + 2] = tempPixels[i].B;
Colors[indexStart + 3] = tempPixels[i].A;
}
}
public void Use()
{
GL.ActiveTexture(TextureUnit);
GL.BindTexture(TextureTarget.Texture2D,Handle);
}
public void UploadToShader()
{
Use();
GL.TexImage2D(TextureTarget.Texture2D,InternalPixelFormat,Width,Height,PixelFormat.Rgba,PixelType.UnsignedByte,Colors);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
}
private void ApplyTextureSettings() //todo make it so doesn't always have to be rgba image
{
Use();
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureWrapS,(int) TextureWrapMode.Repeat); //tex wrap mode
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureWrapT,(int) TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D,TextureParameterName.TextureMagFilter,(int) TextureMagFilter.Linear); //scaling up,tex interp
GL.TexParameter(TextureTarget.Texture2D,(int) TextureMagFilter.Linear); //scaling down
}
}
}
我的绘画循环:
ShadowBuffer = new FBO(FBOType.Shadow,2560,FramebufferAttachment.ColorAttachment0,PixelInternalFormat.Rgba,TextureUnit.Texture3);
var defaultBuffer = new FBO();
解决方法
最后的问题是:
- 我没有更改GL.viewport的大小以匹配帧缓冲区。
- 我没有启用人脸剔除,因此当我基于uvs /法线(没有深度附件)进行着色时,有时会穿过球体多边形的内壳而不是外壳,从而导致颜色不连续屏幕纹理的大小。
我也偶然地没有正确设置纹理过滤,但这并不是我关注的任何主要图形故障的原因。
谢谢您的帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。