237 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			237 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								#include "RenderTargetImpl.h"
							 | 
						||
| 
								 | 
							
								#include "ogl.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <Kore/Graphics3/Graphics.h>
							 | 
						||
| 
								 | 
							
								#include <Kore/Log.h>
							 | 
						||
| 
								 | 
							
								#include <Kore/System.h>
							 | 
						||
| 
								 | 
							
								#ifdef KINC_ANDROID
							 | 
						||
| 
								 | 
							
								#include <GLContext.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								using namespace Kore;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef GL_RGBA16F_EXT
							 | 
						||
| 
								 | 
							
								#define GL_RGBA16F_EXT 0x881A
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef GL_RGBA32F_EXT
							 | 
						||
| 
								 | 
							
								#define GL_RGBA32F_EXT 0x8814
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef GL_HALF_FLOAT
							 | 
						||
| 
								 | 
							
								#define GL_HALF_FLOAT 0x140B
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace {
							 | 
						||
| 
								 | 
							
									int pow(int pow) {
							 | 
						||
| 
								 | 
							
										int ret = 1;
							 | 
						||
| 
								 | 
							
										for (int i = 0; i < pow; ++i)
							 | 
						||
| 
								 | 
							
											ret *= 2;
							 | 
						||
| 
								 | 
							
										return ret;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int getPower2(int i) {
							 | 
						||
| 
								 | 
							
										for (int power = 0;; ++power)
							 | 
						||
| 
								 | 
							
											if (pow(power) >= i)
							 | 
						||
| 
								 | 
							
												return pow(power);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool nonPow2RenderTargetsSupported() {
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
								#ifdef KINC_ANDROID
							 | 
						||
| 
								 | 
							
										if (ndk_helper::GLContext::GetInstance()->GetGLVersion() >= 3.0)
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void RenderTargetImpl::setupDepthStencil(int depthBufferBits, int stencilBufferBits, int width, int height) {
							 | 
						||
| 
								 | 
							
									if (depthBufferBits > 0 && stencilBufferBits > 0) {
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										GLenum internalFormat = GL_DEPTH24_STENCIL8_OES;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										GLenum internalFormat;
							 | 
						||
| 
								 | 
							
										if (depthBufferBits == 24)
							 | 
						||
| 
								 | 
							
											internalFormat = GL_DEPTH24_STENCIL8;
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
											internalFormat = GL_DEPTH32F_STENCIL8;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										// Renderbuffer
							 | 
						||
| 
								 | 
							
										// 		glGenRenderbuffers(1, &_depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// 		glCheckErrors();
							 | 
						||
| 
								 | 
							
										// 		glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// 		glCheckErrors();
							 | 
						||
| 
								 | 
							
										// 		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
							 | 
						||
| 
								 | 
							
										// 		glCheckErrors();
							 | 
						||
| 
								 | 
							
										// #ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										// 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// #else
							 | 
						||
| 
								 | 
							
										// 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// #endif
							 | 
						||
| 
								 | 
							
										// 		glCheckErrors();
							 | 
						||
| 
								 | 
							
										// Texture
							 | 
						||
| 
								 | 
							
										glGenTextures(1, &_depthTexture);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glBindTexture(GL_TEXTURE_2D, _depthTexture);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if (depthBufferBits > 0) {
							 | 
						||
| 
								 | 
							
										// Renderbuffer
							 | 
						||
| 
								 | 
							
										// glGenRenderbuffers(1, &_depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// glCheckErrors();
							 | 
						||
| 
								 | 
							
										// glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// glCheckErrors();
							 | 
						||
| 
								 | 
							
										// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
							 | 
						||
| 
								 | 
							
										// glCheckErrors();
							 | 
						||
| 
								 | 
							
										// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
							 | 
						||
| 
								 | 
							
										// glCheckErrors();
							 | 
						||
| 
								 | 
							
										// Texture
							 | 
						||
| 
								 | 
							
										glGenTextures(1, &_depthTexture);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glBindTexture(GL_TEXTURE_2D, _depthTexture);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
							 | 
						||
| 
								 | 
							
										glCheckErrors();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Graphics3::RenderTarget::RenderTarget(int width, int height, int depthBufferBits, bool antialiasing, RenderTargetFormat format, int stencilBufferBits,
							 | 
						||
| 
								 | 
							
								                                      int contextId)
							 | 
						||
| 
								 | 
							
								    : width(width), height(height) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (nonPow2RenderTargetsSupported()) {
							 | 
						||
| 
								 | 
							
										texWidth = width;
							 | 
						||
| 
								 | 
							
										texHeight = height;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										texWidth = getPower2(width);
							 | 
						||
| 
								 | 
							
										texHeight = getPower2(height);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									this->contextId = contextId;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// (DK) required on windows/gl
							 | 
						||
| 
								 | 
							
									Kore::System::makeCurrent(contextId);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									glGenTextures(1, &_texture);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBindTexture(GL_TEXTURE_2D, _texture);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch (format) {
							 | 
						||
| 
								 | 
							
								#ifndef KINC_MACOS
							 | 
						||
| 
								 | 
							
									case Target128BitFloat:
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_EXT, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, 0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case Target64BitFloat:
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_EXT, texWidth, texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, texWidth, texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case Target16BitDepth:
							 | 
						||
| 
								 | 
							
								#ifdef KINC_OPENGL_ES
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, texWidth, texHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case Target32Bit:
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glGenFramebuffers(1, &_framebuffer);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									setupDepthStencil(depthBufferBits, stencilBufferBits, texWidth, texHeight);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (format == Target16BitDepth) {
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _texture, 0);
							 | 
						||
| 
								 | 
							
								#ifndef OPENGLES
							 | 
						||
| 
								 | 
							
										glDrawBuffer(GL_NONE);
							 | 
						||
| 
								 | 
							
										glReadBuffer(GL_NONE);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else {
							 | 
						||
| 
								 | 
							
										glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									// GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
							 | 
						||
| 
								 | 
							
									// glDrawBuffers(1, drawBuffers);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									glBindFramebuffer(GL_FRAMEBUFFER, 0);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBindTexture(GL_TEXTURE_2D, 0);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Graphics3::RenderTarget::useColorAsTexture(TextureUnit unit) {
							 | 
						||
| 
								 | 
							
									glActiveTexture(GL_TEXTURE0 + unit.unit);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBindTexture(GL_TEXTURE_2D, _texture);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Graphics3::RenderTarget::useDepthAsTexture(TextureUnit unit) {
							 | 
						||
| 
								 | 
							
									glActiveTexture(GL_TEXTURE0 + unit.unit);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
									glBindTexture(GL_TEXTURE_2D, _depthTexture);
							 | 
						||
| 
								 | 
							
									glCheckErrors();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Graphics3::RenderTarget::setDepthStencilFrom(RenderTarget *source) {
							 | 
						||
| 
								 | 
							
									glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
							 | 
						||
| 
								 | 
							
									glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, source->_depthTexture, 0);
							 | 
						||
| 
								 | 
							
								}
							 |