diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 34f801d..6f7432e 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -42,9 +42,9 @@ #import "KRBoundingVolume.h" #import "KRStockGeometry.h" -KRCamera::KRCamera(KRContext &context, GLint width, GLint height) : KRContextObject(context) { - backingWidth = width; - backingHeight = height; +KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { + backingWidth = 0; + backingHeight = 0; double const PI = 3.141592653589793f; @@ -96,6 +96,12 @@ KRCamera::KRCamera(KRContext &context, GLint width, GLint height) : KRContextObj m_cShadowBuffers = 0; + compositeDepthTexture = 0; + compositeColorTexture = 0; + lightAccumulationTexture = 0; + compositeFramebuffer = 0; + lightAccumulationBuffer = 0; + memset(shadowFramebuffer, sizeof(GLuint) * 3, 0); memset(shadowDepthTexture, sizeof(GLuint) * 3, 0); @@ -104,8 +110,6 @@ KRCamera::KRCamera(KRContext &context, GLint width, GLint height) : KRContextObj m_skyBoxName = ""; m_pSkyBoxTexture = NULL; - - createBuffers(); } KRCamera::~KRCamera() { @@ -139,6 +143,8 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix) GLint defaultFBO; GLDEBUG(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO)); + createBuffers(); + m_pContext->rotateBuffers(true); KRMat4 invViewMatrix = viewMatrix; invViewMatrix.invert(); @@ -157,7 +163,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix) lightDirection.normalize(); - allocateShadowBuffers(); + allocateShadowBuffers(m_cShadowBuffers); int iOffset=m_iFrame % m_cShadowBuffers; for(int iShadow2=iOffset; iShadow2 < m_cShadowBuffers + iOffset; iShadow2++) { int iShadow = iShadow2 % m_cShadowBuffers; @@ -202,6 +208,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix) void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightDirection, KRVector3 &cameraPosition) { + setViewportSize(KRVector2(backingWidth, backingHeight)); @@ -497,52 +504,63 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD void KRCamera::createBuffers() { - // ===== Create offscreen compositing framebuffer object ===== - GLDEBUG(glGenFramebuffers(1, &compositeFramebuffer)); - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); + GLint renderBufferWidth = 0, renderBufferHeight = 0; + GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &renderBufferWidth)); + GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &renderBufferHeight)); - // ----- Create texture color buffer for compositeFramebuffer ----- - GLDEBUG(glGenTextures(1, &compositeColorTexture)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, compositeColorTexture, 0)); - - // ----- Create Depth Texture for compositeFramebuffer ----- - GLDEBUG(glGenTextures(1, &compositeDepthTexture)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); - //GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); - //GLDEBUG(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, backingWidth, backingHeight)); - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); - - // ===== Create offscreen compositing framebuffer object ===== - GLDEBUG(glGenFramebuffers(1, &lightAccumulationBuffer)); - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, lightAccumulationBuffer)); - - // ----- Create texture color buffer for compositeFramebuffer ----- - GLDEBUG(glGenTextures(1, &lightAccumulationTexture)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, lightAccumulationTexture)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures - GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightAccumulationTexture, 0)); - - allocateShadowBuffers(); + if(renderBufferWidth != backingWidth || renderBufferHeight != backingHeight) { + backingWidth = renderBufferWidth; + backingHeight = renderBufferHeight; + + destroyBuffers(); + + // ===== Create offscreen compositing framebuffer object ===== + GLDEBUG(glGenFramebuffers(1, &compositeFramebuffer)); + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); + + // ----- Create texture color buffer for compositeFramebuffer ----- + GLDEBUG(glGenTextures(1, &compositeColorTexture)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, compositeColorTexture, 0)); + + // ----- Create Depth Texture for compositeFramebuffer ----- + GLDEBUG(glGenTextures(1, &compositeDepthTexture)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); + //GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); + //GLDEBUG(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, backingWidth, backingHeight)); + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); + + // ===== Create offscreen compositing framebuffer object ===== + GLDEBUG(glGenFramebuffers(1, &lightAccumulationBuffer)); + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, lightAccumulationBuffer)); + + // ----- Create texture color buffer for compositeFramebuffer ----- + GLDEBUG(glGenTextures(1, &lightAccumulationTexture)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, lightAccumulationTexture)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures + GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightAccumulationTexture, 0)); + + allocateShadowBuffers(m_cShadowBuffers); + } } -void KRCamera::allocateShadowBuffers() { +void KRCamera::allocateShadowBuffers(int cBuffers) { // First deallocate buffers no longer needed - for(int iShadow = m_cShadowBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { + for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { if (shadowDepthTexture[iShadow]) { GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); shadowDepthTexture[iShadow] = 0; @@ -555,7 +573,7 @@ void KRCamera::allocateShadowBuffers() { } // Allocate newly required buffers - for(int iShadow = 0; iShadow < m_cShadowBuffers; iShadow++) { + for(int iShadow = 0; iShadow < cBuffers; iShadow++) { if(!shadowDepthTexture[iShadow]) { shadowValid[iShadow] = false; @@ -580,8 +598,7 @@ void KRCamera::allocateShadowBuffers() { void KRCamera::destroyBuffers() { - m_cShadowBuffers = 0; - allocateShadowBuffers(); + allocateShadowBuffers(0); if (compositeDepthTexture) { GLDEBUG(glDeleteTextures(1, &compositeDepthTexture)); diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index e7a1dce..48717f0 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -52,7 +52,7 @@ class KRContext; class KRCamera : public KRContextObject { public: - KRCamera(KRContext &context, GLint width, GLint height); + KRCamera(KRContext &context); virtual ~KRCamera(); GLint backingWidth, backingHeight; @@ -60,7 +60,7 @@ public: void renderFrame(KRScene &scene, KRMat4 &viewMatrix); void renderShadowBuffer(KRScene &scene, int iShadow); void invalidateShadowBuffers(); - void allocateShadowBuffers(); + void allocateShadowBuffers(int cBuffers); void createBuffers(); KRVector3 getPosition() const; diff --git a/KREngine/KREngine/Classes/KREngine.h b/KREngine/KREngine/Classes/KREngine.h index 0f0037e..97f44e0 100644 --- a/KREngine/KREngine/Classes/KREngine.h +++ b/KREngine/KREngine/Classes/KREngine.h @@ -50,7 +50,7 @@ typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_F @property(nonatomic, assign) KRCamera *camera; @property(nonatomic, retain) NSString *debug_text; -- (id)initForWidth: (GLuint)width Height: (GLuint)height; +- (id)init; - (BOOL)loadResource:(NSString *)path; // Parameter enumeration interface diff --git a/KREngine/KREngine/Classes/KREngine.mm b/KREngine/KREngine/Classes/KREngine.mm index a8ab0c1..d6c5d0d 100644 --- a/KREngine/KREngine/Classes/KREngine.mm +++ b/KREngine/KREngine/Classes/KREngine.mm @@ -51,13 +51,13 @@ using namespace std; @synthesize debug_text = _debug_text; double const PI = 3.141592653589793f; -- (id)initForWidth: (GLuint)width Height: (GLuint)height +- (id)init { _camera = NULL; _context = NULL; if ((self = [super init])) { _context = new KRContext(); - _camera = new KRCamera(*_context, width, height); + _camera = new KRCamera(*_context); _parameter_names = [@{ @"camera_fov" : @0, @"shadow_quality" : @1, diff --git a/KREngine/KREngine/Classes/KRMat4.cpp b/KREngine/KREngine/Classes/KRMat4.cpp index 8cdbdb6..27758a3 100644 --- a/KREngine/KREngine/Classes/KRMat4.cpp +++ b/KREngine/KREngine/Classes/KRMat4.cpp @@ -303,3 +303,31 @@ KRVector3 KRMat4::DotWDiv(const KRMat4 &m, const KRVector3 &v) { r /= DotW(m, v); return r; } + +KRMat4 KRMat4::LookAt(const KRVector3 &cameraPos, const KRVector3 &lookAtPos, const KRVector3 &upDirection) +{ + KRMat4 matLookat; + KRVector3 lookat_z_axis = lookAtPos - cameraPos; + lookat_z_axis.normalize(); + KRVector3 lookat_x_axis = KRVector3::Cross(upDirection, lookat_z_axis); + lookat_x_axis.normalize(); + KRVector3 lookat_y_axis = KRVector3::Cross(lookat_z_axis, lookat_x_axis); + + matLookat.getPointer()[0] = lookat_x_axis.x; + matLookat.getPointer()[1] = lookat_y_axis.x; + matLookat.getPointer()[2] = lookat_z_axis.x; + + matLookat.getPointer()[4] = lookat_x_axis.y; + matLookat.getPointer()[5] = lookat_y_axis.y; + matLookat.getPointer()[6] = lookat_z_axis.y; + + matLookat.getPointer()[8] = lookat_x_axis.z; + matLookat.getPointer()[9] = lookat_y_axis.z; + matLookat.getPointer()[10] = lookat_z_axis.z; + + matLookat.getPointer()[12] = -KRVector3::Dot(lookat_x_axis, cameraPos); + matLookat.getPointer()[13] = -KRVector3::Dot(lookat_y_axis, cameraPos); + matLookat.getPointer()[14] = -KRVector3::Dot(lookat_z_axis, cameraPos); + + return matLookat; +} \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRMat4.h b/KREngine/KREngine/Classes/KRMat4.h index 5c15ab7..053cd54 100644 --- a/KREngine/KREngine/Classes/KRMat4.h +++ b/KREngine/KREngine/Classes/KRMat4.h @@ -105,6 +105,8 @@ public: static KRVector3 Dot(const KRMat4 &m, const KRVector3 &v); static float DotW(const KRMat4 &m, const KRVector3 &v); static KRVector3 DotWDiv(const KRMat4 &m, const KRVector3 &v); + + static KRMat4 LookAt(const KRVector3 &cameraPos, const KRVector3 &lookAtPos, const KRVector3 &upDirection); }; #endif // KRMAT4_I \ No newline at end of file