GPU framebuffer API:

Allow binding a texture to a different texture attachment than the
first.

Also fix a number error in seperable gaussian blur shader.
This commit is contained in:
2014-11-18 11:56:23 +01:00
parent 70a4bcd7f5
commit 998a867ba3
4 changed files with 47 additions and 25 deletions

View File

@@ -141,8 +141,8 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex);
* be called before rendering to the window framebuffer again */
GPUFrameBuffer *GPU_framebuffer_create(void);
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]);
void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex);
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
void GPU_framebuffer_texture_detach(GPUTexture *tex);
void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex, int w, int h);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);

View File

@@ -323,6 +323,7 @@ struct GPUTexture {
int fromblender; /* we got the texture from Blender */
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
int depth; /* is a depth texture? */
};
@@ -370,6 +371,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
tex->refcount = 1;
tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
tex->depth = depth;
tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -791,7 +793,7 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->refcount == 0) {
if (tex->fb)
GPU_framebuffer_texture_detach(tex->fb, tex);
GPU_framebuffer_texture_detach(tex);
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -831,9 +833,12 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
/* GPUFrameBuffer */
/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
#define GPU_FB_MAX_SLOTS 4
struct GPUFrameBuffer {
GLuint object;
GPUTexture *colortex;
GPUTexture *colortex[GPU_FB_MAX_SLOTS];
GPUTexture *depthtex;
};
@@ -857,16 +862,21 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
return fb;
}
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
{
GLenum status;
GLenum attachment;
GLenum error;
if (slot >= GPU_FB_MAX_SLOTS) {
fprintf(stderr, "Attaching to index %d framebuffer slot unsupported in blender use at most %d\n", slot, GPU_FB_MAX_SLOTS);
return 0;
}
if (tex->depth)
attachment = GL_DEPTH_ATTACHMENT_EXT;
else
attachment = GL_COLOR_ATTACHMENT0_EXT;
attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = fb->object;
@@ -890,8 +900,9 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err
glReadBuffer(GL_NONE);
}
else {
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
/* last bound prevails here, better allow explicit control here too */
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
}
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
@@ -905,22 +916,26 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err
if (tex->depth)
fb->depthtex = tex;
else
fb->colortex = tex;
fb->colortex[slot] = tex;
tex->fb= fb;
tex->fb_attachment = slot;
return 1;
}
void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
void GPU_framebuffer_texture_detach(GPUTexture *tex)
{
GLenum attachment;
GPUFrameBuffer *fb;
if (!tex->fb)
if (!tex->fb || tex->fb_attachment == -1)
return;
if (GG.currentfb != tex->fb->object) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
fb = tex->fb;
if (GG.currentfb != fb->object) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = tex->fb->object;
}
@@ -929,14 +944,16 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
attachment = GL_DEPTH_ATTACHMENT_EXT;
}
else {
fb->colortex = NULL;
attachment = GL_COLOR_ATTACHMENT0_EXT;
BLI_assert(fb->colortex[tex->fb_attachment] == tex);
fb->colortex[tex->fb_attachment] = NULL;
attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
tex->target, 0, 0);
tex->fb = NULL;
tex->fb_attachment = -1;
}
void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h)
@@ -973,10 +990,15 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
int i;
if (fb->depthtex)
GPU_framebuffer_texture_detach(fb, fb->depthtex);
if (fb->colortex)
GPU_framebuffer_texture_detach(fb, fb->colortex);
GPU_framebuffer_texture_detach(fb->depthtex);
for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
if (fb->colortex[i]) {
GPU_framebuffer_texture_detach(fb->colortex[i]);
}
}
if (fb->object) {
glDeleteFramebuffersEXT(1, &fb->object);
@@ -1093,7 +1115,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
@@ -1104,7 +1126,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}

View File

@@ -1851,7 +1851,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, NULL)) {
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1863,7 +1863,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1881,7 +1881,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, NULL)) {
if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1893,7 +1893,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}

View File

@@ -10,7 +10,7 @@ void main()
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y ) ) * 0.234375;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y ) ) * 0.09375;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, -3.0 * ScaleU.y ) ) * 0.015625;
color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625;
gl_FragColor = color;
}