Add multisampled FBO support
This commit is contained in:
		
							parent
							
								
									f20d32eb3a
								
							
						
					
					
						commit
						f84505f36b
					
				
							
								
								
									
										75
									
								
								src/k3.c
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								src/k3.c
									
									
									
									
									
								
							| @ -2744,14 +2744,29 @@ 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 " : ""); | ||||||
| 	 | 	 | ||||||
|  | 	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; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
| 	GLuint fbo = 0; | 	GLuint fbo = 0; | ||||||
| 	if(GLAD_GL_EXT_framebuffer_object) { |  | ||||||
| 	glGenFramebuffersEXT(1, &fbo); | 	glGenFramebuffersEXT(1, &fbo); | ||||||
| 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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) { | 	if(diffuse) { | ||||||
| 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(diffuse), 0); | 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, GL_FROM_K3TEX(diffuse), 0); | ||||||
| 	} else { | 	} else { | ||||||
| @ -2767,23 +2782,43 @@ struct k3Offscreen *k3OffscreenCreate(struct k3Tex *diffuse, struct k3Tex *depth | |||||||
| 		k3Log(k3_WARN, "Framebuffer incomplete"); | 		k3Log(k3_WARN, "Framebuffer incomplete"); | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | 	if(samples) { | ||||||
| 		glDrawBuffer(GL_BACK); // XXX: this should not be necessary
 | 		GLuint msfbo; | ||||||
| 	} else { | 		glGenFramebuffersEXT(1, &msfbo); | ||||||
| 		k3Log(k3_ERR, "Non-FBO offscreens not implemented"); | 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, msfbo); | ||||||
| 		return NULL; | 		 | ||||||
|  | 		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); | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 	struct k3Offscreen *ret = malloc(sizeof(*ret)); | 		if(depth) { | ||||||
| 	ret->fbo = fbo; | 			glGenRenderbuffersEXT(1, &ret->multisampling.rboDepth); | ||||||
| 	ret->diffuse = diffuse; | 			glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ret->multisampling.rboDepth); | ||||||
| 	ret->depth = depth; | 			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
	 mid
						mid