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

View File

@@ -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;

View File

@@ -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

View File

@@ -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,

View File

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

View File

@@ -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