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