OpenGLフレームバッファ処理を単純な「このテクスチャを「レンダリングターゲット」として設定する」呼び出しに抽象化するC#(SharpGL風)コードがあります。テクスチャが最初にレンダー ターゲットとして設定されるとき、そのサイズのテクスチャに一致する深度バッファを持つ FBO を作成します。その FBO/深度バッファ コンボは、同じサイズのすべてのテクスチャに再利用されます。
次のような奇妙なエラーがあります。
最初はアプリが実行され、正常にレンダリングされます。しかし、ウィンドウ サイズを大きくすると、一部のコードで「レンダー ターゲット」テクスチャのサイズを変更する必要が生じる可能性があります。これは、glDeleteTextures() および glGenTextures() を介して行われます (バインド、glTexImage2D、および texparams により、MIN_FILTER と MAG_FILTER は両方とも GL_NEAREST になります)。 )。そうするときに同じ名前 (ID) を取得する傾向があることに気付きました (GL は解放されたばかりの名前を再利用するため)。
次に、次のコードを実行します (わずかに粗悪な GL ライクな構文をお詫びします)。
void SetRenderTarget(Texture texture)
{
if (texture != null)
{
var size = (texture.Width << 16) | texture.Height;
FrameBufferInfo info;
if (!_mapSizeToFrameBufferInfo.TryGetValue(size, out info))
{
info = new FrameBufferInfo();
info.Width = texture.Width;
info.Height = texture.Height;
GL.GenFramebuffersEXT(1, _buffer);
info.FrameBuffer = _buffer[0];
GL.BindFramebufferEXT(GL.FRAMEBUFFER_EXT, info.FrameBuffer);
GL.FramebufferTexture2DEXT(GL.FRAMEBUFFER_EXT, GL.COLOR_ATTACHMENT0_EXT, GL.TEXTURE_2D, texture.InternalID, 0);
GL.GenRenderbuffersEXT(1, _buffer);
info.DepthBuffer = _buffer[0];
GL.BindRenderBufferEXT(GL.RENDERBUFFER_EXT, info.DepthBuffer);
GL.RenderbufferStorageEXT(GL.RENDERBUFFER_EXT, GL.DEPTH_COMPONENT16, texture.Width, texture.Height);
GL.BindRenderBufferEXT(GL.RENDERBUFFER_EXT, 0);
GL.FramebufferRenderbufferEXT(GL.FRAMEBUFFER_EXT, GL.DEPTH_ATTACHMENT_EXT, GL.RENDERBUFFER_EXT, info.DepthBuffer);
_mapSizeToFrameBufferInfo.Add(size, info);
}
else
{
GL.BindFramebufferEXT(GL.FRAMEBUFFER_EXT, info.FrameBuffer);
GL.FramebufferTexture2DEXT(GL.FRAMEBUFFER_EXT, GL.COLOR_ATTACHMENT0_EXT, GL.TEXTURE_2D, texture.InternalID, 0);
}
GL.CheckFrameBufferStatus(GL.FRAMEBUFFER_EXT);
}
else
{
GL.FramebufferTexture2DEXT(GL.FRAMEBUFFER_EXT, GL.COLOR_ATTACHMENT0_EXT, GL.TEXTURE_2D, 0, 0);
GL.BindFramebufferEXT(GL.FRAMEBUFFER_EXT, 0);
}
ProjectStandardOrthographic();
}
上記のウィンドウのサイズ変更後、GL は glFramebufferTexture2DEXT() 呼び出しから GL_INVALID_VALUE エラーを返します (glGetError() および gDEBugger で識別されます)。これを無視すると、glCheckFrameBufferStatus() は後で GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT で失敗します。これも無視すると、「framebuffer to dobious to do anything」エラーを確認すると、予想されるエラーが表示され、確認しないと黒い画面が表示されます。
NVidia GeForce GTX 550 Ti、Vista 64 (32 ビット アプリ)、306.97 ドライバーで実行しています。Core プロファイルで GL 3.3 を使用しています。
回避策と好奇心:テクスチャを再配置するときに、glDeleteTextures() の前に glGenTextures() を実行すると、同じ ID が返されないようにするために、問題が解決します。これは愚かなクルーゲであり、メモリ不足エラーの可能性を高めるため、これを行いたくありません。GLが最近のFBOでテクスチャを使用していた/使用していて、テクスチャIDが使用されているか、何らかの形で無効になっているため、受け入れられないと判断したためだと理論付けていますか? 多分?
問題の後、gDEBugger は、両方の FBO (深度バッファーと以前のテクスチャが小さい元のものと、組み合わせが大きい新しいもの) に同じテクスチャ ID が添付されていることを示しています。
割り当てを解除する前に、(再び glFramebufferTexture2DEXT を介して) フレーム バッファからテクスチャを切り離そうとしましたが、役に立ちませんでした (gDEBuffer は変更を反映しますが、問題は引き続き発生します)。深度バッファを完全に取り出してみました。使用する前に glGetTexLevelParameter() でテクスチャ サイズを確認してみました。それは確かに存在します。