#include "Renderer.h" #include "../nclgl/Camera.h" #include "../nclgl/HeightMap.h" #include "../nclgl/SceneNode.h" #include "../nclgl/MeshAnimation.h" #include "../nclgl/MeshMaterial.h" #include "../nclgl/CubeRobot.h" #define SHADOWSIZE 2048 const int POST_PASSES = 10; Renderer::Renderer(Window& parent) : OGLRenderer(parent) { fullScreenQuad = Mesh::GenerateQuad(); terrain = new HeightMap(TEXTUREDIR"noise.png"); waterTex = SOIL_load_OGL_texture(TEXTUREDIR"water.TGA", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); earthTex = SOIL_load_OGL_texture(TEXTUREDIR"Barren Reds.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); earthBump = SOIL_load_OGL_texture(TEXTUREDIR"Barren RedsDOT3.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); skybox = SOIL_load_OGL_cubemap( TEXTUREDIR"rusted_west.jpg", TEXTUREDIR"rusted_east.jpg", TEXTUREDIR"rusted_up.jpg", TEXTUREDIR"rusted_down.jpg", TEXTUREDIR"rusted_south.jpg", TEXTUREDIR"rusted_north.jpg", SOIL_LOAD_RGB, SOIL_CREATE_NEW_ID, 0); if (!earthTex || !earthBump || !skybox || !waterTex) { return; } SetTextureRepeating(earthTex, true); SetTextureRepeating(earthBump, true); SetTextureRepeating(waterTex, true); sceneShader = new Shader("SceneVertex.glsl", "SceneFragment.glsl"); reflectShader = new Shader("reflectVertex.glsl", "reflectFragment.glsl"); skyboxShader = new Shader("skyboxVertex.glsl", "skyboxFragment.glsl"); lightShader = new Shader("BumpVertex.glsl", "BumpFragment.glsl"); skinningShader = new Shader("SkinningVertex.glsl", "TexturedFragment.glsl"); shadowShader = new Shader("shadowVert.glsl", "shadowFrag.glsl"); shadowSceneShader = new Shader("shadowscenevert.glsl", "shadowscenefrag.glsl"); //reflectSphereShader - new Shader("BumpVertex.glsl", "reflectSphereFragment.glsl"); redShader = new Shader("presentVert.glsl", "redFrag.glsl"); combineShader = new Shader("combinevert.glsl", "combinefrag.glsl"); //sceneBlurShader = new Shader("TexturedVertex.glsl","TexturedFragment.glsl"); //processBlurShader = new Shader("TexturedVertex.glsl","processfrag.glsl"); if (!sceneShader->LoadSuccess() || !reflectShader->LoadSuccess() || !skyboxShader->LoadSuccess() || !lightShader->LoadSuccess() || !skinningShader->LoadSuccess() || !shadowShader->LoadSuccess() || !shadowSceneShader->LoadSuccess() //|| !reflectSphereShader->LoadSuccess() || !redShader->LoadSuccess() || !combineShader->LoadSuccess() //|| sceneBlurShader->LoadSuccess() //|| processBlurShader->LoadSuccess() ){ return; } root = new SceneNode(); terrain->SetTexture(SOIL_load_OGL_texture(TEXTUREDIR"Barren Reds.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS)); terrain->SetBumpMap(SOIL_load_OGL_texture(TEXTUREDIR"Barren RedsDOT3.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS)); SetTextureRepeating(terrain->GetTexture(), true); SetTextureRepeating(terrain->GetBumpMap(), true); Vector3 heightmapSize = terrain->GetHeightmapSize(); //Mesh* sphere = Mesh::LoadFromMeshFile("Sphere.msh"); //SceneNode* sphereNode = new SceneNode(sphere); //sphereNode->SetTransform(Matrix4::Translation(Vector3(500, 300, 0)) * Matrix4::Scale(Vector3(50, 50, 50))); //sphereNode->SetShader(reflectShader); //sphereNode->SetBoundingRadius(50.0f); //root->AddChild(sphereNode); Mesh* sphere2 = Mesh::LoadFromMeshFile("Sphere.msh"); sphere2->SetTexture(SOIL_load_OGL_texture(TEXTUREDIR"brick.tga", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS)); SetTextureRepeating(sphere2->GetTexture(), true); SceneNode* sphereNode2 = new SceneNode(sphere2); sphereNode2->SetTransform(Matrix4::Translation(Vector3(800, 300, 500)) * Matrix4::Scale(Vector3(50, 50, 50))); sphereNode2->SetShader(reflectShader); sphereNode2->SetBoundingRadius(500.0f); root->AddChild(sphereNode2); //Mesh* sphere = Mesh::LoadFromMeshFile("Sphere.msh"); //sphere->SetTexture(SOIL_load_OGL_texture(TEXTUREDIR"brick.tga", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS)); //SetTextureRepeating(sphere->GetTexture(), true); //SceneNode* sphereNode = new SceneNode(sphere); //sphereNode->SetTransform(Matrix4::Scale(Vector3(5, 5, 5)) * Matrix4::Translation(heightmapSize * Vector3(0.0f, 1.5f, 0.0f))); ////sphereNode->SetTransform(Matrix4::Scale(Vector3(2000, 2000, 2000)));; ////sphereNode->SetTransform(Matrix4::Translation(Vector3(-50, 50, 50))); //sphereNode->SetShader(reflectShader); //sphereNode->SetBoundingRadius(500.0f); //sphereNode->SetColour(Vector4(1, 0, 0, 1)); //root->AddChild(sphereNode); cubeRobot = Mesh::LoadFromMeshFile("OffsetCubeY.msh"); SceneNode* cubeRobotNode = new SceneNode(cubeRobot); //cubeRobotNode->SetTransform(Matrix4::Translation(Vector3(1000, 1000, 1000)) * Matrix4::Scale(Vector3(100, 100, 100))); sphereNode2->SetTransform(Matrix4::Translation(Vector3(1000, 300, 0)) * Matrix4::Scale(Vector3(50, 50, 50))); sphereNode2->SetShader(reflectShader); cubeRobotNode->SetBoundingRadius(20); root->AddChild(new CubeRobot(cubeRobot)); /// //////////// mesh = Mesh::LoadFromMeshFile("Role_T.msh"); anim = new MeshAnimation("Role_T.anm"); material = new MeshMaterial("Role_T.mat"); for (int i = 0; i < mesh->GetSubMeshCount(); ++i) { const MeshMaterialEntry* matEntry = material->GetMaterialForLayer(i); const string* filename = nullptr; matEntry->GetEntry("Diffuse", &filename); string path = TEXTUREDIR + *filename; GLuint texID = SOIL_load_OGL_texture(path.c_str(), SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_INVERT_Y); matTextures.emplace_back(texID); } currentFrame = 0; frameTime = 0.0f; SceneNode* meshNode = new SceneNode(mesh); meshNode->SetShader(skinningShader); BindShader(skinningShader); meshNode->SetBoundingRadius(100.0f); root->AddChild(meshNode); /// glGenTextures(1, &shadowTex); glBindTexture(GL_TEXTURE_2D, shadowTex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOWSIZE, SHADOWSIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glBindTexture(GL_TEXTURE_2D, 0); glGenFramebuffers(1, &shadowFBO); glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowTex, 0); glDrawBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); sceneMeshes.emplace_back(Mesh::GenerateQuad()); sceneMeshes.emplace_back(Mesh::LoadFromMeshFile("Sphere.msh")); sceneMeshes.emplace_back(Mesh::LoadFromMeshFile("Cylinder.msh")); sceneMeshes.emplace_back(Mesh::LoadFromMeshFile("Cone.msh")); sceneDiffuse = SOIL_load_OGL_texture(TEXTUREDIR"Barren Reds.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); sceneBump = SOIL_load_OGL_texture(TEXTUREDIR"Barren RedsDOT3.JPG", SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS); SetTextureRepeating(sceneDiffuse, true); SetTextureRepeating(sceneBump, true); glEnable(GL_DEPTH_TEST); sceneTransforms.resize(4); sceneTransforms[0] = Matrix4::Translation(Vector3(500, 500, 500)) * Matrix4::Rotation(45, Vector3(1, 0, 0)) * Matrix4::Scale(Vector3(100, 100, 100)); sceneTransforms[1] = Matrix4::Rotation(45, Vector3(1, 0, 0)) * Matrix4::Scale(Vector3(100, 100, 100)); sceneTransforms[2] = Matrix4::Rotation(45, Vector3(1, 0, 0)) * Matrix4::Scale(Vector3(100, 100, 100)); sceneTransforms[3] = Matrix4::Rotation(45, Vector3(1, 0, 0)) * Matrix4::Scale(Vector3(100, 100, 100)); sceneTime = 0.0f; light2 = new Light(heightmapSize * Vector3(0.0f, 1.0f, 0.0f), Vector4(1, 1, 1, 1), heightmapSize.x); // camOne = new Camera(-45.0f, 0.0f, //heightmapSize* Vector3(0.5f, 5.0f, 0.5f)); camOne = new Camera(-10.0f, 180.0f, Vector3(16.0f, 350.0f, -805.0f)); //camOne->SetSpeed(0.1f); camTwo = new Camera(-10.0f, 180.0f, Vector3(16.0f, 350.0f, -805.0f)); //camTwo->SetSpeed(0.1f); cameraPerspectiveMatrix = Matrix4::Perspective(1.0f, 10000.0f, (float)width / (float)height, 45.0f); cameraSplitScreenPerspectiveMatrix = Matrix4::Perspective(1.0f, 10000.0f, (float)width / ((float)height / 2.0f), 45.0f); shadowPerspectiveMatrix = Matrix4::Perspective(1.0f, 10000.0f, 1, 90.0f); light = new Light(heightmapSize * Vector3(0.5f, 1.5f, 0.5f), Vector4(1, 1, 1, 1), heightmapSize.x); projMatrix = Matrix4::Perspective(1.0f, 15000.0f, (float)width / (float)height, 45.0f); //glGenFramebuffers(1, &bufferFBO); //glGenFramebuffers(1, &pointLightFBO); //glGenFramebuffers(1, &shadowFBO); //glGenFramebuffers(1, &shadowCubeMapFBO); //glGenFramebuffers(1, &combinedFBO); //gBuffer[0] = GL_COLOR_ATTACHMENT0; //gBuffer[1] = GL_COLOR_ATTACHMENT1; //gBuffer[2] = GL_COLOR_ATTACHMENT2; //lightBuffer[0] = GL_COLOR_ATTACHMENT0; //lightBuffer[1] = GL_COLOR_ATTACHMENT1; //combinedBuffer[0] = GL_COLOR_ATTACHMENT0; //generateGBuffer(); //generateLightBuffer(); //generateShadowBuffer(); //generateShadowCubeMapBuffer(); //generateCombinedBuffer(); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); waterRotate = 0.0f; waterCycle = 0.0f; init = true; } Renderer::~Renderer(void) { delete camOne; delete terrain; delete fullScreenQuad; delete light; delete light2; delete root; delete cubeRobot; delete mesh; delete anim; delete material; delete sceneShader; delete lightShader; delete reflectShader; delete skyboxShader; delete skinningShader; delete shadowShader; delete shadowSceneShader; delete redShader; delete combineShader; glDeleteTextures(1, &shadowTex); glDeleteFramebuffers(1, &shadowFBO); for (auto& i : sceneMeshes) { delete i; } glDeleteTextures(1, &bufferColourTex); glDeleteTextures(1, &bufferNormalTex); glDeleteTextures(1, &bufferPosTex); glDeleteTextures(1, &bufferDepthTex); glDeleteTextures(1, &lightEmissiveTex); glDeleteTextures(1, &lightSpecularTex); glDeleteTextures(1, &shadowTex); glDeleteTextures(1, &shadowCubeMapTex); glDeleteTextures(1, &combinedTex); glDeleteTextures(2, bufferColourTexPost); glDeleteFramebuffers(1, &bufferFBO); glDeleteFramebuffers(1, &pointLightFBO); glDeleteFramebuffers(1, &shadowFBO); glDeleteFramebuffers(1, &shadowCubeMapFBO); glDeleteFramebuffers(1, &combinedFBO); glDeleteFramebuffers(1, &processFBO); root = NULL; } void Renderer::CombineBuffers() { glBindFramebuffer(GL_FRAMEBUFFER, combinedFBO); BindShader(combineShader); if (drawSplitScreen) projMatrix = cameraSplitScreenPerspectiveMatrix; else projMatrix = cameraPerspectiveMatrix; glUniformMatrix4fv(glGetUniformLocation(currentShader->GetProgram(), "oriProjMatrix"), 1, false, (float*)&projMatrix); projMatrix = Matrix4::Orthographic(-1, 1, 1, -1, -1, 1); viewMatrix = camOne->BuildViewMatrix(); UpdateShaderMatrices(); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "diffuseTex"), 2); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "emissiveTex"), 3); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "specularTex"), 4); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "posTex"), 5); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "depthTex"), 6); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "skybox"), 7); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, bufferColourTex); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, lightEmissiveTex); glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, lightSpecularTex); glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D, bufferPosTex); glActiveTexture(GL_TEXTURE6); glBindTexture(GL_TEXTURE_2D, bufferDepthTex); glActiveTexture(GL_TEXTURE7); glBindTexture(GL_TEXTURE_CUBE_MAP, skybox); fullScreenQuad->Draw(); glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::UpdateScene(float dt) { Matrix4 rotation = Matrix4::Rotation(camOne->GetYaw(), Vector3(0, 1, 0)); Vector3 forward = rotation * Vector3(0, 0, -1); Vector3 right = rotation * Vector3(1, 0, 0); if (cameraAutomatic) { if (waitCameraTime == 0.0f) { // camOne->SetYaw(10.0); } waitCameraTime += dt; //camOne->SetYaw((Window::GetMouse()->GetRelativePosition().x)); if (waitCameraTime > 25.0f) { //25.0f camOne->SetPosition(camOne->GetPosition() + forward * 1.0); std::cout << "X: " << camOne->GetPosition().x << "Y: " << camOne->GetPosition().y << "Z: " << camOne->GetPosition().z; std::cout << "Yaw: " << camOne->GetYaw() << "Pitch: " << camOne->GetPitch(); if (camOne->GetPosition().z > 1350.0f) { //camOne->SetYaw(30.0f); camOne->SetPosition(camOne->GetPosition() - right * 1.0); } if (camOne->GetPosition().x > 1900.0f) { //camOne->SetYaw(30.0f); camOne->SetPosition(camOne->GetPosition() - forward * 1.0); } //if (camOne->GetPosition().z > 650.0f) { // //camOne->SetYaw(30.0f); // camOne->SetPosition(camOne->GetPosition() - forward * 1.0); //} } moveCamOne = true; } else { moveCamOne = true; } if (moveCamOne) camOne->UpdateCamera(dt); else camTwo->UpdateCamera(dt); camOne->UpdateCamera(dt); viewMatrix = camOne->BuildViewMatrix(); frameFrustum.FromMatrix(projMatrix * viewMatrix); waterRotate += dt * 2.0f; waterCycle += dt * 0.25f; sceneTime += dt; frameTime -= dt; while (frameTime < 0.0f) { currentFrame = (currentFrame + 1) % anim->GetFrameCount(); frameTime += 1.0f / anim->GetFrameRate(); } for (int i = 0; i < 4; ++i) { Vector3 t = Vector3(-10 + (5 * i), 2.0f + sin(sceneTime * i), 0); sceneTransforms[i] = Matrix4::Translation(t) * Matrix4::Rotation(sceneTime * 10 * i, Vector3(1, 0, 0)); } redIntensity += dt / 1000.0f; if (redIntensity >= 90.0f) redIntensity -= 90.0f; root->Update(dt); } void Renderer::RenderScene() { currentCamera = camOne; modelMatrix.ToIdentity(); if (drawSplitScreen) projMatrix = cameraSplitScreenPerspectiveMatrix; else projMatrix = cameraPerspectiveMatrix; // glBindFramebuffer(GL_FRAMEBUFFER, 0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); DrawSkybox(); DrawHeightmap(); DrawWater(); DrawCharacter(); DrawMainNodeScene(); DrawShadowScene(); DrawMainShadowScene(); //CombineBuffers(); if (applyRedPostProcess) DrawRedPostProcess(); if (drawSplitScreen) glViewport(0, 0, width, height / 2); if (drawSplitScreen) { currentCamera = camTwo; modelMatrix.ToIdentity(); projMatrix = cameraSplitScreenPerspectiveMatrix; glViewport(0, height / 2, width, height / 2); DrawSkybox(); DrawHeightmap(); DrawWater(); DrawCharacter(); DrawMainNodeScene(); DrawShadowScene(); DrawMainShadowScene(); glViewport(0, 0, width, height); } } void Renderer::DrawRedPostProcess() { glBindFramebuffer(GL_FRAMEBUFFER, combinedFBO); BindShader(redShader); UpdateShaderMatrices(); glUniform1i(glGetUniformLocation(currentShader->GetProgram(), "diffuseTex"), 2); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, combinedTex); glUniform1f(glGetUniformLocation(currentShader->GetProgram(), "intensity"), sin(redIntensity)); fullScreenQuad->Draw(); glUseProgram(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::DrawSkybox() { glDepthMask(GL_FALSE); BindShader(skyboxShader); UpdateShaderMatrices(); fullScreenQuad->Draw(); glDepthMask(GL_TRUE); } void Renderer::DrawHeightmap() { BindShader(lightShader); SetShaderLight(*light); glUniform3fv(glGetUniformLocation( lightShader->GetProgram(), "cameraPos"), 1, (float*)&camOne->GetPosition()); glUniform1i(glGetUniformLocation( lightShader->GetProgram(), "diffuseTex"), 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, earthTex); glUniform1i(glGetUniformLocation( lightShader->GetProgram(), "bumpTex"), 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, earthBump); modelMatrix.ToIdentity(); textureMatrix.ToIdentity(); UpdateShaderMatrices(); terrain->Draw(); } void Renderer::DrawWater() { BindShader(reflectShader); glUniform3fv(glGetUniformLocation( reflectShader->GetProgram(), "cameraPos"), 1, (float*)&camOne->GetPosition()); glUniform1i(glGetUniformLocation( reflectShader->GetProgram(), "diffuseTex"), 0); glUniform1i(glGetUniformLocation( reflectShader->GetProgram(), "cubeTex"), 2); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, waterTex); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_CUBE_MAP, skybox); Vector3 hSize = terrain->GetHeightmapSize(); modelMatrix = Matrix4::Translation(hSize * 0.5f) * Matrix4::Scale(hSize * 0.5f) * Matrix4::Rotation(90, Vector3(1, 0, 0)); textureMatrix = Matrix4::Translation(Vector3(waterCycle, 0.0f, waterCycle)) * Matrix4::Scale(Vector3(10, 10, 10)) * Matrix4::Rotation(waterRotate, Vector3(0, 0, 1)); UpdateShaderMatrices(); //SetShaderLight (* light ); // No lighting in this shader ! fullScreenQuad->Draw(); } void Renderer::DrawCharacter() { BindShader(skinningShader); glUniform1i( glGetUniformLocation(skinningShader->GetProgram(), "diffuseTex"), 0); modelMatrix = Matrix4::Translation(Vector3(500,150,120)) * Matrix4::Scale(Vector3(100, 100, 100)); UpdateShaderMatrices(); vector frameMatrices; const Matrix4* invBindPose = mesh->GetInverseBindPose(); const Matrix4* frameData = anim->GetJointData(currentFrame); for (unsigned int i = 0; i < mesh->GetJointCount(); ++i) { frameMatrices.emplace_back(frameData[i] * invBindPose[i]); } int j = glGetUniformLocation(skinningShader->GetProgram(), "joints"); glUniformMatrix4fv(j, frameMatrices.size(), false, (float*)frameMatrices.data()); for (int i = 0; i < mesh->GetSubMeshCount(); ++i) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, matTextures[i]); mesh->DrawSubMesh(i); } } void Renderer::DrawShadowScene() { glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, SHADOWSIZE, SHADOWSIZE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); BindShader(shadowShader); viewMatrix = Matrix4::BuildViewMatrix( light2->GetPosition(), Vector3(0, 0, 0)); projMatrix = Matrix4::Perspective(1, 100, 1, 45); shadowMatrix = projMatrix * viewMatrix; for (int i = 0; i < 4; ++i) { modelMatrix = sceneTransforms[i]; UpdateShaderMatrices(); sceneMeshes[i]->Draw(); } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glViewport(0, 0, width, height); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::DrawMainShadowScene() { BindShader(shadowSceneShader); SetShaderLight(*light2); viewMatrix = camOne->BuildViewMatrix(); projMatrix = Matrix4::Perspective(1.0f, 15000.0f, (float)width / (float)height, 45.0f); glUniform1i(glGetUniformLocation(shadowSceneShader->GetProgram(), "diffuseTex"), 0); glUniform1i(glGetUniformLocation(shadowSceneShader->GetProgram(), "bumpTex"), 1); glUniform1i(glGetUniformLocation(shadowSceneShader->GetProgram(), "shadowTex"), 2); glUniform3fv(glGetUniformLocation(shadowSceneShader->GetProgram(), "cameraPos"), 1, (float*)&camOne->GetPosition()); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, sceneDiffuse); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, sceneBump); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, shadowTex); for (int i = 0; i < 4; ++i) { int tr = 300 * i; modelMatrix = sceneTransforms[i] * Matrix4::Translation(Vector3(tr, 250, 250)) * Matrix4::Scale(Vector3(100,100,100)); UpdateShaderMatrices(); sceneMeshes[i]->Draw(); } } void Renderer::DrawMainNodeScene() { BuildNodeLists(root); SortNodeLists(); BindShader(sceneShader); UpdateShaderMatrices(); glUniform1i( glGetUniformLocation(sceneShader->GetProgram(), "diffuseTex"), 0); DrawNodes(); ClearNodeLists(); } void Renderer::BuildNodeLists(SceneNode* from) { if (frameFrustum.InsideFrustum(*from)) { Vector3 dir = from->GetWorldTransform().GetPositionVector() - camOne->GetPosition(); from->SetCameraDistance(Vector3::Dot(dir, dir)); if (from->GetColour().w < 1.0f) { transparentNodeList.push_back(from); } else { nodeList.push_back(from); } } for (vector::const_iterator i = from->GetChildIteratorStart(); i != from->GetChildIteratorEnd(); ++i) { BuildNodeLists((*i)); } } void Renderer::SortNodeLists() { std::sort(transparentNodeList.rbegin(), transparentNodeList.rend(), SceneNode::CompareByCameraDistance); std::sort(nodeList.begin(), nodeList.end(), SceneNode::CompareByCameraDistance); } void Renderer::DrawNodes() { for (const auto& i : nodeList) { DrawNode(i); } for (const auto& i : transparentNodeList) { DrawNode(i); } } void Renderer::DrawNode(SceneNode* n) { if (n->GetMesh()) { Matrix4 model = n->GetWorldTransform() * Matrix4::Scale(n->GetModelScale()); glUniformMatrix4fv( glGetUniformLocation(currentShader->GetProgram(), "modelMatrix"), 1, false, model.values); glUniform4fv( glGetUniformLocation(currentShader->GetProgram(), "nodeColour"), 1, (float*)&n->GetColour()); GLuint texture = n->GetTexture(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); glUniform1i( glGetUniformLocation(currentShader->GetProgram(), "useTexture"), texture); n->Draw(*this); } } void Renderer::ClearNodeLists() { transparentNodeList.clear(); nodeList.clear(); } void Renderer::GenerateScreenTexture(GLuint& into, bool depth) { glGenTextures(1, &into); glBindTexture(GL_TEXTURE_2D, into); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, depth ? GL_DEPTH_COMPONENT24 : GL_RGBA8, width, height, 0, depth ? GL_DEPTH_COMPONENT : GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); } void Renderer::GenerateShadowTexture(GLuint& into) { glGenTextures(1, &into); glBindTexture(GL_TEXTURE_2D, into); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOWSIZE, SHADOWSIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glBindTexture(GL_TEXTURE_2D, 0); } void Renderer::GenerateShadowCubeMapTexture(GLuint& into) { glGenTextures(1, &into); glBindTexture(GL_TEXTURE_CUBE_MAP, into); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); for (int i = 0; i < 6; ++i) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT24, SHADOWSIZE, SHADOWSIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glBindTexture(GL_TEXTURE_2D, 0); } void Renderer::generateGBuffer() { GenerateScreenTexture(bufferColourTex); GenerateScreenTexture(bufferNormalTex); GenerateScreenTexture(bufferPosTex); GenerateScreenTexture(bufferDepthTex, true); glBindFramebuffer(GL_FRAMEBUFFER, bufferFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bufferColourTex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, bufferNormalTex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, bufferPosTex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, bufferDepthTex, 0); glDrawBuffers(3, gBuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::generateLightBuffer() { GenerateScreenTexture(lightEmissiveTex); GenerateScreenTexture(lightSpecularTex); glBindFramebuffer(GL_FRAMEBUFFER, pointLightFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightEmissiveTex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, lightSpecularTex, 0); glDrawBuffers(2, lightBuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::generateShadowBuffer() { GenerateShadowTexture(shadowTex); glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowTex, 0); glDrawBuffer(GL_NONE); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::generateShadowCubeMapBuffer() { GenerateShadowCubeMapTexture(shadowCubeMapTex); glBindFramebuffer(GL_FRAMEBUFFER, shadowCubeMapFBO); glDrawBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::generateCombinedBuffer() { GenerateScreenTexture(combinedTex); glBindFramebuffer(GL_FRAMEBUFFER, combinedFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, combinedTex, 0); glDrawBuffers(1, combinedBuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { return; } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void Renderer::DrawPostProcess() { glBindFramebuffer(GL_FRAMEBUFFER, processFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bufferColourTexPost[1], 0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); BindShader(sceneShader); modelMatrix.ToIdentity(); viewMatrix.ToIdentity(); projMatrix.ToIdentity(); UpdateShaderMatrices(); glDisable(GL_DEPTH_TEST); glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation( sceneShader->GetProgram(), "sceneTex"), 0); for (int i = 0; i < POST_PASSES; ++i) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bufferColourTexPost[1], 0); glUniform1i(glGetUniformLocation(sceneShader->GetProgram(), "isVertical"), 0); glBindTexture(GL_TEXTURE_2D, bufferColourTexPost[0]); fullScreenQuad->Draw(); //Now to swap the colour buffers, and do the second blur pass glUniform1i(glGetUniformLocation(sceneShader->GetProgram(), "isVertical"), 1); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, bufferColourTexPost[0], 0); glBindTexture(GL_TEXTURE_2D, bufferColourTexPost[1]); fullScreenQuad->Draw(); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glEnable(GL_DEPTH_TEST); }