jav*_*ver 6 opengl state-machine render-to-texture
我尝试创建一个附有2个纹理的FrameBuffer(Multi Render Targets).然后在每个时间步骤中,清除和绘制两个纹理,如下面的代码.(某些部分将被替换为伪代码,以缩短它.)
版本1
//beginning of the 1st time step
initialize(framebufferID12)
//^ I quite sure it is done correctly,
//^ Note : there is no glDrawBuffers() calling
loop , do once every time step {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID12);
//(#1#) a line will be add here in version 2 (see belowed) <------------
glClearColor (0.5f, 0.0f, 0.5f, 0.0f);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// paint a lot of object here , using glsl (Shader .frag, .vert)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
Run Code Online (Sandbox Code Playgroud)
所有对象都正确地绘制到两个质感,但只有第一个纹理(ATTACHMENT0)被清除每一帧,这是不对的.
版本2
我尝试插入一行代码......
glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ;
Run Code Online (Sandbox Code Playgroud)
在(#1#),它按预期工作,即清除所有两个纹理.
(图片http://s13.postimg.org/66k9lr5av/gl_Draw_Buffer.jpg)
版本3
从第2版,我动议是glDrawBuffers()语句是内部帧缓冲区的初始化这样
initialize(int framebufferID12){
int nameFBO = glGenFramebuffersEXT();
int nameTexture0=glGenTextures();
int nameTexture1=glGenTextures();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,nameFBO);
glBindTexture(nameTexture0);
glTexImage2D( .... ); glTexParameteri(...);
glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture0);
glBindTexture(nameTexture1);
glTexImage2D( .... ); glTexParameteri(...);
glFramebufferTexture2DEXT( ATTACHMENT0, nameTexture1);
glDrawBuffers({ATTACHMENT0,ATTACHMENT1}) ; //<--- moved here ---
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
return nameFBO ;
}
Run Code Online (Sandbox Code Playgroud)
它不再起作用(症状如版本1),为什么?
opengl手册说"对上下文状态的更改将存储在这个对象中",所以glDrawBuffers()的状态修改 会存储在"framebufferID12"中吗?那么,为什么我必须每次都调用它(或每次我改变FBO)
我可能会误解一些opengl的概念,请有人赐教.
编辑1:谢谢jp.我同意这是有道理的,但是不应该将状态记录在FBO中吗?
编辑2(接受答案):Reto Koradi的回答是正确的!我正在使用一个名为LWJGL的不太标准的库.
是的,绘制缓冲区设置是帧缓冲区状态的一部分.例如,如果您查看OpenGL 3.3规范文档,它将在第299页的表6.23中列出,标题为"Framebuffer(每帧缓冲对象的状态)".
FBO的默认值是单个绘制缓冲区,即GL_COLOR_ATTACHMENT0.从同一规范,第214页:
对于帧缓冲对象,在初始状态下,片段颜色为零的绘制缓冲区为COLOR_ATTACHMENT0.对于默认的帧缓冲区和帧缓冲区对象,除零之外的片段颜色的初始绘制缓冲区状态为NONE.
因此,如果您有多个绘制缓冲区,则需要显式glDrawBuffers()调用.
现在,如果你把glDrawBuffers()呼叫作为FBO设置的一部分,为什么它似乎不适合你,这有点神秘.我在你的代码中注意到的一件事是你正在使用EXTFBO调用的形式.我怀疑这可能与你的问题有关.
自3.0版以来,FBO已成为标准OpenGL的一部分.如果您有任何方式使用OpenGL 3.0或更高版本,我强烈建议您使用标准入口点.虽然扩展通常在功能成为标准后仍然有效,但我总是怀疑它们如何与其他功能交互.特别是,在3.0之前有多个FBO功能扩展,具有不同的行为.如果与标准FBO功能相比,其中一些与其他OpenGL调用的交互方式不同,我不会感到惊讶.
因此,请尝试使用标准入口点(没有EXT名称的入口点).这有望解决您的问题.