Implemented KRMat4::LookAt

KREngine object no longer requires a width and height passed into init.
KRCamera no longer requires a width and height passed into the constructor; it now automatically resizes its buffers to match the active render target.

--HG--
extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40128
This commit is contained in:
kearwood
2012-10-17 19:43:15 +00:00
parent a884f4fcd2
commit 736ca4fc4b
6 changed files with 103 additions and 56 deletions

View File

@@ -42,9 +42,9 @@
#import "KRBoundingVolume.h" #import "KRBoundingVolume.h"
#import "KRStockGeometry.h" #import "KRStockGeometry.h"
KRCamera::KRCamera(KRContext &context, GLint width, GLint height) : KRContextObject(context) { KRCamera::KRCamera(KRContext &context) : KRContextObject(context) {
backingWidth = width; backingWidth = 0;
backingHeight = height; backingHeight = 0;
double const PI = 3.141592653589793f; double const PI = 3.141592653589793f;
@@ -96,6 +96,12 @@ KRCamera::KRCamera(KRContext &context, GLint width, GLint height) : KRContextObj
m_cShadowBuffers = 0; m_cShadowBuffers = 0;
compositeDepthTexture = 0;
compositeColorTexture = 0;
lightAccumulationTexture = 0;
compositeFramebuffer = 0;
lightAccumulationBuffer = 0;
memset(shadowFramebuffer, sizeof(GLuint) * 3, 0); memset(shadowFramebuffer, sizeof(GLuint) * 3, 0);
memset(shadowDepthTexture, 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_skyBoxName = "";
m_pSkyBoxTexture = NULL; m_pSkyBoxTexture = NULL;
createBuffers();
} }
KRCamera::~KRCamera() { KRCamera::~KRCamera() {
@@ -139,6 +143,8 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix)
GLint defaultFBO; GLint defaultFBO;
GLDEBUG(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO)); GLDEBUG(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO));
createBuffers();
m_pContext->rotateBuffers(true); m_pContext->rotateBuffers(true);
KRMat4 invViewMatrix = viewMatrix; KRMat4 invViewMatrix = viewMatrix;
invViewMatrix.invert(); invViewMatrix.invert();
@@ -157,7 +163,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix)
lightDirection.normalize(); lightDirection.normalize();
allocateShadowBuffers(); allocateShadowBuffers(m_cShadowBuffers);
int iOffset=m_iFrame % m_cShadowBuffers; int iOffset=m_iFrame % m_cShadowBuffers;
for(int iShadow2=iOffset; iShadow2 < m_cShadowBuffers + iOffset; iShadow2++) { for(int iShadow2=iOffset; iShadow2 < m_cShadowBuffers + iOffset; iShadow2++) {
int iShadow = iShadow2 % m_cShadowBuffers; 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) { void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightDirection, KRVector3 &cameraPosition) {
setViewportSize(KRVector2(backingWidth, backingHeight)); setViewportSize(KRVector2(backingWidth, backingHeight));
@@ -497,52 +504,63 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD
void KRCamera::createBuffers() { void KRCamera::createBuffers() {
// ===== Create offscreen compositing framebuffer object ===== GLint renderBufferWidth = 0, renderBufferHeight = 0;
GLDEBUG(glGenFramebuffers(1, &compositeFramebuffer)); GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &renderBufferWidth));
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &renderBufferHeight));
// ----- Create texture color buffer for compositeFramebuffer ----- if(renderBufferWidth != backingWidth || renderBufferHeight != backingHeight) {
GLDEBUG(glGenTextures(1, &compositeColorTexture)); backingWidth = renderBufferWidth;
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture)); backingHeight = renderBufferHeight;
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); destroyBuffers();
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 // ===== Create offscreen compositing framebuffer object =====
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); GLDEBUG(glGenFramebuffers(1, &compositeFramebuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, compositeColorTexture, 0)); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer));
// ----- Create Depth Texture for compositeFramebuffer ----- // ----- Create texture color buffer for compositeFramebuffer -----
GLDEBUG(glGenTextures(1, &compositeDepthTexture)); GLDEBUG(glGenTextures(1, &compositeColorTexture));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeColorTexture));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 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_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(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_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
//GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, compositeColorTexture, 0));
//GLDEBUG(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, backingWidth, backingHeight));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); // ----- Create Depth Texture for compositeFramebuffer -----
GLDEBUG(glGenTextures(1, &compositeDepthTexture));
// ===== Create offscreen compositing framebuffer object ===== GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture));
GLDEBUG(glGenFramebuffers(1, &lightAccumulationBuffer)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, lightAccumulationBuffer)); 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
// ----- Create texture color buffer for compositeFramebuffer ----- GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); // This is necessary for non-power-of-two textures
GLDEBUG(glGenTextures(1, &lightAccumulationTexture)); GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, lightAccumulationTexture)); //GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, backingWidth, backingHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); //GLDEBUG(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, backingWidth, backingHeight));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0));
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 // ===== Create offscreen compositing framebuffer object =====
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL)); GLDEBUG(glGenFramebuffers(1, &lightAccumulationBuffer));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightAccumulationTexture, 0)); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, lightAccumulationBuffer));
allocateShadowBuffers(); // ----- 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 // 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]) { if (shadowDepthTexture[iShadow]) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
shadowDepthTexture[iShadow] = 0; shadowDepthTexture[iShadow] = 0;
@@ -555,7 +573,7 @@ void KRCamera::allocateShadowBuffers() {
} }
// Allocate newly required buffers // Allocate newly required buffers
for(int iShadow = 0; iShadow < m_cShadowBuffers; iShadow++) { for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
if(!shadowDepthTexture[iShadow]) { if(!shadowDepthTexture[iShadow]) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
@@ -580,8 +598,7 @@ void KRCamera::allocateShadowBuffers() {
void KRCamera::destroyBuffers() void KRCamera::destroyBuffers()
{ {
m_cShadowBuffers = 0; allocateShadowBuffers(0);
allocateShadowBuffers();
if (compositeDepthTexture) { if (compositeDepthTexture) {
GLDEBUG(glDeleteTextures(1, &compositeDepthTexture)); GLDEBUG(glDeleteTextures(1, &compositeDepthTexture));

View File

@@ -52,7 +52,7 @@ class KRContext;
class KRCamera : public KRContextObject { class KRCamera : public KRContextObject {
public: public:
KRCamera(KRContext &context, GLint width, GLint height); KRCamera(KRContext &context);
virtual ~KRCamera(); virtual ~KRCamera();
GLint backingWidth, backingHeight; GLint backingWidth, backingHeight;
@@ -60,7 +60,7 @@ public:
void renderFrame(KRScene &scene, KRMat4 &viewMatrix); void renderFrame(KRScene &scene, KRMat4 &viewMatrix);
void renderShadowBuffer(KRScene &scene, int iShadow); void renderShadowBuffer(KRScene &scene, int iShadow);
void invalidateShadowBuffers(); void invalidateShadowBuffers();
void allocateShadowBuffers(); void allocateShadowBuffers(int cBuffers);
void createBuffers(); void createBuffers();
KRVector3 getPosition() const; KRVector3 getPosition() const;

View File

@@ -50,7 +50,7 @@ typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_F
@property(nonatomic, assign) KRCamera *camera; @property(nonatomic, assign) KRCamera *camera;
@property(nonatomic, retain) NSString *debug_text; @property(nonatomic, retain) NSString *debug_text;
- (id)initForWidth: (GLuint)width Height: (GLuint)height; - (id)init;
- (BOOL)loadResource:(NSString *)path; - (BOOL)loadResource:(NSString *)path;
// Parameter enumeration interface // Parameter enumeration interface

View File

@@ -51,13 +51,13 @@ using namespace std;
@synthesize debug_text = _debug_text; @synthesize debug_text = _debug_text;
double const PI = 3.141592653589793f; double const PI = 3.141592653589793f;
- (id)initForWidth: (GLuint)width Height: (GLuint)height - (id)init
{ {
_camera = NULL; _camera = NULL;
_context = NULL; _context = NULL;
if ((self = [super init])) { if ((self = [super init])) {
_context = new KRContext(); _context = new KRContext();
_camera = new KRCamera(*_context, width, height); _camera = new KRCamera(*_context);
_parameter_names = [@{ _parameter_names = [@{
@"camera_fov" : @0, @"camera_fov" : @0,
@"shadow_quality" : @1, @"shadow_quality" : @1,

View File

@@ -303,3 +303,31 @@ KRVector3 KRMat4::DotWDiv(const KRMat4 &m, const KRVector3 &v) {
r /= DotW(m, v); r /= DotW(m, v);
return r; 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;
}

View File

@@ -105,6 +105,8 @@ public:
static KRVector3 Dot(const KRMat4 &m, const KRVector3 &v); static KRVector3 Dot(const KRMat4 &m, const KRVector3 &v);
static float DotW(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 KRVector3 DotWDiv(const KRMat4 &m, const KRVector3 &v);
static KRMat4 LookAt(const KRVector3 &cameraPos, const KRVector3 &lookAtPos, const KRVector3 &upDirection);
}; };
#endif // KRMAT4_I #endif // KRMAT4_I