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); | ||
|  | } |