Add multisampled FBO support
This commit is contained in:
parent
f20d32eb3a
commit
f84505f36b
101
src/k3.c
101
src/k3.c
@ -2744,46 +2744,81 @@ struct k3ARBFP *k3ProgramARBFP(const char *src) {
|
|||||||
return (struct k3ARBFP*) (uintptr_t) p;
|
return (struct k3ARBFP*) (uintptr_t) p;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth) {
|
struct k3Offscreen *k3OffscreenCreateMultisampled(struct k3Tex *diffuse, struct k3Tex *depth, uint8_t samples) {
|
||||||
k3Log(k3_INFO, "Init %sFBO", !diffuse && depth ? "depth-only " : "");
|
k3Log(k3_INFO, "Init %sFBO", !diffuse && depth ? "depth-only " : "");
|
||||||
|
|
||||||
GLuint fbo = 0;
|
if(samples && (!GLAD_GL_EXT_framebuffer_multisample || !GLAD_GL_EXT_framebuffer_blit)) {
|
||||||
if(GLAD_GL_EXT_framebuffer_object) {
|
samples = 0;
|
||||||
glGenFramebuffersEXT(1, &fbo);
|
k3Log(k3_WARN, "Multisampled offscreens not supported.");
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
}
|
||||||
|
|
||||||
if(diffuse) {
|
if(!GLAD_GL_EXT_framebuffer_object) {
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(diffuse), 0);
|
|
||||||
} else {
|
|
||||||
glDrawBuffer(GL_NONE);
|
|
||||||
glReadBuffer(GL_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(depth) {
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(depth), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
|
||||||
k3Log(k3_WARN, "Framebuffer incomplete");
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
||||||
glDrawBuffer(GL_BACK); // XXX: this should not be necessary
|
|
||||||
} else {
|
|
||||||
k3Log(k3_ERR, "Non-FBO offscreens not implemented");
|
k3Log(k3_ERR, "Non-FBO offscreens not implemented");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k3Offscreen *ret = malloc(sizeof(*ret));
|
GLuint fbo = 0;
|
||||||
|
glGenFramebuffersEXT(1, &fbo);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||||
|
|
||||||
|
struct k3Offscreen *ret = calloc(1, sizeof(*ret));
|
||||||
ret->fbo = fbo;
|
ret->fbo = fbo;
|
||||||
ret->diffuse = diffuse;
|
ret->diffuse = diffuse;
|
||||||
ret->depth = depth;
|
ret->depth = depth;
|
||||||
|
ret->multisampling.samples = samples;
|
||||||
|
|
||||||
|
if(diffuse) {
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(diffuse), 0);
|
||||||
|
} else {
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
glReadBuffer(GL_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(depth) {
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(depth), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
||||||
|
k3Log(k3_WARN, "Framebuffer incomplete");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(samples) {
|
||||||
|
GLuint msfbo;
|
||||||
|
glGenFramebuffersEXT(1, &msfbo);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, msfbo);
|
||||||
|
|
||||||
|
ret->multisampling.fbo = msfbo;
|
||||||
|
|
||||||
|
if(diffuse) {
|
||||||
|
glGenRenderbuffersEXT(1, &ret->multisampling.rboDiffuse);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ret->multisampling.rboDiffuse);
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, diffuse->glInternalFormat, diffuse->szX, diffuse->szY);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, ret->multisampling.rboDiffuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(depth) {
|
||||||
|
glGenRenderbuffersEXT(1, &ret->multisampling.rboDepth);
|
||||||
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ret->multisampling.rboDepth);
|
||||||
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, depth->glInternalFormat, depth->szX, depth->szY);
|
||||||
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ret->multisampling.rboDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
glDrawBuffer(GL_BACK); // XXX: this should not be necessary
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth) {
|
||||||
|
return k3OffscreenCreateMultisampled(diffuse, depth, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void k3BeginOffscreen(struct k3Offscreen *offscr) {
|
void k3BeginOffscreen(struct k3Offscreen *offscr) {
|
||||||
if(GLAD_GL_EXT_framebuffer_object) {
|
if(GLAD_GL_EXT_framebuffer_object) {
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, offscr->fbo);
|
GLuint fbo = offscr->multisampling.samples > 0 ? offscr->multisampling.fbo : offscr->fbo;
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||||
|
|
||||||
struct k3Tex *t = offscr->diffuse ? offscr->diffuse : offscr->depth;
|
struct k3Tex *t = offscr->diffuse ? offscr->diffuse : offscr->depth;
|
||||||
glViewport(0, 0, k3TexSzX(t), k3TexSzY(t));
|
glViewport(0, 0, k3TexSzX(t), k3TexSzY(t));
|
||||||
@ -2794,6 +2829,12 @@ void k3BeginOffscreen(struct k3Offscreen *offscr) {
|
|||||||
|
|
||||||
void k3EndOffscreen(struct k3Offscreen *offscr) {
|
void k3EndOffscreen(struct k3Offscreen *offscr) {
|
||||||
if(GLAD_GL_EXT_framebuffer_object) {
|
if(GLAD_GL_EXT_framebuffer_object) {
|
||||||
|
if(offscr->multisampling.samples) {
|
||||||
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, offscr->fbo);
|
||||||
|
|
||||||
|
glBlitFramebufferEXT(0, 0, offscr->diffuse->szX, offscr->diffuse->szY, 0, 0, offscr->diffuse->szX, offscr->diffuse->szY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
glViewport(0, 0, MainWidth, MainHeight);
|
glViewport(0, 0, MainWidth, MainHeight);
|
||||||
} else {
|
} else {
|
||||||
@ -2809,7 +2850,9 @@ void k3BlitToScreenEffect(struct k3Offscreen *offscr, int additive, int effect,
|
|||||||
if(GLAD_GL_EXT_framebuffer_object) {
|
if(GLAD_GL_EXT_framebuffer_object) {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, GL_FROM_K3TEX(offscr->diffuse));
|
struct k3Tex *tex = offscr->diffuse ? offscr->diffuse : offscr->depth;
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, GL_FROM_K3TEX(tex));
|
||||||
|
|
||||||
if(additive) {
|
if(additive) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
@ -2856,7 +2899,7 @@ void k3BlitToScreenEffect(struct k3Offscreen *offscr, int additive, int effect,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLint uSz = glGetUniformLocation(GL_FROM_K3GLSL(basicBlitProgram), "u_sz");
|
GLint uSz = glGetUniformLocation(GL_FROM_K3GLSL(basicBlitProgram), "u_sz");
|
||||||
glUniform2f(uSz, k3TexSzX(offscr->diffuse), k3TexSzY(offscr->diffuse));
|
glUniform2f(uSz, k3TexSzX(tex), k3TexSzY(tex));
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
} else {
|
} else {
|
||||||
@ -2864,8 +2907,8 @@ void k3BlitToScreenEffect(struct k3Offscreen *offscr, int additive, int effect,
|
|||||||
glUseProgramObjectARB(effect == k3_GLSL ? GL_FROM_K3GLSL(program) : 0);
|
glUseProgramObjectARB(effect == k3_GLSL ? GL_FROM_K3GLSL(program) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
float bleedW = 1.0f / k3TexSzX(offscr->diffuse);
|
float bleedW = 1.0f / k3TexSzX(tex);
|
||||||
float bleedH = 1.0f / k3TexSzY(offscr->diffuse);
|
float bleedH = 1.0f / k3TexSzY(tex);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
1
src/k3.h
1
src/k3.h
@ -190,6 +190,7 @@ void k3PassDepthOnly(mat4 projection, mat4 cam, int clear, int cull);
|
|||||||
void k3PassShadowmap(mat4 projection, mat4 cam, struct k3Offscreen *offscr);
|
void k3PassShadowmap(mat4 projection, mat4 cam, struct k3Offscreen *offscr);
|
||||||
|
|
||||||
struct k3Offscreen;
|
struct k3Offscreen;
|
||||||
|
struct k3Offscreen *k3OffscreenCreateMultisampled(struct k3Tex *diffuse, struct k3Tex *depth, uint8_t samples);
|
||||||
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth);
|
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth);
|
||||||
void k3BeginOffscreen(struct k3Offscreen*);
|
void k3BeginOffscreen(struct k3Offscreen*);
|
||||||
void k3EndOffscreen(struct k3Offscreen*);
|
void k3EndOffscreen(struct k3Offscreen*);
|
||||||
|
@ -45,6 +45,13 @@ struct k3Offscreen {
|
|||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
struct k3Tex *diffuse;
|
struct k3Tex *diffuse;
|
||||||
struct k3Tex *depth;
|
struct k3Tex *depth;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t samples;
|
||||||
|
GLuint fbo;
|
||||||
|
GLuint rboDiffuse;
|
||||||
|
GLuint rboDepth;
|
||||||
|
} multisampling;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct k3Mdl {
|
struct k3Mdl {
|
||||||
|
Loading…
Reference in New Issue
Block a user