3D C/C++ tutorials -> OpenGL 2.1 -> Deferred rendering - FXAA
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
opengl_21_tutorials_win32_framework.h
// ----------------------------------------------------------------------------------------------------------------------------
//
// Version 2.02
//
// ----------------------------------------------------------------------------------------------------------------------------
#include <windows.h>
#include "glmath.h"
#include "string.h"
#include <gl/glew.h> // http://glew.sourceforge.net/
#include <gl/wglew.h>
#include <FreeImage.h> // http://freeimage.sourceforge.net/
// ----------------------------------------------------------------------------------------------------------------------------
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "FreeImage.lib")
// ----------------------------------------------------------------------------------------------------------------------------
extern CString ModuleDirectory, ErrorLog;
// ----------------------------------------------------------------------------------------------------------------------------
#define BUFFER_SIZE_INCREMENT 1048576
// ----------------------------------------------------------------------------------------------------------------------------
class CBuffer
{
private:
BYTE *Buffer;
int BufferSize, Position;
public:
CBuffer();
~CBuffer();
void AddData(void *Data, int DataSize);
void Empty();
void *GetData();
int GetDataSize();
private:
void SetDefaults();
};
// ----------------------------------------------------------------------------------------------------------------------------
extern int gl_max_texture_size, gl_max_texture_max_anisotropy_ext;
// ----------------------------------------------------------------------------------------------------------------------------
class CTexture
{
protected:
GLuint Texture;
public:
CTexture();
~CTexture();
operator GLuint ();
bool LoadTexture2D(char *FileName);
bool LoadTextureCubeMap(char **FileNames);
void Destroy();
protected:
FIBITMAP *CTexture::GetBitmap(char *FileName, int &Width, int &Height, int &BPP);
};
// ----------------------------------------------------------------------------------------------------------------------------
class CShaderProgram
{
protected:
GLuint VertexShader, FragmentShader, Program;
public:
GLuint *UniformLocations, *AttribLocations;
public:
CShaderProgram();
~CShaderProgram();
operator GLuint ();
bool Load(char *VertexShaderFileName, char *FragmentShaderFileName);
void Destroy();
protected:
GLuint LoadShader(char *FileName, GLenum Type);
void SetDefaults();
};
// ----------------------------------------------------------------------------------------------------------------------------
class CCamera
{
protected:
mat4x4 *ViewMatrix, *ViewMatrixInverse;
public:
vec3 X, Y, Z, Position, Reference;
CCamera();
~CCamera();
void Look(const vec3 &Position, const vec3 &Reference, bool RotateAroundReference = false);
void Move(const vec3 &Movement);
vec3 OnKeys(BYTE Keys, float FrameTime);
void OnMouseMove(int dx, int dy);
void OnMouseWheel(float zDelta);
void SetViewMatrixPointer(float *ViewMatrix, float *ViewMatrixInverse = NULL);
private:
void CalculateViewMatrix();
};
// ----------------------------------------------------------------------------------------------------------------------------
class COpenGLRenderer
{
protected:
int Width, Height;
mat3x3 NormalMatrix;
mat4x4 ModelMatrix, ViewMatrix, ProjectionMatrix, ProjectionBiasMatrixInverse;
protected:
CTexture Texture[3];
CShaderProgram Preprocess, DeferredLighting, FXAA;
GLuint ColorBuffers[2], NormalBuffer, DepthBuffer;
GLuint VBO, FBO;
public:
bool CalculateFXAA, Pause;
vec3 LightColors[4], LightPositions[4];
public:
CString Text;
public:
COpenGLRenderer();
~COpenGLRenderer();
bool Init();
void Render(float FrameTime);
void Resize(int Width, int Height);
void Destroy();
protected:
void InitArrayBuffers();
};
// ----------------------------------------------------------------------------------------------------------------------------
class COpenGLView
{
protected:
char *Title;
int Width, Height, Samples;
HWND hWnd;
HGLRC hGLRC;
protected:
int LastX, LastY;
public:
COpenGLView();
~COpenGLView();
bool Init(HINSTANCE hInstance, char *Title, int Width, int Height, int Samples);
void Show(bool Maximized = false);
void MessageLoop();
void Destroy();
void OnKeyDown(UINT Key);
void OnMouseMove(int X, int Y);
void OnMouseWheel(short zDelta);
void OnPaint();
void OnRButtonDown(int X, int Y);
void OnSize(int Width, int Height);
};
// ----------------------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
// ----------------------------------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR sCmdLine, int iShow);
opengl_21_tutorials_win32_framework.cpp
#include "opengl_21_tutorials_win32_framework.h"
// ----------------------------------------------------------------------------------------------------------------------------
CBuffer::CBuffer()
{
SetDefaults();
}
CBuffer::~CBuffer()
{
Empty();
}
void CBuffer::AddData(void *Data, int DataSize)
{
int Remaining = BufferSize - Position;
if(DataSize > Remaining)
{
BYTE *OldBuffer = Buffer;
int OldBufferSize = BufferSize;
int Needed = DataSize - Remaining;
BufferSize += Needed > BUFFER_SIZE_INCREMENT ? Needed : BUFFER_SIZE_INCREMENT;
Buffer = new BYTE[BufferSize];
memcpy(Buffer, OldBuffer, OldBufferSize);
delete [] OldBuffer;
}
memcpy(Buffer + Position, Data, DataSize);
Position += DataSize;
}
void CBuffer::Empty()
{
delete [] Buffer;
SetDefaults();
}
void *CBuffer::GetData()
{
return Buffer;
}
int CBuffer::GetDataSize()
{
return Position;
}
void CBuffer::SetDefaults()
{
Buffer = NULL;
BufferSize = 0;
Position = 0;
}
// ----------------------------------------------------------------------------------------------------------------------------
int gl_max_texture_size = 0, gl_max_texture_max_anisotropy_ext = 0;
// ----------------------------------------------------------------------------------------------------------------------------
CTexture::CTexture()
{
Texture = 0;
}
CTexture::~CTexture()
{
}
CTexture::operator GLuint ()
{
return Texture;
}
bool CTexture::LoadTexture2D(char *FileName)
{
CString DirectoryFileName = ModuleDirectory + FileName;
int Width, Height, BPP;
FIBITMAP *dib = GetBitmap(DirectoryFileName, Width, Height, BPP);
if(dib == NULL)
{
ErrorLog.Append("Error loading texture " + DirectoryFileName + "!\r\n");
return false;
}
GLenum Format = 0;
if(BPP == 32) Format = GL_BGRA;
if(BPP == 24) Format = GL_BGR;
if(Format == 0)
{
ErrorLog.Append("Unsupported texture format (%s)!\r\n", FileName);
FreeImage_Unload(dib);
return false;
}
Destroy();
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(GLEW_EXT_texture_filter_anisotropic)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_max_texture_max_anisotropy_ext);
}
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, Format, GL_UNSIGNED_BYTE, FreeImage_GetBits(dib));
glBindTexture(GL_TEXTURE_2D, 0);
FreeImage_Unload(dib);
return true;
}
bool CTexture::LoadTextureCubeMap(char **FileNames)
{
int Width, Height, BPP;
FIBITMAP *dib[6];
bool Error = false;
for(int i = 0; i < 6; i++)
{
CString DirectoryFileName = ModuleDirectory + FileNames[i];
dib[i] = GetBitmap(DirectoryFileName, Width, Height, BPP);
if(dib[i] == NULL)
{
ErrorLog.Append("Error loading texture " + DirectoryFileName + "!\r\n");
Error = true;
}
}
if(Error)
{
for(int i = 0; i < 6; i++)
{
FreeImage_Unload(dib[i]);
}
return false;
}
GLenum Format = 0;
if(BPP == 32) Format = GL_BGRA;
if(BPP == 24) Format = GL_BGR;
if(Format == 0)
{
ErrorLog.Append("Unsupported texture format (%s)!\r\n", FileNames[5]);
for(int i = 0; i < 6; i++)
{
FreeImage_Unload(dib[i]);
}
return false;
}
Destroy();
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, Texture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(GLEW_EXT_texture_filter_anisotropic)
{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_max_texture_max_anisotropy_ext);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE);
for(int i = 0; i < 6; i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, Width, Height, 0, Format, GL_UNSIGNED_BYTE, FreeImage_GetBits(dib[i]));
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
for(int i = 0; i < 6; i++)
{
FreeImage_Unload(dib[i]);
}
return true;
}
void CTexture::Destroy()
{
glDeleteTextures(1, &Texture);
Texture = 0;
}
FIBITMAP *CTexture::GetBitmap(char *FileName, int &Width, int &Height, int &BPP)
{
FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(FileName);
if(fif == FIF_UNKNOWN)
{
fif = FreeImage_GetFIFFromFilename(FileName);
}
if(fif == FIF_UNKNOWN)
{
return NULL;
}
FIBITMAP *dib = NULL;
if(FreeImage_FIFSupportsReading(fif))
{
dib = FreeImage_Load(fif, FileName);
}
if(dib != NULL)
{
int OriginalWidth = FreeImage_GetWidth(dib);
int OriginalHeight = FreeImage_GetHeight(dib);
Width = OriginalWidth;
Height = OriginalHeight;
if(Width == 0 || Height == 0)
{
FreeImage_Unload(dib);
return NULL;
}
BPP = FreeImage_GetBPP(dib);
if(Width > gl_max_texture_size) Width = gl_max_texture_size;
if(Height > gl_max_texture_size) Height = gl_max_texture_size;
if(!GLEW_ARB_texture_non_power_of_two)
{
Width = 1 << (int)floor((log((float)Width) / log(2.0f)) + 0.5f);
Height = 1 << (int)floor((log((float)Height) / log(2.0f)) + 0.5f);
}
if(Width != OriginalWidth || Height != OriginalHeight)
{
FIBITMAP *rdib = FreeImage_Rescale(dib, Width, Height, FILTER_BICUBIC);
FreeImage_Unload(dib);
dib = rdib;
}
}
return dib;
}
// ----------------------------------------------------------------------------------------------------------------------------
CShaderProgram::CShaderProgram()
{
SetDefaults();
}
CShaderProgram::~CShaderProgram()
{
}
CShaderProgram::operator GLuint ()
{
return Program;
}
bool CShaderProgram::Load(char *VertexShaderFileName, char *FragmentShaderFileName)
{
bool Error = false;
Destroy();
Error |= ((VertexShader = LoadShader(VertexShaderFileName, GL_VERTEX_SHADER)) == 0);
Error |= ((FragmentShader = LoadShader(FragmentShaderFileName, GL_FRAGMENT_SHADER)) == 0);
if(Error)
{
Destroy();
return false;
}
Program = glCreateProgram();
glAttachShader(Program, VertexShader);
glAttachShader(Program, FragmentShader);
glLinkProgram(Program);
int LinkStatus;
glGetProgramiv(Program, GL_LINK_STATUS, &LinkStatus);
if(LinkStatus == GL_FALSE)
{
ErrorLog.Append("Error linking program (%s, %s)!\r\n", VertexShaderFileName, FragmentShaderFileName);
int InfoLogLength = 0;
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength > 0)
{
char *InfoLog = new char[InfoLogLength];
int CharsWritten = 0;
glGetProgramInfoLog(Program, InfoLogLength, &CharsWritten, InfoLog);
ErrorLog.Append(InfoLog);
delete [] InfoLog;
}
Destroy();
return false;
}
return true;
}
void CShaderProgram::Destroy()
{
glDetachShader(Program, VertexShader);
glDetachShader(Program, FragmentShader);
glDeleteShader(VertexShader);
glDeleteShader(FragmentShader);
glDeleteProgram(Program);
delete [] UniformLocations;
delete [] AttribLocations;
SetDefaults();
}
GLuint CShaderProgram::LoadShader(char *FileName, GLenum Type)
{
CString DirectoryFileName = ModuleDirectory + FileName;
FILE *File;
if(fopen_s(&File, DirectoryFileName, "rb") != 0)
{
ErrorLog.Append("Error loading file " + DirectoryFileName + "!\r\n");
return 0;
}
fseek(File, 0, SEEK_END);
long Size = ftell(File);
fseek(File, 0, SEEK_SET);
char *Source = new char[Size + 1];
fread(Source, 1, Size, File);
fclose(File);
Source[Size] = 0;
GLuint Shader = glCreateShader(Type);
glShaderSource(Shader, 1, (const char**)&Source, NULL);
delete [] Source;
glCompileShader(Shader);
int CompileStatus;
glGetShaderiv(Shader, GL_COMPILE_STATUS, &CompileStatus);
if(CompileStatus == GL_FALSE)
{
ErrorLog.Append("Error compiling shader %s!\r\n", FileName);
int InfoLogLength = 0;
glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &InfoLogLength);
if(InfoLogLength > 0)
{
char *InfoLog = new char[InfoLogLength];
int CharsWritten = 0;
glGetShaderInfoLog(Shader, InfoLogLength, &CharsWritten, InfoLog);
ErrorLog.Append(InfoLog);
delete [] InfoLog;
}
glDeleteShader(Shader);
return 0;
}
return Shader;
}
void CShaderProgram::SetDefaults()
{
VertexShader = 0;
FragmentShader = 0;
Program = 0;
UniformLocations = NULL;
AttribLocations = NULL;
}
// ----------------------------------------------------------------------------------------------------------------------------
CCamera::CCamera()
{
ViewMatrix = NULL;
ViewMatrixInverse = NULL;
X = vec3(1.0f, 0.0f, 0.0f);
Y = vec3(0.0f, 1.0f, 0.0f);
Z = vec3(0.0f, 0.0f, 1.0f);
Position = vec3(0.0f, 0.0f, 5.0f);
Reference = vec3(0.0f, 0.0f, 0.0f);
}
CCamera::~CCamera()
{
}
void CCamera::Look(const vec3 &Position, const vec3 &Reference, bool RotateAroundReference)
{
this->Position = Position;
this->Reference = Reference;
Z = normalize(Position - Reference);
X = normalize(cross(vec3(0.0f, 1.0f, 0.0f), Z));
Y = cross(Z, X);
if(!RotateAroundReference)
{
this->Reference = this->Position;
this->Position += Z * 0.05f;
}
CalculateViewMatrix();
}
void CCamera::Move(const vec3 &Movement)
{
Position += Movement;
Reference += Movement;
CalculateViewMatrix();
}
vec3 CCamera::OnKeys(BYTE Keys, float FrameTime)
{
float Speed = 5.0f;
if(Keys & 0x40) Speed *= 2.0f;
if(Keys & 0x80) Speed *= 0.5f;
float Distance = Speed * FrameTime;
vec3 Up(0.0f, 1.0f, 0.0f);
vec3 Right = X;
vec3 Forward = cross(Up, Right);
Up *= Distance;
Right *= Distance;
Forward *= Distance;
vec3 Movement;
if(Keys & 0x01) Movement += Forward;
if(Keys & 0x02) Movement -= Forward;
if(Keys & 0x04) Movement -= Right;
if(Keys & 0x08) Movement += Right;
if(Keys & 0x10) Movement += Up;
if(Keys & 0x20) Movement -= Up;
return Movement;
}
void CCamera::OnMouseMove(int dx, int dy)
{
float Sensitivity = 0.25f;
Position -= Reference;
if(dx != 0)
{
float DeltaX = (float)dx * Sensitivity;
X = rotate(X, DeltaX, vec3(0.0f, 1.0f, 0.0f));
Y = rotate(Y, DeltaX, vec3(0.0f, 1.0f, 0.0f));
Z = rotate(Z, DeltaX, vec3(0.0f, 1.0f, 0.0f));
}
if(dy != 0)
{
float DeltaY = (float)dy * Sensitivity;
Y = rotate(Y, DeltaY, X);
Z = rotate(Z, DeltaY, X);
if(Y.y < 0.0f)
{
Z = vec3(0.0f, Z.y > 0.0f ? 1.0f : -1.0f, 0.0f);
Y = cross(Z, X);
}
}
Position = Reference + Z * length(Position);
CalculateViewMatrix();
}
void CCamera::OnMouseWheel(float zDelta)
{
Position -= Reference;
if(zDelta < 0 && length(Position) < 500.0f)
{
Position += Position * 0.1f;
}
if(zDelta > 0 && length(Position) > 0.05f)
{
Position -= Position * 0.1f;
}
Position += Reference;
CalculateViewMatrix();
}
void CCamera::SetViewMatrixPointer(float *ViewMatrix, float *ViewMatrixInverse)
{
this->ViewMatrix = (mat4x4*)ViewMatrix;
this->ViewMatrixInverse = (mat4x4*)ViewMatrixInverse;
CalculateViewMatrix();
}
void CCamera::CalculateViewMatrix()
{
if(ViewMatrix != NULL)
{
*ViewMatrix = mat4x4(X.x, Y.x, Z.x, 0.0f, X.y, Y.y, Z.y, 0.0f, X.z, Y.z, Z.z, 0.0f, -dot(X, Position), -dot(Y, Position), -dot(Z, Position), 1.0f);
if(ViewMatrixInverse != NULL)
{
*ViewMatrixInverse = inverse(*ViewMatrix);
}
}
}
// ----------------------------------------------------------------------------------------------------------------------------
CCamera Camera;
// ----------------------------------------------------------------------------------------------------------------------------
COpenGLRenderer::COpenGLRenderer()
{
CalculateFXAA = true;
Pause = false;
Camera.SetViewMatrixPointer(&ViewMatrix);
}
COpenGLRenderer::~COpenGLRenderer()
{
}
bool COpenGLRenderer::Init()
{
// ------------------------------------------------------------------------------------------------------------------------
bool Error = false;
// ------------------------------------------------------------------------------------------------------------------------
if(!GLEW_ARB_texture_non_power_of_two)
{
ErrorLog.Append("GL_ARB_texture_non_power_of_two not supported!\r\n");
Error = true;
}
if(!GLEW_ARB_depth_texture)
{
ErrorLog.Append("GLEW_ARB_depth_texture not supported!\r\n");
Error = true;
}
if(!GLEW_EXT_framebuffer_object)
{
ErrorLog.Append("GL_EXT_framebuffer_object not supported!\r\n");
Error = true;
}
// ------------------------------------------------------------------------------------------------------------------------
char *TextureFileName[] = {"cube.jpg", "floor.jpg", "wall.jpg"};
for(int i = 0; i < 3; i++)
{
Error |= !Texture[i].LoadTexture2D(TextureFileName[i]);
}
// ------------------------------------------------------------------------------------------------------------------------
Error |= !Preprocess.Load("preprocess.vs", "preprocess.fs");
Error |= !DeferredLighting.Load("deferredlighting.vs", "deferredlighting.fs");
Error |= !FXAA.Load("FXAA.vert", "FXAA_Extreme_Quality.frag");
// ------------------------------------------------------------------------------------------------------------------------
if(Error)
{
return false;
}
// ------------------------------------------------------------------------------------------------------------------------
Preprocess.UniformLocations = new GLuint[1];
Preprocess.UniformLocations[0] = glGetUniformLocation(Preprocess, "Texturing");
DeferredLighting.UniformLocations = new GLuint[1];
DeferredLighting.UniformLocations[0] = glGetUniformLocation(DeferredLighting, "ProjectionBiasMatrixInverse");
FXAA.UniformLocations = new GLuint[1];
FXAA.UniformLocations[0] = glGetUniformLocation(FXAA, "RCPFrame");
// ------------------------------------------------------------------------------------------------------------------------
glUseProgram(DeferredLighting);
glUniform1i(glGetUniformLocation(DeferredLighting, "ColorBuffer"), 0);
glUniform1i(glGetUniformLocation(DeferredLighting, "NormalBuffer"), 1);
glUniform1i(glGetUniformLocation(DeferredLighting, "DepthBuffer"), 2);
glUseProgram(0);
// ------------------------------------------------------------------------------------------------------------------------
glGenTextures(2, ColorBuffers);
glGenTextures(1, &NormalBuffer);
glGenTextures(1, &DepthBuffer);
// ------------------------------------------------------------------------------------------------------------------------
glGenBuffers(1, &VBO);
InitArrayBuffers();
// ------------------------------------------------------------------------------------------------------------------------
glGenFramebuffersEXT(1, &FBO);
// ------------------------------------------------------------------------------------------------------------------------
LightColors[0] = vec3(1.0f, 0.0f, 0.0f);
LightPositions[0] = vec3(0.0f, 1.5f, 0.33f);
LightColors[1] = vec3(0.0f, 1.0f, 0.0f);
LightPositions[1] = rotate(LightPositions[0], 120.0f, vec3(0.0f, 1.0f, 0.0f));
LightColors[2] = vec3(0.0f, 0.0f, 1.0f);
LightPositions[2] = rotate(LightPositions[1], 120.0f, vec3(0.0f, 1.0f, 0.0f));
LightColors[3] = vec3(1.0f, 1.0f, 1.0f);
LightPositions[3] = vec3(0.0f, 2.75f, -4.75f);
for(int i = 0; i < 3; i++)
{
glLightfv(GL_LIGHT0 + i, GL_AMBIENT, &vec4(LightColors[i] * 0.125f, 1.0f));
glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, &vec4(LightColors[i] * 0.875f, 1.0f));
glLightf(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, 1.0f);
glLightf(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, 1.0f);
}
glLightfv(GL_LIGHT3, GL_AMBIENT, &vec4(LightColors[3] * 0.25f, 1.0f));
glLightfv(GL_LIGHT3, GL_DIFFUSE, &vec4(LightColors[3] * 0.75f, 1.0f));
glLightf(GL_LIGHT3, GL_LINEAR_ATTENUATION, 1.0f / 32.0f);
glLightf(GL_LIGHT3, GL_QUADRATIC_ATTENUATION, 1.0f / 64.0f);
// ------------------------------------------------------------------------------------------------------------------------
Camera.Look(vec3(0.0f, 1.75f, 1.875f), vec3(0.0f, 1.5f, 0.0f));
// ------------------------------------------------------------------------------------------------------------------------
return true;
// ------------------------------------------------------------------------------------------------------------------------
}
void COpenGLRenderer::Render(float FrameTime)
{
// ------------------------------------------------------------------------------------------------------------------------
GLenum Buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
// render scene to textures -----------------------------------------------------------------------------------------------
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
glDrawBuffers(2, Buffers); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ColorBuffers[0], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, NormalBuffer, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, DepthBuffer, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&ViewMatrix);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 32, (void*)0);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 32, (void*)8);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 32, (void*)20);
glUseProgram(Preprocess);
glUniform1i(Preprocess.UniformLocations[0], true);
glColor3f(1.0f, 1.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, Texture[0]);
glDrawArrays(GL_QUADS, 0, 96);
glBindTexture(GL_TEXTURE_2D, Texture[1]);
glDrawArrays(GL_QUADS, 96, 4);
glBindTexture(GL_TEXTURE_2D, Texture[2]);
glDrawArrays(GL_QUADS, 100, 80);
glBindTexture(GL_TEXTURE_2D, 0);
glUniform1i(Preprocess.UniformLocations[0], false);
glDrawArrays(GL_QUADS, 180, 4);
glMultMatrixf(&ModelMatrix);
glColor3f(0.33f, 0.66f, 1.0f);
glDrawArrays(GL_QUADS, 184, 72);
glUseProgram(0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// set lights positions ------------------------------------------------------------------------------------------------------------------------
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&ViewMatrix);
for(int i = 0; i < 4; i++)
{
glLightfv(GL_LIGHT0 + i, GL_POSITION, &vec4(LightPositions[i], 1.0f));
}
// calculate lighting -----------------------------------------------------------------------------------------------------
if(CalculateFXAA)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBO);
glDrawBuffers(1, Buffers); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ColorBuffers[1], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, 0, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0);
}
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ColorBuffers[0]);
glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, NormalBuffer);
glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, DepthBuffer);
glUseProgram(DeferredLighting);
glBegin(GL_QUADS);
glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 0.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glEnd();
glUseProgram(0);
glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0);
if(CalculateFXAA)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
// calculate antialiasing -------------------------------------------------------------------------------------------------
if(CalculateFXAA)
{
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ColorBuffers[1]);
glUseProgram(FXAA);
glBegin(GL_QUADS);
glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 0.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(0.0f, 1.0f);
glEnd();
glUseProgram(0);
glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0);
}
// rotate object and lights -----------------------------------------------------------------------------------------------
if(!Pause)
{
static float a = 0.0f;
ModelMatrix = translate(0.0f, 1.5f, 0.0f) * rotate(a, vec3(0.0f, 1.0f, 0.0f)) * rotate(a, vec3(1.0f, 0.0f, 0.0f));
a += 22.5f * FrameTime;
for(int i = 0; i < 3; i++)
{
LightPositions[i] = rotate(LightPositions[i], -180.0f * FrameTime, vec3(0.0f, 1.0f, 0.0f));
}
}
// ------------------------------------------------------------------------------------------------------------------------
}
void COpenGLRenderer::Resize(int Width, int Height)
{
this->Width = Width;
this->Height = Height;
glViewport(0, 0, Width, Height);
ProjectionMatrix = perspective(45.0f, (float)Width / (float)Height, 0.125f, 512.0f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&ProjectionMatrix);
ProjectionBiasMatrixInverse = inverse(ProjectionMatrix) * BiasMatrixInverse;
glBindTexture(GL_TEXTURE_2D, ColorBuffers[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, ColorBuffers[1]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, NormalBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, DepthBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, Width, Height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(DeferredLighting);
glUniformMatrix4fv(DeferredLighting.UniformLocations[0], 1, GL_FALSE, &ProjectionBiasMatrixInverse);
glUseProgram(0);
glUseProgram(FXAA);
glUniform2f(FXAA.UniformLocations[0], 1.0f / (float)Width, 1.0f / (float)Height);
glUseProgram(0);
}
void COpenGLRenderer::Destroy()
{
for(int i = 0; i < 3; i++)
{
Texture[i].Destroy();
}
Preprocess.Destroy();
DeferredLighting.Destroy();
FXAA.Destroy();
glDeleteBuffers(1, &VBO);
glDeleteTextures(2, ColorBuffers);
glDeleteTextures(1, &NormalBuffer);
glDeleteTextures(1, &DepthBuffer);
if(GLEW_EXT_framebuffer_object)
{
glDeleteFramebuffersEXT(1, &FBO);
}
}
void COpenGLRenderer::InitArrayBuffers()
{
CBuffer buffer;
vec3 m;
// cubes
m = vec3( 0.0f, 0.5f, 0.0f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
m = vec3( 0.0f, 1.5f,-4.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
m = vec3(-0.625f, 0.5f,-4.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
m = vec3( 0.625f, 0.5f,-4.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x,-0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.5f + m.y, 0.5f + m.z), 12);
// floor
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3(0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 10.0f), 8); buffer.AddData(&vec3(0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f, -5.0f), 12);
buffer.AddData(&vec2( 0.0f, 10.0f), 8); buffer.AddData(&vec3(0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f, -5.0f), 12);
// walls
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f, 5.0f), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f,-5.0f), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f,-5.0f), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f, 5.0f), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, -1.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, -1.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f, 5.0f), 12);
buffer.AddData(&vec2(10.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, -1.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f, 5.0f), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, -1.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f, 5.0f), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-5.0f, 0.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 5.0f, 0.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f,-5.0f), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f,-5.0f), 12);
// pillars
m = vec3(-2.5f, 0.0f,-2.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
m = vec3( 2.5f, 0.0f,-2.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
m = vec3( 2.5f, 0.0f, 2.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
m = vec3(-2.5f, 0.0f, 2.5f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f,-0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 0.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.5f + m.x, 3.0f, 0.5f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 3.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.5f + m.x, 3.0f, 0.5f + m.z), 12);
// ceiling
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(0.0f, -1.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 0.0f), 8); buffer.AddData(&vec3(0.0f, -1.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f,-5.0f), 12);
buffer.AddData(&vec2(10.0f, 10.0f), 8); buffer.AddData(&vec3(0.0f, -1.0f, 0.0f), 12); buffer.AddData(&vec3( 5.0f, 3.0f, 5.0f), 12);
buffer.AddData(&vec2( 0.0f, 10.0f), 8); buffer.AddData(&vec3(0.0f, -1.0f, 0.0f), 12); buffer.AddData(&vec3(-5.0f, 3.0f, 5.0f), 12);
// rotating object
m = vec3(0.0f);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.25f + m.x,-0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.25f + m.x, 0.025f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y,-0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.25f + m.y, 0.025f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3(-1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 1.0f, 0.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f,-1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 1.0f, 0.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f,-1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y,-0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 0.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x,-0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 1.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3( 0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
buffer.AddData(&vec2( 0.0f, 1.0f), 8); buffer.AddData(&vec3( 0.0f, 0.0f, 1.0f), 12); buffer.AddData(&vec3(-0.025f + m.x, 0.025f + m.y, 0.25f + m.z), 12);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, buffer.GetDataSize(), buffer.GetData(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
buffer.Empty();
}
// ----------------------------------------------------------------------------------------------------------------------------
COpenGLRenderer OpenGLRenderer;
// ----------------------------------------------------------------------------------------------------------------------------
CString ModuleDirectory, ErrorLog;
// ----------------------------------------------------------------------------------------------------------------------------
void GetModuleDirectory()
{
char *moduledirectory = new char[256];
GetModuleFileName(GetModuleHandle(NULL), moduledirectory, 256);
*(strrchr(moduledirectory, '\\') + 1) = 0;
ModuleDirectory = moduledirectory;
delete [] moduledirectory;
}
// ----------------------------------------------------------------------------------------------------------------------------
COpenGLView::COpenGLView()
{
}
COpenGLView::~COpenGLView()
{
}
bool COpenGLView::Init(HINSTANCE hInstance, char *Title, int Width, int Height, int Samples)
{
this->Title = Title;
this->Width = Width;
this->Height = Height;
WNDCLASSEX WndClassEx;
memset(&WndClassEx, 0, sizeof(WNDCLASSEX));
WndClassEx.cbSize = sizeof(WNDCLASSEX);
WndClassEx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WndClassEx.lpfnWndProc = WndProc;
WndClassEx.hInstance = hInstance;
WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClassEx.lpszClassName = "Win32OpenGLWindowClass";
if(RegisterClassEx(&WndClassEx) == 0)
{
ErrorLog.Set("RegisterClassEx failed!");
return false;
}
DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
hWnd = CreateWindowEx(WS_EX_APPWINDOW, WndClassEx.lpszClassName, Title, Style, 0, 0, Width, Height, NULL, NULL, hInstance, NULL);
if(hWnd == NULL)
{
ErrorLog.Set("CreateWindowEx failed!");
return false;
}
HDC hDC = GetDC(hWnd);
if(hDC == NULL)
{
ErrorLog.Set("GetDC failed!");
return false;
}
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
int PixelFormat = ChoosePixelFormat(hDC, &pfd);
if(PixelFormat == 0)
{
ErrorLog.Set("ChoosePixelFormat failed!");
return false;
}
static int MSAAPixelFormat = 0;
if(SetPixelFormat(hDC, MSAAPixelFormat == 0 ? PixelFormat : MSAAPixelFormat, &pfd) == FALSE)
{
ErrorLog.Set("SetPixelFormat failed!");
return false;
}
hGLRC = wglCreateContext(hDC);
if(hGLRC == NULL)
{
ErrorLog.Set("wglCreateContext failed!");
return false;
}
if(wglMakeCurrent(hDC, hGLRC) == FALSE)
{
ErrorLog.Set("wglMakeCurrent failed!");
return false;
}
if(glewInit() != GLEW_OK)
{
ErrorLog.Set("glewInit failed!");
return false;
}
if(!GLEW_VERSION_2_1)
{
ErrorLog.Set("OpenGL 2.1 not supported!");
return false;
}
if(MSAAPixelFormat == 0 && Samples > 0)
{
if(GLEW_ARB_multisample && WGLEW_ARB_pixel_format)
{
while(Samples > 0)
{
UINT NumFormats = 0;
int PFAttribs[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, Samples,
0
};
if(wglChoosePixelFormatARB(hDC, PFAttribs, NULL, 1, &MSAAPixelFormat, &NumFormats) == TRUE && NumFormats > 0) break;
Samples--;
}
wglDeleteContext(hGLRC);
DestroyWindow(hWnd);
UnregisterClass(WndClassEx.lpszClassName, hInstance);
return Init(hInstance, Title, Width, Height, Samples);
}
else
{
Samples = 0;
}
}
this->Samples = Samples;
GetModuleDirectory();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max_texture_size);
if(GLEW_EXT_texture_filter_anisotropic)
{
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_texture_max_anisotropy_ext);
}
if(WGLEW_EXT_swap_control)
{
wglSwapIntervalEXT(0);
}
return OpenGLRenderer.Init();
}
void COpenGLView::Show(bool Maximized)
{
RECT dRect, wRect, cRect;
GetWindowRect(GetDesktopWindow(), &dRect);
GetWindowRect(hWnd, &wRect);
GetClientRect(hWnd, &cRect);
wRect.right += Width - cRect.right;
wRect.bottom += Height - cRect.bottom;
wRect.right -= wRect.left;
wRect.bottom -= wRect.top;
wRect.left = dRect.right / 2 - wRect.right / 2;
wRect.top = dRect.bottom / 2 - wRect.bottom / 2;
MoveWindow(hWnd, wRect.left, wRect.top, wRect.right, wRect.bottom, FALSE);
ShowWindow(hWnd, Maximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
}
void COpenGLView::MessageLoop()
{
MSG Msg;
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
void COpenGLView::Destroy()
{
if(GLEW_VERSION_2_1)
{
OpenGLRenderer.Destroy();
}
wglDeleteContext(hGLRC);
DestroyWindow(hWnd);
}
void COpenGLView::OnKeyDown(UINT Key)
{
switch(Key)
{
case VK_F1:
OpenGLRenderer.CalculateFXAA = !OpenGLRenderer.CalculateFXAA;
break;
case VK_SPACE:
OpenGLRenderer.Pause = !OpenGLRenderer.Pause;
break;
}
}
void COpenGLView::OnMouseMove(int X, int Y)
{
if(GetKeyState(VK_RBUTTON) & 0x80)
{
Camera.OnMouseMove(LastX - X, LastY - Y);
LastX = X;
LastY = Y;
}
}
void COpenGLView::OnMouseWheel(short zDelta)
{
Camera.OnMouseWheel(zDelta);
}
void COpenGLView::OnPaint()
{
static DWORD LastFPSTime = GetTickCount(), LastFrameTime = LastFPSTime, FPS = 0;
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
DWORD Time = GetTickCount();
float FrameTime = (Time - LastFrameTime) * 0.001f;
LastFrameTime = Time;
if(Time - LastFPSTime > 1000)
{
CString Text = Title;
if(OpenGLRenderer.Text[0] != 0)
{
Text.Append(" - " + OpenGLRenderer.Text);
}
Text.Append(" - %dx%d", Width, Height);
Text.Append(", ATF %dx", gl_max_texture_max_anisotropy_ext);
Text.Append(", MSAA %dx", Samples);
Text.Append(", FPS: %d", FPS);
Text.Append(" - %s", glGetString(GL_RENDERER));
SetWindowText(hWnd, Text);
LastFPSTime = Time;
FPS = 0;
}
else
{
FPS++;
}
BYTE Keys = 0x00;
if(GetKeyState('W') & 0x80) Keys |= 0x01;
if(GetKeyState('S') & 0x80) Keys |= 0x02;
if(GetKeyState('A') & 0x80) Keys |= 0x04;
if(GetKeyState('D') & 0x80) Keys |= 0x08;
if(GetKeyState('R') & 0x80) Keys |= 0x10;
if(GetKeyState('F') & 0x80) Keys |= 0x20;
if(GetKeyState(VK_SHIFT) & 0x80) Keys |= 0x40;
if(GetKeyState(VK_CONTROL) & 0x80) Keys |= 0x80;
float MinD = 0.25f;
if(Keys & 0x3F)
{
vec3 Movement = Camera.OnKeys(Keys, FrameTime);
if(Camera.Reference.x + Movement.x < -5.0f + MinD) Movement.x -= Camera.Reference.x + Movement.x - (-5.0f + MinD);
if(Camera.Reference.x + Movement.x > 5.0f - MinD) Movement.x -= Camera.Reference.x + Movement.x - ( 5.0f - MinD);
if(Camera.Reference.y + Movement.y < 0.0f + MinD) Movement.y -= Camera.Reference.y + Movement.y - ( 0.0f + MinD);
if(Camera.Reference.y + Movement.y > 3.0f - MinD) Movement.y -= Camera.Reference.y + Movement.y - ( 3.0f - MinD);
if(Camera.Reference.z + Movement.z < -5.0f + MinD) Movement.z -= Camera.Reference.z + Movement.z - (-5.0f + MinD);
if(Camera.Reference.z + Movement.z > 5.0f - MinD) Movement.z -= Camera.Reference.z + Movement.z - ( 5.0f - MinD);
Camera.Move(Movement);
}
if(GetKeyState(VK_NUMPAD4) & 0x80) OpenGLRenderer.LightPositions[3].x -= FrameTime;
if(GetKeyState(VK_NUMPAD6) & 0x80) OpenGLRenderer.LightPositions[3].x += FrameTime;
if(GetKeyState(VK_NUMPAD2) & 0x80) OpenGLRenderer.LightPositions[3].y -= FrameTime;
if(GetKeyState(VK_NUMPAD8) & 0x80) OpenGLRenderer.LightPositions[3].y += FrameTime;
if(GetKeyState(VK_NUMPAD9) & 0x80) OpenGLRenderer.LightPositions[3].z -= FrameTime;
if(GetKeyState(VK_NUMPAD1) & 0x80) OpenGLRenderer.LightPositions[3].z += FrameTime;
if(OpenGLRenderer.LightPositions[3].x < -5.0f + MinD) OpenGLRenderer.LightPositions[3].x = -5.0f + MinD;
if(OpenGLRenderer.LightPositions[3].x > 5.0f - MinD) OpenGLRenderer.LightPositions[3].x = 5.0f - MinD;
if(OpenGLRenderer.LightPositions[3].y < 0.0f + MinD) OpenGLRenderer.LightPositions[3].y = 0.0f + MinD;
if(OpenGLRenderer.LightPositions[3].y > 3.0f - MinD) OpenGLRenderer.LightPositions[3].y = 3.0f - MinD;
if(OpenGLRenderer.LightPositions[3].z < -5.0f + MinD) OpenGLRenderer.LightPositions[3].z = -5.0f + MinD;
if(OpenGLRenderer.LightPositions[3].z > 5.0f - MinD) OpenGLRenderer.LightPositions[3].z = 5.0f - MinD;
if(GetKeyState(VK_NUMPAD5) & 0x80) OpenGLRenderer.LightPositions[3] = vec3(0.0f, 2.75f, 0.0f);
OpenGLRenderer.Render(FrameTime);
SwapBuffers(hDC);
EndPaint(hWnd, &ps);
InvalidateRect(hWnd, NULL, FALSE);
}
void COpenGLView::OnRButtonDown(int X, int Y)
{
LastX = X;
LastY = Y;
}
void COpenGLView::OnSize(int Width, int Height)
{
this->Width = Width;
this->Height = Height;
OpenGLRenderer.Resize(Width, Height);
}
// ----------------------------------------------------------------------------------------------------------------------------
COpenGLView OpenGLView;
// ----------------------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
case WM_MOUSEMOVE:
OpenGLView.OnMouseMove(LOWORD(lParam), HIWORD(lParam));
break;
case 0x020A: // WM_MOUSWHEEL
OpenGLView.OnMouseWheel(HIWORD(wParam));
break;
case WM_KEYDOWN:
OpenGLView.OnKeyDown((UINT)wParam);
break;
case WM_PAINT:
OpenGLView.OnPaint();
break;
case WM_RBUTTONDOWN:
OpenGLView.OnRButtonDown(LOWORD(lParam), HIWORD(lParam));
break;
case WM_SIZE:
OpenGLView.OnSize(LOWORD(lParam), HIWORD(lParam));
break;
default:
return DefWindowProc(hWnd, uiMsg, wParam, lParam);
}
return 0;
}
// ----------------------------------------------------------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR sCmdLine, int iShow)
{
char *AppName = "Deferred rendering - FXAA";
if(OpenGLView.Init(hInstance, AppName, 800, 600, 0))
{
OpenGLView.Show();
OpenGLView.MessageLoop();
}
else
{
MessageBox(NULL, ErrorLog, AppName, MB_OK | MB_ICONERROR);
}
OpenGLView.Destroy();
return 0;
}
preprocess.vs
#version 120
varying vec3 Normal;
void main()
{
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
Normal = gl_NormalMatrix * gl_Normal;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
preprocess.fs
#version 120
uniform sampler2D Texture;
uniform bool Texturing;
varying vec3 Normal;
void main()
{
gl_FragData[0] = gl_Color;
if(Texturing) gl_FragData[0] *= texture2D(Texture, gl_TexCoord[0].st);
gl_FragData[1] = vec4(normalize(Normal) * 0.5 + 0.5, 1.0);
}
deferredlighting.vs
#version 120
void main()
{
gl_TexCoord[0] = gl_Vertex;
gl_Position = gl_Vertex * 2.0 - 1.0;
}
deferredlighting.fs
#version 120
uniform sampler2D ColorBuffer, NormalBuffer, DepthBuffer;
uniform mat4x4 ProjectionBiasMatrixInverse;
void main()
{
gl_FragColor = texture2D(ColorBuffer, gl_TexCoord[0].st);
float Depth = texture2D(DepthBuffer, gl_TexCoord[0].st).r;
if(Depth < 1.0)
{
vec3 Normal = normalize(texture2D(NormalBuffer, gl_TexCoord[0].st).rgb * 2.0 - 1.0);
vec4 Position = ProjectionBiasMatrixInverse * vec4(gl_TexCoord[0].st, Depth, 1.0);
Position /= Position.w;
vec3 Light = vec3(0.0);
for(int i = 0; i < 4; i++)
{
vec3 LightDirection = gl_LightSource[i].position.xyz - Position.xyz;
float LightDistance2 = dot(LightDirection, LightDirection);
float LightDistance = sqrt(LightDistance2);
LightDirection /= LightDistance;
float NdotLD = max(dot(Normal, LightDirection), 0.0);
float Attenuation = gl_LightSource[i].constantAttenuation;
Attenuation += gl_LightSource[i].linearAttenuation * LightDistance;
Attenuation += gl_LightSource[i].quadraticAttenuation * LightDistance2;
Light += (gl_LightSource[i].ambient.rgb + gl_LightSource[i].diffuse.rgb * NdotLD) / Attenuation;
}
gl_FragColor.rgb *= Light;
}
}
Download
|