#include <string>#include <vector>#include <stack>#include <math.h>#include <stdio.h>#include <sstream>#include <memory>#include <glimg/glimg.h>#include <glimg/TextureGenerator.h>#include <glload/gl_3_3.h>#include <GL/freeglut.h>#include "../framework/framework.h"#include "../framework/Mesh.h"#include "../framework/MatrixStack.h"#include "../framework/MousePole.h"#include "../framework/ObjectPole.h"#include "../framework/Timer.h"#include "../framework/UniformBlockArray.h"#include "../framework/directories.h"#include <glm/glm.hpp>#include <glm/gtc/type_ptr.hpp>#include <glm/gtc/matrix_transform.hpp>#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))structProgramData{GLuinttheProgram;GLuintmodelToCameraMatrixUnif;};floatg_fzNear=1.0f;floatg_fzFar=1000.0f;ProgramDatag_program;constintg_projectionBlockIndex=0;constintg_colorTexUnit=0;ProgramDataLoadProgram(conststd::string&strVertexShader,conststd::string&strFragmentShader){std::vector<GLuint>shaderList;shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER,strVertexShader));shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER,strFragmentShader));ProgramDatadata;data.theProgram=Framework::CreateProgram(shaderList);data.modelToCameraMatrixUnif=glGetUniformLocation(data.theProgram,"modelToCameraMatrix");GLuintprojectionBlock=glGetUniformBlockIndex(data.theProgram,"Projection");glUniformBlockBinding(data.theProgram,projectionBlock,g_projectionBlockIndex);GLuintcolorTextureUnif=glGetUniformLocation(data.theProgram,"colorTexture");glUseProgram(data.theProgram);glUniform1i(colorTextureUnif,g_colorTexUnit);glUseProgram(0);returndata;}voidInitializePrograms(){g_program=LoadProgram("PT.vert","Tex.frag");}structProjectionBlock{glm::mat4cameraToClipMatrix;};GLuintg_projectionUniformBuffer=0;GLuintg_checkerTexture=0;GLuintg_mipmapTestTexture=0;constintNUM_SAMPLERS=6;GLuintg_samplers[NUM_SAMPLERS];voidCreateSamplers(){glGenSamplers(NUM_SAMPLERS,&g_samplers[0]);for(intsamplerIx=0;samplerIx<NUM_SAMPLERS;samplerIx++){glSamplerParameteri(g_samplers[samplerIx],GL_TEXTURE_WRAP_S,GL_REPEAT);glSamplerParameteri(g_samplers[samplerIx],GL_TEXTURE_WRAP_T,GL_REPEAT);}//NearestglSamplerParameteri(g_samplers[0],GL_TEXTURE_MAG_FILTER,GL_NEAREST);glSamplerParameteri(g_samplers[0],GL_TEXTURE_MIN_FILTER,GL_NEAREST);//LinearglSamplerParameteri(g_samplers[1],GL_TEXTURE_MAG_FILTER,GL_LINEAR);glSamplerParameteri(g_samplers[1],GL_TEXTURE_MIN_FILTER,GL_LINEAR);//Linear mipmap NearestglSamplerParameteri(g_samplers[2],GL_TEXTURE_MAG_FILTER,GL_LINEAR);glSamplerParameteri(g_samplers[2],GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);//Linear mipmap linearglSamplerParameteri(g_samplers[3],GL_TEXTURE_MAG_FILTER,GL_LINEAR);glSamplerParameteri(g_samplers[3],GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);//Low anisotropicglSamplerParameteri(g_samplers[4],GL_TEXTURE_MAG_FILTER,GL_LINEAR);glSamplerParameteri(g_samplers[4],GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);glSamplerParameterf(g_samplers[4],GL_TEXTURE_MAX_ANISOTROPY_EXT,4.0f);//Max anisotropicGLfloatmaxAniso=0.0f;glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT,&maxAniso);printf("Maximum anisotropy: %f\n",maxAniso);glSamplerParameteri(g_samplers[5],GL_TEXTURE_MAG_FILTER,GL_LINEAR);glSamplerParameteri(g_samplers[5],GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);glSamplerParameterf(g_samplers[5],GL_TEXTURE_MAX_ANISOTROPY_EXT,maxAniso);}voidFillWithColor(std::vector<GLubyte>&buffer,GLubytered,GLubytegreen,GLubyteblue,intwidth,intheight){intnumTexels=width*height;buffer.resize(numTexels*3);std::vector<GLubyte>::iteratorit=buffer.begin();while(it!=buffer.end()){*it++=red;*it++=green;*it++=blue;}}constGLubytemipmapColors[]={0xFF,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,};voidLoadMipmapTexture(){glGenTextures(1,&g_mipmapTestTexture);glBindTexture(GL_TEXTURE_2D,g_mipmapTestTexture);GLintoldAlign=0;glGetIntegerv(GL_UNPACK_ALIGNMENT,&oldAlign);glPixelStorei(GL_UNPACK_ALIGNMENT,1);for(intmipmapLevel=0;mipmapLevel<8;mipmapLevel++){intwidth=128>>mipmapLevel;intheight=128>>mipmapLevel;std::vector<GLubyte>buffer;constGLubyte*pCurrColor=&mipmapColors[mipmapLevel*3];FillWithColor(buffer,pCurrColor[0],pCurrColor[1],pCurrColor[2],width,height);glTexImage2D(GL_TEXTURE_2D,mipmapLevel,GL_RGB8,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,&buffer[0]);}glPixelStorei(GL_UNPACK_ALIGNMENT,oldAlign);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,7);glBindTexture(GL_TEXTURE_2D,0);}voidLoadCheckerTexture(){try{std::stringfilename(LOCAL_FILE_DIR);filename+="checker.dds";std::auto_ptr<glimg::ImageSet>pImageSet(glimg::loaders::dds::LoadFromFile(filename.c_str()));glGenTextures(1,&g_checkerTexture);glBindTexture(GL_TEXTURE_2D,g_checkerTexture);for(intmipmapLevel=0;mipmapLevel<pImageSet->GetMipmapCount();mipmapLevel++){glimg::SingleImageimage=pImageSet->GetImage(mipmapLevel,0,0);glimg::Dimensionsdims=image.GetDimensions();glTexImage2D(GL_TEXTURE_2D,mipmapLevel,GL_RGB8,dims.width,dims.height,0,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,image.GetImageData());}glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,pImageSet->GetMipmapCount()-1);glBindTexture(GL_TEXTURE_2D,0);}catch(std::exception&e){printf("%s\n",e.what());throw;}}Framework::Mesh*g_pPlane=NULL;Framework::Mesh*g_pCorridor=NULL;//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.voidinit(){InitializePrograms();try{g_pCorridor=newFramework::Mesh("Corridor.xml");g_pPlane=newFramework::Mesh("BigPlane.xml");}catch(std::exception&except){printf("%s\n",except.what());throw;}glEnable(GL_CULL_FACE);glCullFace(GL_BACK);glFrontFace(GL_CW);constfloatdepthZNear=0.0f;constfloatdepthZFar=1.0f;glEnable(GL_DEPTH_TEST);glDepthMask(GL_TRUE);glDepthFunc(GL_LEQUAL);glDepthRange(depthZNear,depthZFar);glEnable(GL_DEPTH_CLAMP);//Setup our Uniform BuffersglGenBuffers(1,&g_projectionUniformBuffer);glBindBuffer(GL_UNIFORM_BUFFER,g_projectionUniformBuffer);glBufferData(GL_UNIFORM_BUFFER,sizeof(ProjectionBlock),NULL,GL_DYNAMIC_DRAW);glBindBufferRange(GL_UNIFORM_BUFFER,g_projectionBlockIndex,g_projectionUniformBuffer,0,sizeof(ProjectionBlock));glBindBuffer(GL_UNIFORM_BUFFER,0);LoadCheckerTexture();LoadMipmapTexture();CreateSamplers();}usingFramework::Timer;Timerg_camTimer=Timer(Timer::TT_LOOP,5.0f);intg_currSampler=0;boolg_useMipmapTexture=false;boolg_drawCorridor=false;//Called to update the display.//You should call glutSwapBuffers after all of your rendering to display what you rendered.//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.voiddisplay(){glClearColor(0.75f,0.75f,1.0f,1.0f);glClearDepth(1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);if(g_pPlane&&g_pCorridor){g_camTimer.Update();floatcyclicAngle=g_camTimer.GetAlpha()*6.28f;floathOffset=cosf(cyclicAngle)*0.25f;floatvOffset=sinf(cyclicAngle)*0.25f;Framework::MatrixStackmodelMatrix;constglm::mat4&worldToCamMat=glm::lookAt(glm::vec3(hOffset,1.0f,-64.0f),glm::vec3(hOffset,-5.0f+vOffset,-44.0f),glm::vec3(0.0f,1.0f,0.0f));modelMatrix.ApplyMatrix(worldToCamMat);{Framework::MatrixStackPusherpush(modelMatrix);glUseProgram(g_program.theProgram);glUniformMatrix4fv(g_program.modelToCameraMatrixUnif,1,GL_FALSE,glm::value_ptr(modelMatrix.Top()));glActiveTexture(GL_TEXTURE0+g_colorTexUnit);glBindTexture(GL_TEXTURE_2D,g_useMipmapTexture?g_mipmapTestTexture:g_checkerTexture);glBindSampler(g_colorTexUnit,g_samplers[g_currSampler]);if(g_drawCorridor)g_pCorridor->Render("tex");elseg_pPlane->Render("tex");glBindSampler(g_colorTexUnit,0);glBindTexture(GL_TEXTURE_2D,0);glUseProgram(0);}}glutPostRedisplay();glutSwapBuffers();}//Called whenever the window is resized. The new window size is given, in pixels.//This is an opportunity to call glViewport or glScissor to keep up with the change in size.voidreshape(intw,inth){Framework::MatrixStackpersMatrix;persMatrix.Perspective(90.0f,(h/(float)w),g_fzNear,g_fzFar);ProjectionBlockprojData;projData.cameraToClipMatrix=persMatrix.Top();glBindBuffer(GL_UNIFORM_BUFFER,g_projectionUniformBuffer);glBufferSubData(GL_UNIFORM_BUFFER,0,sizeof(ProjectionBlock),&projData);glBindBuffer(GL_UNIFORM_BUFFER,0);glViewport(0,0,(GLsizei)w,(GLsizei)h);glutPostRedisplay();}constchar*g_samplerNames[NUM_SAMPLERS]={"Nearest","Linear","Linear with nearest mipmaps","Linear with linear mipmaps","Low anisotropic","Max anisotropic",};//Called whenever a key on the keyboard was pressed.//The key is given by the ''key'' parameter, which is in ASCII.//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to //exit the program.voidkeyboard(unsignedcharkey,intx,inty){switch(key){case27:deleteg_pPlane;deleteg_pCorridor;g_pPlane=NULL;g_pCorridor=NULL;glutLeaveMainLoop();return;case32:g_useMipmapTexture=!g_useMipmapTexture;break;case'y':g_drawCorridor=!g_drawCorridor;break;case'p':g_camTimer.TogglePause();break;}if(('1'<=key)&&(key<='9')){intnumber=key-'1';if(number<NUM_SAMPLERS){printf("Sampler: %s\n",g_samplerNames[number]);g_currSampler=number;}}}unsignedintdefaults(unsignedintdisplayMode,int&width,int&height){returndisplayMode;}