Add multisampled FBO support
This commit is contained in:
parent
f20d32eb3a
commit
f84505f36b
103
src/k3.c
103
src/k3.c
@ -2744,46 +2744,81 @@ struct k3ARBFP *k3ProgramARBFP(const char *src) {
|
||||
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 " : "");
|
||||
|
||||
GLuint fbo = 0;
|
||||
if(GLAD_GL_EXT_framebuffer_object) {
|
||||
glGenFramebuffersEXT(1, &fbo);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDrawBuffer(GL_BACK); // XXX: this should not be necessary
|
||||
} else {
|
||||
if(samples && (!GLAD_GL_EXT_framebuffer_multisample || !GLAD_GL_EXT_framebuffer_blit)) {
|
||||
samples = 0;
|
||||
k3Log(k3_WARN, "Multisampled offscreens not supported.");
|
||||
}
|
||||
|
||||
if(!GLAD_GL_EXT_framebuffer_object) {
|
||||
k3Log(k3_ERR, "Non-FBO offscreens not implemented");
|
||||
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->diffuse = diffuse;
|
||||
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;
|
||||
}
|
||||
|
||||
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth) {
|
||||
return k3OffscreenCreateMultisampled(diffuse, depth, 0);
|
||||
}
|
||||
|
||||
void k3BeginOffscreen(struct k3Offscreen *offscr) {
|
||||
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;
|
||||
glViewport(0, 0, k3TexSzX(t), k3TexSzY(t));
|
||||
@ -2794,6 +2829,12 @@ void k3BeginOffscreen(struct k3Offscreen *offscr) {
|
||||
|
||||
void k3EndOffscreen(struct k3Offscreen *offscr) {
|
||||
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);
|
||||
glViewport(0, 0, MainWidth, MainHeight);
|
||||
} else {
|
||||
@ -2809,7 +2850,9 @@ void k3BlitToScreenEffect(struct k3Offscreen *offscr, int additive, int effect,
|
||||
if(GLAD_GL_EXT_framebuffer_object) {
|
||||
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) {
|
||||
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");
|
||||
glUniform2f(uSz, k3TexSzX(offscr->diffuse), k3TexSzY(offscr->diffuse));
|
||||
glUniform2f(uSz, k3TexSzX(tex), k3TexSzY(tex));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
} else {
|
||||
@ -2864,8 +2907,8 @@ void k3BlitToScreenEffect(struct k3Offscreen *offscr, int additive, int effect,
|
||||
glUseProgramObjectARB(effect == k3_GLSL ? GL_FROM_K3GLSL(program) : 0);
|
||||
}
|
||||
|
||||
float bleedW = 1.0f / k3TexSzX(offscr->diffuse);
|
||||
float bleedH = 1.0f / k3TexSzY(offscr->diffuse);
|
||||
float bleedW = 1.0f / k3TexSzX(tex);
|
||||
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_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);
|
||||
|
||||
struct k3Offscreen;
|
||||
struct k3Offscreen *k3OffscreenCreateMultisampled(struct k3Tex *diffuse, struct k3Tex *depth, uint8_t samples);
|
||||
struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth);
|
||||
void k3BeginOffscreen(struct k3Offscreen*);
|
||||
void k3EndOffscreen(struct k3Offscreen*);
|
||||
|
@ -45,6 +45,13 @@ struct k3Offscreen {
|
||||
GLuint fbo;
|
||||
struct k3Tex *diffuse;
|
||||
struct k3Tex *depth;
|
||||
|
||||
struct {
|
||||
uint8_t samples;
|
||||
GLuint fbo;
|
||||
GLuint rboDiffuse;
|
||||
GLuint rboDepth;
|
||||
} multisampling;
|
||||
};
|
||||
|
||||
struct k3Mdl {
|
||||
|
Loading…
Reference in New Issue
Block a user