diff --git a/application.cc b/application.cc index 0dafbd3..2dea84d 100644 --- a/application.cc +++ b/application.cc @@ -5,14 +5,24 @@ Application::Application() { Loader loader = Loader(); //load the config.xml loader.loadConfig(this); - graphics = Graphics(glm::uvec2(windowWidth, windowHeight), 0.1f, farPlane, shadowCubeSize, maxShadowRenderCount); + graphics = Graphics(glm::uvec2(windowWidth, windowHeight), 0.1f, farPlane, shadowCubeSize, maxShadowRenderCount, screenPath, screenContinuePath); + gameStarted = false; } void Application::init() { + // define where shaders and textures can be found: + ACGL::Base::Settings::the()->setResourcePath("../"); + ACGL::Base::Settings::the()->setShaderPath(shaderPath); + ACGL::Base::Settings::the()->setTexturePath(texturePath); + ACGL::Base::Settings::the()->setGeometryPath(geometryPath); + graphics.renderLoadingScreen(); // init random generator std::srand(std::time(NULL)); // choose Level TODO: Choose this in a menu +} + +void Application::initLevel() { std::string heightmapFilePath = heightmapPath + "heightmapLvl1.png"; std::string levelXmlFilePath = levelXmlPath + "Level1.xml"; this->level = Level(heightmapFilePath, levelXmlFilePath); @@ -23,11 +33,6 @@ void Application::init() // set Skybox size level.setSkydomeSize((graphics.getFarPlane())-31.0f); - // define where shaders and textures can be found: - ACGL::Base::Settings::the()->setResourcePath("../"); - ACGL::Base::Settings::the()->setShaderPath(shaderPath); - ACGL::Base::Settings::the()->setTexturePath(texturePath); - ACGL::Base::Settings::the()->setGeometryPath(geometryPath); // load Level level.load(); @@ -127,3 +132,19 @@ void Application::setLevelXmlPath(std::string levelXmlPath) { void Application::setMaxShadowRenderCount(int count) { this->maxShadowRenderCount = count; } + +void Application::setLoadingScreenPath(std::string path) { + this->screenPath = path; +} +void Application::setLoadingScreenContinuePath(std::string path) { + this->screenContinuePath = path; +} + +void Application::startGame() { + gameStarted = true; + graphics.startGame(); +} + +bool Application::isGameStarted() { + return gameStarted; +} diff --git a/application.hh b/application.hh index 169a664..be205de 100644 --- a/application.hh +++ b/application.hh @@ -11,6 +11,7 @@ class Application { Graphics* getGraphics(); Level* getLevel(); void init(); + void initLevel(); void setFocused(bool focused); bool isFocused(); void setCameraLock(bool locked); @@ -30,7 +31,12 @@ class Application { void setScriptPath(std::string scriptPath); void setHeightmapPath(std::string heightmapPath); void setLevelXmlPath(std::string levelXmlPath); + void setLoadingScreenPath(std::string path); + void setLoadingScreenContinuePath(std::string path); + bool isGameStarted(); + void startGame(); private: + bool gameStarted; int ignoredMouseUpdates; bool focused; bool cameraLock; @@ -48,6 +54,8 @@ class Application { std::string scriptPath; std::string heightmapPath; std::string levelXmlPath; + std::string screenPath; + std::string screenContinuePath; }; #endif diff --git a/data/config.xml b/data/config.xml index f46e6b4..b389f19 100644 --- a/data/config.xml +++ b/data/config.xml @@ -22,3 +22,8 @@ data/levels/ data/levels/ + + + loadingscreen.png + loadingscreenContinue.png + diff --git a/data/shader/loading.fsh b/data/shader/loading.fsh new file mode 100644 index 0000000..f19e02e --- /dev/null +++ b/data/shader/loading.fsh @@ -0,0 +1,15 @@ +#version 150 + +in vec2 vTexCoord; + +uniform float time; +uniform sampler2D screen; +uniform sampler2D screenContinue; + +out vec4 oColor; + +void main() { + vec4 screenColor = texture(screen, vTexCoord); + vec4 screenContinueColor = texture(screenContinue, vTexCoord); + oColor = mix(screenColor, screenContinueColor, pow(sin(time), 2)); +} diff --git a/data/shader/loading.vsh b/data/shader/loading.vsh new file mode 100644 index 0000000..f3e6540 --- /dev/null +++ b/data/shader/loading.vsh @@ -0,0 +1,11 @@ +#version 150 + +in vec2 aPosition; +in vec2 aTexCoord; + +out vec2 vTexCoord; + +void main() { + vTexCoord = aTexCoord; + gl_Position = vec4(aPosition, 0.0, 1.0); +} diff --git a/data/textures/loadingscreen.png b/data/textures/loadingscreen.png new file mode 100644 index 0000000..4162d66 Binary files /dev/null and b/data/textures/loadingscreen.png differ diff --git a/data/textures/loadingscreenContinue.png b/data/textures/loadingscreenContinue.png new file mode 100644 index 0000000..e8d5e64 Binary files /dev/null and b/data/textures/loadingscreenContinue.png differ diff --git a/graphics.cc b/graphics.cc index 36fda09..7a00fef 100644 --- a/graphics.cc +++ b/graphics.cc @@ -13,17 +13,23 @@ const double lightUpdateDelay = 0.5f; Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, - unsigned int maxShadowRenderCount) { + unsigned int maxShadowRenderCount, + std::string screenPath, + std::string screenContinuePath) { this->windowSize = windowSize; this->nearPlane = nearPlane; this->farPlane = farPlane; this->cube_size = cube_size; this->maxShadowRenderCount = maxShadowRenderCount; + this->loadingScreenPath = screenPath; + this->loadingScreenContinuePath = screenContinuePath; + gameStart = false; } Graphics::Graphics() { } + void Graphics::init(Level* level) { // save Level this->level = level; @@ -37,24 +43,6 @@ void Graphics::init(Level* level) { glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); //glEnable(GL_MULTISAMPLE); - fullscreen_quad_ab = SharedArrayBuffer(new ArrayBuffer()); - fullscreen_quad_ab->defineAttribute("aPosition", GL_FLOAT, 2); - fullscreen_quad_ab->defineAttribute("aTexCoord", GL_FLOAT, 2); - - float quadData[] = { - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - - 1.0f, -1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 1.0f - }; - - fullscreen_quad_ab->setDataElements(6, quadData); - - fullscreen_quad = SharedVertexArrayObject(new VertexArrayObject); - fullscreen_quad->attachAllAttributes(fullscreen_quad_ab); // update lights on creation lastUpdate = -lightUpdateDelay; @@ -93,13 +81,6 @@ void Graphics::init(Level* level) { flamePostShader = ShaderProgramCreator("flame_post") .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &number_of_texture_units); - printf("Your graphics card supports %d texture units.\n", number_of_texture_units); - // Exit if we need more texture units - if (number_of_texture_units < 16) { - printf("You need at least 16 texture units to run this application. Exiting\n"); - exit(-1); - } depth_directionalMaps = std::vector(3); framebuffer_directional = std::vector(3); @@ -118,12 +99,6 @@ void Graphics::init(Level* level) { framebuffer_directional.at(i)->validate(); } - lightingShader->use(); - - for (unsigned int i = 0; isetTexture("shadowMap_directional" + std::to_string(i), depth_directionalMaps.at(i), i+1); - } // always generate and bind 10 cube maps, because otherwise the shader won't work @@ -139,12 +114,6 @@ void Graphics::init(Level* level) { framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject()); - if (level->getLights()->size() > 0) { - for(unsigned int i = 0; isetTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+4); - } - } light_fbo_color_texture = SharedTexture2D(new Texture2D(windowSize, GL_RGBA8)); light_fbo_color_texture->setMinFilter(GL_NEAREST); @@ -163,14 +132,77 @@ void Graphics::init(Level* level) { framebuffer_light->validate(); flamePostShader->use(); - flamePostShader->setTexture("light_fbo", light_fbo_color_texture, 14); flamePostShader->setUniform("windowSizeX", int(windowSize.x)); flamePostShader->setUniform("windowSizeY", int(windowSize.y)); + bindTextureUnits(); + + updateClosestLights(); +} + +void Graphics::bindTextureUnits(){ + + lightingShader->use(); + + for (unsigned int i = 0; isetTexture("shadowMap_directional" + std::to_string(i), depth_directionalMaps.at(i), i+1); + } + + if (level->getLights()->size() > 0) { + for(unsigned int i = 0; isetTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+4); + } + } + flamePostShader->use(); + flamePostShader->setTexture("light_fbo", light_fbo_color_texture, 14); + skydomeShader->use(); skydomeShader->setTexture("nightTexture", level->getSkydome()->getNightTexture()->getReference(), 15); - updateClosestLights(); + loadingShader->use(); + loadingShader->setTexture("screen", loadingScreen, 16); + loadingShader->setTexture("screenContinue", loadingContinueScreen, 17); +} + +void Graphics::renderLoadingScreen() { + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &number_of_texture_units); + printf("Your graphics card supports %d texture units.\n", number_of_texture_units); + // Exit if we need more texture units + if (number_of_texture_units < 18) { + printf("You need at least 18 texture units to run this application. Exiting\n"); + exit(-1); + } + fullscreen_quad_ab = SharedArrayBuffer(new ArrayBuffer()); + fullscreen_quad_ab->defineAttribute("aPosition", GL_FLOAT, 2); + fullscreen_quad_ab->defineAttribute("aTexCoord", GL_FLOAT, 2); + + float quadData[] = { + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f + }; + + fullscreen_quad_ab->setDataElements(6, quadData); + + fullscreen_quad = SharedVertexArrayObject(new VertexArrayObject); + fullscreen_quad->attachAllAttributes(fullscreen_quad_ab); + loadingScreen = Texture2DFileManager::the()->get(Texture2DCreator(loadingScreenPath)); + loadingScreen->generateMipmaps(); + loadingContinueScreen = Texture2DFileManager::the()->get(Texture2DCreator(loadingScreenContinuePath)); + loadingContinueScreen->generateMipmaps(); + loadingShader = ShaderProgramCreator("loading") + .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); + loadingShader->use(); + loadingShader->setUniform("time", 0.0f); + loadingShader->setTexture("screen", loadingScreen, 16); + loadingShader->setTexture("screenContinue", loadingContinueScreen, 17); + fullscreen_quad->render(); } glm::uvec2 Graphics::getWindowSize() { @@ -179,188 +211,197 @@ glm::uvec2 Graphics::getWindowSize() { void Graphics::render(double time) { - // At first render shadows - depthCubeShader->use(); - depthCubeShader->setUniform("farPlane", farPlane); - // render depth textures for point lights - glViewport(0, 0, cube_size, cube_size); - glm::mat4 depthProjectionMatrix_pointlights = glm::perspective(1.571f, (float)cube_size/(float)cube_size, 0.1f, farPlane); - glm::vec3 looking_directions[6] = {glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), - glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}; - glm::vec3 upvectors[6] = {glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, 0.0f, -1.0f), - glm::vec3(0.0f, 0.0f, -1.0f),glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, -1.0f, 0.0f)}; + if (!gameStart) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + loadingShader->use(); + loadingShader->setUniform("time", float(time)); + fullscreen_quad->render(); + } + else { + // At first render shadows + depthCubeShader->use(); + depthCubeShader->setUniform("farPlane", farPlane); + // render depth textures for point lights + glViewport(0, 0, cube_size, cube_size); + glm::mat4 depthProjectionMatrix_pointlights = glm::perspective(1.571f, (float)cube_size/(float)cube_size, 0.1f, farPlane); + glm::vec3 looking_directions[6] = {glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f), + glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -1.0f)}; + glm::vec3 upvectors[6] = {glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, 0.0f, -1.0f), + glm::vec3(0.0f, 0.0f, -1.0f),glm::vec3(0.0f, -1.0f, 0.0f),glm::vec3(0.0f, -1.0f, 0.0f)}; - framebuffer_cube->bind(); - for (unsigned int i_pointlight = 0; i_pointlightgetObjectName(), 0); + framebuffer_cube->bind(); + for (unsigned int i_pointlight = 0; i_pointlightgetObjectName(), 0); + glClear(GL_DEPTH_BUFFER_BIT); + glm::mat4 viewMatrix = glm::lookAt(closestLights.at(i_pointlight).getPosition(), + closestLights.at(i_pointlight).getPosition() + looking_directions[i_face], upvectors[i_face]); + glm::mat4 depthViewProjectionMatrix_face = depthProjectionMatrix_pointlights * viewMatrix; + std::vector viewMatrixVector = std::vector(); + viewMatrixVector.push_back(viewMatrix); + level->render(depthCubeShader, false, &depthViewProjectionMatrix_face, &viewMatrixVector); + if (!framebuffer_cube->isFrameBufferObjectComplete()) { + printf("Framebuffer incomplete, unknown error occured during shadow generation!\n"); + } + } + } + + // render depth textures for sun + depthShader->use(); + glViewport(0, 0, windowSize.x, windowSize.y); + + std::vector depthViewProjectionMatrices = std::vector(framebuffer_directional.size()); + glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition()); + + for (unsigned int i = 0; ibind(); glClear(GL_DEPTH_BUFFER_BIT); - glm::mat4 viewMatrix = glm::lookAt(closestLights.at(i_pointlight).getPosition(), - closestLights.at(i_pointlight).getPosition() + looking_directions[i_face], upvectors[i_face]); - glm::mat4 depthViewProjectionMatrix_face = depthProjectionMatrix_pointlights * viewMatrix; - std::vector viewMatrixVector = std::vector(); - viewMatrixVector.push_back(viewMatrix); - level->render(depthCubeShader, false, &depthViewProjectionMatrix_face, &viewMatrixVector); - if (!framebuffer_cube->isFrameBufferObjectComplete()) { + float projection_size = 0.0f; + switch(i) { + case 0: + projection_size = 10.0f; + break; + case 1: + projection_size = 30.0f; + break; + case 2: + projection_size = farPlane/1.5f; + break; + } + depthViewProjectionMatrices.at(i) = glm::ortho(-projection_size, projection_size, -projection_size, projection_size, -farPlane/1.5f, farPlane/1.5f) * + glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0)); + level->render(depthShader, false, &depthViewProjectionMatrices.at(i)); + if (!framebuffer_directional.at(i)->isFrameBufferObjectComplete()) { printf("Framebuffer incomplete, unknown error occured during shadow generation!\n"); } } - } + + // lighting render pass + framebuffer_light->bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // render depth textures for sun - depthShader->use(); - glViewport(0, 0, windowSize.x, windowSize.y); - - std::vector depthViewProjectionMatrices = std::vector(framebuffer_directional.size()); - glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition()); + //set view and projection matrix + glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level); - for (unsigned int i = 0; ibind(); - glClear(GL_DEPTH_BUFFER_BIT); - float projection_size = 0.0f; - switch(i) { - case 0: - projection_size = 10.0f; - break; - case 1: - projection_size = 30.0f; - break; - case 2: - projection_size = farPlane/1.5f; - break; + //render skydome + skydomeShader->use(); + // set fog Parameters + skydomeShader->setUniform("farPlane", farPlane); + skydomeShader->setUniform("skydomeSize", level->getSkydomeSize()); + skydomeShader->setUniform("fogColor", level->getFogColour()); + skydomeShader->setUniform("cameraCenter", level->getCameraCenter()->getPosition()); + skydomeShader->setUniform("directionalVector", level->getDirectionalLight()->getPosition()); + skydomeShader->setUniform("sunColor", level->getDirectionalLight()->getColour()); + level->getSkydome()->render(skydomeShader, false, true, &lightingViewProjectionMatrix); + + lightingShader->use(); + + //set lighting parameters + + // TODO look into doing this less often, offload to another thread? + // TODO figure out how to deal with bigger numbers of lights. load the nearest on demand? + + double nextUpdate = lastUpdate + lightUpdateDelay; + if (time >= nextUpdate) + { + updateLights(); + lastUpdate = time; } - depthViewProjectionMatrices.at(i) = glm::ortho(-projection_size, projection_size, -projection_size, projection_size, -farPlane/1.5f, farPlane/1.5f) * - glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0)); - level->render(depthShader, false, &depthViewProjectionMatrices.at(i)); - if (!framebuffer_directional.at(i)->isFrameBufferObjectComplete()) { - printf("Framebuffer incomplete, unknown error occured during shadow generation!\n"); + + // convert texture to homogenouse coordinates + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + + std::vector depthBiasVPs = std::vector(depthViewProjectionMatrices.size()); + for (unsigned int i = 0; isetUniform("farPlane", farPlane); + + // set fog Parameters + lightingShader->setUniform("fogColor", level->getFogColour()); + lightingShader->setUniform("cameraCenter", level->getCameraCenter()->getPosition()); + + // set Material Parameters + lightingShader->setUniform("ambientColor", level->getAmbientLight()); + lightingShader->setUniform("camera", level->getPhysics()->getCameraPosition()); + lightingShader->setUniform("movement", glm::vec2(-0.3f, -0.4f)); + lightingShader->setUniform("time", (float) time); + + // render the level + level->render(lightingShader, true, &lightingViewProjectionMatrix, &depthBiasVPs); + + // draw flames on top + flameShader->use(); + // cull faces to get consistent color while using alpha + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // draw with colors + flameShader->setUniform("viewProjectionMatrix", lightingViewProjectionMatrix); + flameShader->setUniform("modelViewProjectionMatrix", lightingViewProjectionMatrix); + flameShader->setUniform("withColor", true); + flameShader->setUniform("time", (float) time); + flameShader->setUniform("bottom", true); + flameShader->setUniform("left", true); + flame_positions->render(); + flameShader->setUniform("left", false); + flame_positions->render(); + flameShader->setUniform("bottom", false); + flameShader->setUniform("left", true); + flame_positions->render(); + flameShader->setUniform("left", false); + flame_positions->render(); + glDisable(GL_CULL_FACE); + + // draw slightly larger only for stencil buffer to blur edges + flameShader->use(); + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFF); //Set any stencil to 1 + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF);//write to stencil buffer + glClear(GL_STENCIL_BUFFER_BIT);//clear stencil buffer + + glm::mat4 modelMatrix = glm::scale(glm::vec3(1.1f)); + flameShader->setUniform("viewProjectionMatrix", lightingViewProjectionMatrix); + flameShader->setUniform("modelViewProjectionMatrix", lightingViewProjectionMatrix * modelMatrix); + flameShader->setUniform("withColor", false); + flameShader->setUniform("time", (float) time); + flameShader->setUniform("bottom", true); + flameShader->setUniform("left", true); + flame_positions->render(); + flameShader->setUniform("left", false); + flame_positions->render(); + flameShader->setUniform("bottom", false); + flameShader->setUniform("left", true); + flame_positions->render(); + flameShader->setUniform("left", false); + flame_positions->render(); + + glStencilFunc(GL_EQUAL, 1, 0xFF); //Pass test if stencil value is 1 + glStencilMask(0x00);// don't write to stencil buffer + + flamePostShader->use(); + fullscreen_quad->render(); + glDepthMask(GL_TRUE); + + glDisable(GL_STENCIL_TEST); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_light->getObjectName()); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, windowSize.x, windowSize.y, 0, 0, windowSize.x, windowSize.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); } - - // lighting render pass - framebuffer_light->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - //set view and projection matrix - glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level); - - //render skydome - skydomeShader->use(); - // set fog Parameters - skydomeShader->setUniform("farPlane", farPlane); - skydomeShader->setUniform("skydomeSize", level->getSkydomeSize()); - skydomeShader->setUniform("fogColor", level->getFogColour()); - skydomeShader->setUniform("cameraCenter", level->getCameraCenter()->getPosition()); - skydomeShader->setUniform("directionalVector", level->getDirectionalLight()->getPosition()); - skydomeShader->setUniform("sunColor", level->getDirectionalLight()->getColour()); - level->getSkydome()->render(skydomeShader, false, true, &lightingViewProjectionMatrix); - - lightingShader->use(); - - //set lighting parameters - - // TODO look into doing this less often, offload to another thread? - // TODO figure out how to deal with bigger numbers of lights. load the nearest on demand? - - double nextUpdate = lastUpdate + lightUpdateDelay; - if (time >= nextUpdate) - { - updateLights(); - lastUpdate = time; - } - - // convert texture to homogenouse coordinates - glm::mat4 biasMatrix( - 0.5, 0.0, 0.0, 0.0, - 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.5, 0.5, 0.5, 1.0 - ); - - std::vector depthBiasVPs = std::vector(depthViewProjectionMatrices.size()); - for (unsigned int i = 0; isetUniform("farPlane", farPlane); - - // set fog Parameters - lightingShader->setUniform("fogColor", level->getFogColour()); - lightingShader->setUniform("cameraCenter", level->getCameraCenter()->getPosition()); - - // set Material Parameters - lightingShader->setUniform("ambientColor", level->getAmbientLight()); - lightingShader->setUniform("camera", level->getPhysics()->getCameraPosition()); - lightingShader->setUniform("movement", glm::vec2(-0.3f, -0.4f)); - lightingShader->setUniform("time", (float) time); - - // render the level - level->render(lightingShader, true, &lightingViewProjectionMatrix, &depthBiasVPs); - - // draw flames on top - flameShader->use(); - // cull faces to get consistent color while using alpha - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - // draw with colors - flameShader->setUniform("viewProjectionMatrix", lightingViewProjectionMatrix); - flameShader->setUniform("modelViewProjectionMatrix", lightingViewProjectionMatrix); - flameShader->setUniform("withColor", true); - flameShader->setUniform("time", (float) time); - flameShader->setUniform("bottom", true); - flameShader->setUniform("left", true); - flame_positions->render(); - flameShader->setUniform("left", false); - flame_positions->render(); - flameShader->setUniform("bottom", false); - flameShader->setUniform("left", true); - flame_positions->render(); - flameShader->setUniform("left", false); - flame_positions->render(); - glDisable(GL_CULL_FACE); - - // draw slightly larger only for stencil buffer to blur edges - flameShader->use(); - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, 0xFF); //Set any stencil to 1 - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glStencilMask(0xFF);//write to stencil buffer - glClear(GL_STENCIL_BUFFER_BIT);//clear stencil buffer - - glm::mat4 modelMatrix = glm::scale(glm::vec3(1.1f)); - flameShader->setUniform("viewProjectionMatrix", lightingViewProjectionMatrix); - flameShader->setUniform("modelViewProjectionMatrix", lightingViewProjectionMatrix * modelMatrix); - flameShader->setUniform("withColor", false); - flameShader->setUniform("time", (float) time); - flameShader->setUniform("bottom", true); - flameShader->setUniform("left", true); - flame_positions->render(); - flameShader->setUniform("left", false); - flame_positions->render(); - flameShader->setUniform("bottom", false); - flameShader->setUniform("left", true); - flame_positions->render(); - flameShader->setUniform("left", false); - flame_positions->render(); - - glStencilFunc(GL_EQUAL, 1, 0xFF); //Pass test if stencil value is 1 - glStencilMask(0x00);// don't write to stencil buffer - - flamePostShader->use(); - fullscreen_quad->render(); - glDepthMask(GL_TRUE); - - glDisable(GL_STENCIL_TEST); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_light->getObjectName()); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, windowSize.x, windowSize.y, 0, 0, windowSize.x, windowSize.y, - GL_COLOR_BUFFER_BIT, GL_NEAREST); } bool Graphics::compareLightDistances(Light a, Light b) { @@ -447,6 +488,7 @@ void Graphics::resize(glm::uvec2 windowSize) { light_fbo_depth_texture->resize(windowSize); flamePostShader->setUniform("windowSizeX", int(windowSize.x)); flamePostShader->setUniform("windowSizeY", int(windowSize.y)); + bindTextureUnits(); } glm::mat4 Graphics::buildViewMatrix(Level* level) { @@ -483,3 +525,7 @@ void Graphics::saveDepthBufferToDisk(int face, std::string filename) { } delete [] depthbuffer; } + +void Graphics::startGame() { + gameStart = true; +} diff --git a/graphics.hh b/graphics.hh index 3e5358a..eb22ae5 100644 --- a/graphics.hh +++ b/graphics.hh @@ -12,7 +12,9 @@ using namespace ACGL::OpenGL; class Graphics { public: - Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, unsigned int maxShadowRenderCount); + Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, + unsigned int maxShadowRenderCount, std::string screenPath, + std::string screenContinuePath); Graphics(); void init(Level* level); void render(double time); @@ -20,7 +22,10 @@ class Graphics { glm::uvec2 getWindowSize(); void resize(glm::uvec2 windowSize); float getFarPlane(); + void startGame(); + void renderLoadingScreen(); private: + void bindTextureUnits(); void updateLights(); void updateClosestLights(); bool compareLightDistances(Light a, Light b); @@ -29,7 +34,12 @@ class Graphics { glm::uvec2 windowSize; float nearPlane; float farPlane; + std::string loadingScreenPath; + std::string loadingScreenContinuePath; + SharedTexture2D loadingScreen; + SharedTexture2D loadingContinueScreen; std::vector closestLights; + SharedShaderProgram loadingShader; SharedShaderProgram lightingShader; SharedShaderProgram skydomeShader; SharedShaderProgram depthCubeShader; @@ -51,6 +61,7 @@ class Graphics { unsigned int maxShadowRenderCount; Level* level; int number_of_texture_units = 0; + bool gameStart; }; #endif diff --git a/loader.cc b/loader.cc index f05c4c5..36ca918 100644 --- a/loader.cc +++ b/loader.cc @@ -6,9 +6,6 @@ Loader::Loader() { } void Loader::loadConfig(Application* application) { - int windowWidth, windowHeight, shadowCubeSize, maxShadowRenderCount; - float farPlane; - std::string compositionsPath, shaderPath, geometryPath, texturePath, scriptPath, heightmapPath, levelXmlPath; XMLDocument* config = new XMLDocument(); const char* xmlFile = "../data/config.xml"; config->LoadFile(xmlFile); @@ -26,10 +23,33 @@ void Loader::loadConfig(Application* application) { application->setCompositionsPath(queryString(config, "compositionsPath")); application->setShaderPath(queryString(config, "shaderPath")); application->setGeometryPath(queryString(config, "geometryPath")); - application->setTexturePath(queryString(config, "texturePath")); + std::string texturePath = queryString(config, "texturePath"); + application->setTexturePath(texturePath); application->setScriptPath(queryString(config, "scriptPath")); application->setHeightmapPath(queryString(config, "heightmapPath")); application->setLevelXmlPath(queryString(config, "levelXmlPath")); + XMLElement* loadingScreen = config->FirstChildElement("loadingScreen"); + if (loadingScreen != NULL) { + std::string screenPath = queryString(loadingScreen, "screenPath"); + std::string screenContinuePath = queryString(loadingScreen, "screenContinuePath"); + std::string screenCheckPath = "../" + texturePath + screenPath; + std::string screenContinueCheckPath = "../" + texturePath + screenPath; + struct stat buf; + if(stat(screenCheckPath.c_str(), &buf) != 0){ + std::cout << "The texture file " << screenCheckPath << " does not exist." << std::endl; + exit(-1); + } + if(stat(screenContinueCheckPath.c_str(), &buf) != 0){ + std::cout << "The texture file " << screenContinueCheckPath << " does not exist." << std::endl; + exit(-1); + } + application->setLoadingScreenPath(screenPath); + application->setLoadingScreenContinuePath(screenContinuePath); + } + else { + printf("Could not find loading screen settings in config.xml. Exiting.\n"); + exit(-1); + } } void Loader::load(std::string filePath, Level* level, std::string compositionsPath, std::string scriptPath, std::string globalGeometryPath, std::string globalTexturePath) { diff --git a/main.cc b/main.cc index a47f5f1..aa70ed8 100644 --- a/main.cc +++ b/main.cc @@ -12,6 +12,9 @@ static void resizeCallback(GLFWwindow* window, int newWidth, int newHeight) static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int) { + if (!app.isGameStarted() && _action == GLFW_PRESS) { + app.startGame(); + } if (_key == GLFW_KEY_ESCAPE && _action == GLFW_PRESS) { if (app.isFocused() && !app.isLocked()) { glfwSetWindowShouldClose( _window, GL_TRUE ); @@ -22,6 +25,9 @@ static void keyCallback(GLFWwindow* _window, int _key, int, int _action, int) } static void mouseCallback(GLFWwindow* window, int button, int action, int) { + if (!app.isGameStarted() && action == GLFW_PRESS) { + app.startGame(); + } if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetCursorPos(window, app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2); @@ -127,6 +133,9 @@ int main( int argc, char *argv[] ) glfwSwapInterval( 0 ); app.init(); + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glfwSwapBuffers(window); + app.initLevel(); int frameCount = 0; @@ -135,6 +144,7 @@ int main( int argc, char *argv[] ) double showNextFPS = startTimeInSeconds + FPSdelay; double lastUpdate=0.0f; + bool gameStarted = false; do { @@ -148,28 +158,28 @@ int main( int argc, char *argv[] ) showNextFPS = now + FPSdelay; frameCount = 0; } - - - if (app.isLocked() && app.getIgnoredMouseUpdates() == 0) { - int stateW = glfwGetKey(window, GLFW_KEY_W); - int stateA = glfwGetKey(window, GLFW_KEY_A); - int stateS = glfwGetKey(window, GLFW_KEY_S); - int stateD = glfwGetKey(window, GLFW_KEY_D); - int stateK = glfwGetKey(window, GLFW_KEY_K); - int stateL = glfwGetKey(window, GLFW_KEY_L); - - double xpos, ypos; - glfwGetCursorPos(window, &xpos, &ypos); - glfwSetCursorPos(window, app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2); - app.getLevel()->update(now - lastUpdate, now, - glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2, - (float)xpos-app.getGraphics()->getWindowSize().x/2), - stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS,stateK == GLFW_PRESS,stateL == GLFW_PRESS); - } - else { - app.getLevel()->update(now - lastUpdate, now, glm::vec2(0.0f, 0.0f), false, false, false, false,false,false); - if (app.isLocked()) { - app.ignoredOneMouseUpdate(); + if (app.isGameStarted()) { + if (app.isLocked() && app.getIgnoredMouseUpdates() == 0) { + int stateW = glfwGetKey(window, GLFW_KEY_W); + int stateA = glfwGetKey(window, GLFW_KEY_A); + int stateS = glfwGetKey(window, GLFW_KEY_S); + int stateD = glfwGetKey(window, GLFW_KEY_D); + int stateK = glfwGetKey(window, GLFW_KEY_K); + int stateL = glfwGetKey(window, GLFW_KEY_L); + + double xpos, ypos; + glfwGetCursorPos(window, &xpos, &ypos); + glfwSetCursorPos(window, app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2); + app.getLevel()->update(now - lastUpdate, now, + glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2, + (float)xpos-app.getGraphics()->getWindowSize().x/2), + stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS,stateK == GLFW_PRESS,stateL == GLFW_PRESS); + } + else { + app.getLevel()->update(now - lastUpdate, now, glm::vec2(0.0f, 0.0f), false, false, false, false,false,false); + if (app.isLocked()) { + app.ignoredOneMouseUpdate(); + } } }