Merge branch 'master' of github.com:Faerbit/swp

This commit is contained in:
Steffen Fündgens 2015-02-13 17:14:38 +01:00
commit 1492a312ed
21 changed files with 291 additions and 86 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@ CMakeLists.txt.user
*.zip *.zip
*.db *.db
*.blend1 *.blend1
*.swp

View File

@ -69,7 +69,7 @@
</object> </object>
<light> <light>
<xOffset>0.0</xOffset> <xOffset>0.0</xOffset>
<yOffset>3</yOffset> <yOffset>2</yOffset>
<zOffset>0.0</zOffset> <zOffset>0.0</zOffset>
<rColour>1.0</rColour> <rColour>1.0</rColour>
<gColour>1.0</gColour> <gColour>1.0</gColour>

View File

@ -5,3 +5,8 @@ This will be a Marble Race Game developed for the Softwarepraktikum at the RWTH
##Building ##Building
Currently only tested on Linux. To build execute build.sh. Resulting binary will be in binaries. Currently only tested on Linux. To build execute build.sh. Resulting binary will be in binaries.
You can also use the run.sh script to directly start the binary after building it. You can also use the run.sh script to directly start the binary after building it.
##Control
You can control the camera by moving the mouse. You can zoom with the mouse wheel.
The marble is controlled via the W,A,S and D keys.

View File

@ -1,7 +1,7 @@
#version 150 #version 150
out float fragmentDepth; out float gl_FragDepth;
void main() { void main() {
fragmentDepth = gl_FragCoord.z; gl_FragDepth = gl_FragCoord.z;
} }

16
Shader/depth_cube.fsh Normal file
View File

@ -0,0 +1,16 @@
#version 150
in vec4 fragPosition;
uniform float farPlane;
out float gl_FragDepth;
void main() {
float nearPlane = 0.1;
float A = -(farPlane+nearPlane)/(farPlane-nearPlane);
float B = -2*(farPlane*nearPlane)/(farPlane - nearPlane);
float value = 0.5*(-A*length(fragPosition) + B)/length(fragPosition) + 0.5;
gl_FragDepth = value;
//gl_FragDepth = length(fragPosition)/farPlane;
}

15
Shader/depth_cube.vsh Normal file
View File

@ -0,0 +1,15 @@
#version 150
in vec3 aPosition;
in vec3 aNormal;
in vec3 aTexcoord;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
out vec4 fragPosition;
void main() {
fragPosition = modelViewMatrix * vec4(aPosition, 1.0);
gl_Position = modelViewProjectionMatrix * vec4(aPosition, 1.0);
}

View File

@ -9,7 +9,16 @@ out vec4 oColor;
uniform sampler2D uTexture; uniform sampler2D uTexture;
uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMap;
uniform samplerCubeShadow shadowMap_cube; uniform samplerCubeShadow shadowMap_cube0;
uniform samplerCubeShadow shadowMap_cube1;
uniform samplerCubeShadow shadowMap_cube2;
uniform samplerCubeShadow shadowMap_cube3;
uniform samplerCubeShadow shadowMap_cube4;
uniform samplerCubeShadow shadowMap_cube5;
uniform samplerCubeShadow shadowMap_cube6;
uniform samplerCubeShadow shadowMap_cube7;
uniform samplerCubeShadow shadowMap_cube8;
uniform samplerCubeShadow shadowMap_cube9;
uniform vec3 ambientColor; uniform vec3 ambientColor;
uniform float ambientFactor; uniform float ambientFactor;
uniform float diffuseFactor; uniform float diffuseFactor;
@ -17,6 +26,7 @@ uniform float specularFactor;
uniform vec3 camera; uniform vec3 camera;
uniform float shininess; uniform float shininess;
uniform int lightCount; uniform int lightCount;
uniform int maxShadowRenderCount;
uniform vec3 directionalLightVector; uniform vec3 directionalLightVector;
uniform vec3 directionalColor; uniform vec3 directionalColor;
uniform float directionalIntensity; uniform float directionalIntensity;
@ -70,9 +80,10 @@ float samplePointShadow(samplerCubeShadow shadowMap, vec3 lightDirection) {
float A = -(farPlane+nearPlane)/(farPlane-nearPlane); float A = -(farPlane+nearPlane)/(farPlane-nearPlane);
float B = -2*(farPlane*nearPlane)/(farPlane - nearPlane); float B = -2*(farPlane*nearPlane)/(farPlane - nearPlane);
float compValue = 0.5*(-A*length(lightDirection) + B)/length(lightDirection) + 0.5; float compValue = 0.5*(-A*length(lightDirection) + B)/length(lightDirection) + 0.5;
float bias = 0.005; float bias = 0.001*tan(acos(clamp(dot(vNormal, -directionalLightVector), 0.0, 1.0)));
vec3 vector = vec3(-lightDirection.x, -lightDirection.y, lightDirection.z); bias = clamp(bias, 0.0, 0.01);
return texture(shadowMap, vec4(vector , compValue - bias)); //return texture(shadowMap, vec4(lightDirection , length(lightDirection)/farPlane - bias));
return texture(shadowMap, vec4(lightDirection , compValue - bias));
} }
float distanceToBorder(vec2 vector) { float distanceToBorder(vec2 vector) {
@ -91,11 +102,13 @@ void main()
// direction lighting // direction lighting
if(length(directionalLightVector)>0.0f) { if(length(directionalLightVector)>0.0f) {
vec3 directionalVector = normalize(directionalLightVector); vec3 directionalVector = normalize(directionalLightVector);
float directionalVisibility = sampleDirectionalShadow(shadowMap, shadowCoord);
diffuseColor += clamp(dot(normalize(vNormal), directionalVector) diffuseColor += clamp(dot(normalize(vNormal), directionalVector)
*diffuseFactor*directionalIntensity*directionalColor, 0.0, 1.0); *diffuseFactor*directionalIntensity*directionalColor, 0.0, 1.0)*directionalVisibility;
vec3 cameraVector = normalize(camera - vec3(fragPosition)); vec3 cameraVector = normalize(camera - vec3(fragPosition));
specularColor += clamp(pow((dot((cameraVector+directionalVector),normalize(vNormal))/(length(cameraVector+directionalVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0) specularColor += clamp(pow((dot((cameraVector+directionalVector),normalize(vNormal))/
*specularFactor*directionalIntensity*directionalColor; (length(cameraVector+directionalVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*directionalIntensity*directionalColor*directionalVisibility;
} }
// point lights // point lights
@ -103,24 +116,50 @@ void main()
for(int i = 0; i<lightCount; i++) { for(int i = 0; i<lightCount; i++) {
vec3 lightDirection = vec3(fragPosition) - lightSources[i]; vec3 lightDirection = vec3(fragPosition) - lightSources[i];
float distance = length(lightDirection); float distance = length(lightDirection);
float pointVisibility = 1.0f;
// only take lights into account with meaningful contribution // only take lights into account with meaningful contribution
if (distance > 0.001f) { if (distance < farPlane) {
if (i == 0 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube0, lightDirection);
}
if (i == 1 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube1, lightDirection);
}
if (i == 2 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube2, lightDirection);
}
if (i == 3 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube3, lightDirection);
}
if (i == 4 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube4, lightDirection);
}
if (i == 5 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube5, lightDirection);
}
if (i == 6 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube6, lightDirection);
}
if (i == 7 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube7, lightDirection);
}
if (i == 8 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube8, lightDirection);
}
if (i == 9 && i<maxShadowRenderCount) {
pointVisibility = samplePointShadow(shadowMap_cube9, lightDirection);
}
vec3 lightVector = normalize(lightSources[i]-vec3(fragPosition)); vec3 lightVector = normalize(lightSources[i]-vec3(fragPosition));
float intensity = clamp(exp(-(1/lightIntensities[i])*distance), 0.0, 1.0); float intensity = clamp(exp(-(1/lightIntensities[i])*distance), 0.0, 1.0);
diffuseColor += clamp(dot(normalize(vNormal), lightVector) diffuseColor += clamp(dot(normalize(vNormal), lightVector)
*diffuseFactor*intensity*lightColors[i], 0.0, 1.0); *diffuseFactor*intensity*lightColors[i], 0.0, 1.0)*pointVisibility;
vec3 cameraVector = normalize(camera - vec3(fragPosition)); vec3 cameraVector = normalize(camera - vec3(fragPosition));
specularColor += clamp(pow((dot((cameraVector+lightVector),normalize(vNormal))/(length(cameraVector+lightVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0) specularColor += clamp(pow((dot((cameraVector+lightVector),normalize(vNormal))/
*specularFactor*intensity*lightColors[i]; (length(cameraVector+lightVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
visibility = samplePointShadow(shadowMap_cube, lightDirection); *specularFactor*intensity*lightColors[i]*pointVisibility;
} }
} }
// shadows
visibility *= sampleDirectionalShadow(shadowMap, shadowCoord);
specularColor *= visibility;
diffuseColor *= visibility;
vec3 finalColor = specularColor + diffuseColor + ambientColor; vec3 finalColor = specularColor + diffuseColor + ambientColor;
float distanceCameraCenter = distance(cameraCenter, vec3(fragPosition)); float distanceCameraCenter = distance(cameraCenter, vec3(fragPosition));

View File

@ -5,7 +5,7 @@ Application::Application() {
Loader loader = Loader(); Loader loader = Loader();
//load the config.xml //load the config.xml
loader.loadConfig(this); loader.loadConfig(this);
graphics = Graphics(glm::uvec2(windowWidth, windowHeight), 0.1f, farPlane, shadowCubeSize); graphics = Graphics(glm::uvec2(windowWidth, windowHeight), 0.1f, farPlane, shadowCubeSize, maxShadowRenderCount);
} }
void Application::init() void Application::init()
@ -123,3 +123,7 @@ void Application::setHeightmapPath(std::string heightmapPath) {
void Application::setLevelXmlPath(std::string levelXmlPath) { void Application::setLevelXmlPath(std::string levelXmlPath) {
this->levelXmlPath = levelXmlPath; this->levelXmlPath = levelXmlPath;
} }
void Application::setMaxShadowRenderCount(int count) {
this->maxShadowRenderCount = count;
}

View File

@ -22,6 +22,7 @@ class Application {
void setWindowHeight(int windowHeight); void setWindowHeight(int windowHeight);
void setShadowCubeSize(int shadowCubeSize); void setShadowCubeSize(int shadowCubeSize);
void setFarPlane(float farPlane); void setFarPlane(float farPlane);
void setMaxShadowRenderCount(int count);
void setCompositionsPath(std::string compositionsPath); void setCompositionsPath(std::string compositionsPath);
void setShaderPath(std::string shaderPath); void setShaderPath(std::string shaderPath);
void setGeometryPath(std::string geometryPath); void setGeometryPath(std::string geometryPath);
@ -38,6 +39,7 @@ class Application {
int windowWidth; int windowWidth;
int windowHeight; int windowHeight;
int shadowCubeSize; int shadowCubeSize;
int maxShadowRenderCount;
float farPlane; float farPlane;
std::string compositionsPath; std::string compositionsPath;
std::string shaderPath; std::string shaderPath;

View File

@ -3,6 +3,7 @@
Camera::Camera(glm::vec2 rotation, float distance) { Camera::Camera(glm::vec2 rotation, float distance) {
this->rotation = rotation; this->rotation = rotation;
this->distance = distance; this->distance = distance;
this->setIsPhysicsCamera(true);
} }
Camera::Camera() { Camera::Camera() {
@ -31,6 +32,15 @@ void Camera::setRotation(glm::vec2 rotation) {
updatePosition(); updatePosition();
} }
bool Camera::getIsPhysicsCamera()
{
return usePhysicsCamera;
}
void Camera::setIsPhysicsCamera(bool val)
{
usePhysicsCamera = val;
}
void Camera::updateRotation(glm::vec2 rotation) { void Camera::updateRotation(glm::vec2 rotation) {
this->rotation += rotation; this->rotation += rotation;
if((this->rotation.x + rotation.x) >= 1.57f) { if((this->rotation.x + rotation.x) >= 1.57f) {

View File

@ -19,7 +19,8 @@ class Camera {
glm::vec3 getPosition(); glm::vec3 getPosition();
void setDirection(glm::vec3 dir); void setDirection(glm::vec3 dir);
glm::vec3 getDirection(); glm::vec3 getDirection();
bool getIsPhysicsCamera();
void setIsPhysicsCamera(bool val);
private: private:
void updatePosition(); void updatePosition();
float distance; float distance;
@ -27,6 +28,7 @@ class Camera {
glm::vec3 vector; glm::vec3 vector;
glm::vec3 position; glm::vec3 position;
glm::vec3 direction; glm::vec3 direction;
bool usePhysicsCamera;
}; };
#endif #endif

View File

@ -7,6 +7,8 @@
<farPlane>150.0</farPlane> <farPlane>150.0</farPlane>
<maxShadowRenderCount>10</maxShadowRenderCount>
<compositionsPath>../Levels/ObjectSetups/Compositions.xml</compositionsPath> <compositionsPath>../Levels/ObjectSetups/Compositions.xml</compositionsPath>
<shaderPath>Shader/</shaderPath> <shaderPath>Shader/</shaderPath>

View File

@ -1,7 +1,9 @@
#include "graphics.hh" #include "graphics.hh"
#include "lodepng.h"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <functional>
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh> #include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
@ -9,11 +11,14 @@ using namespace ACGL::OpenGL;
const double lightUpdateDelay = 0.5f; const double lightUpdateDelay = 0.5f;
Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size) { Graphics::Graphics(glm::uvec2 windowSize, float nearPlane,
float farPlane, int cube_size,
unsigned int maxShadowRenderCount) {
this->windowSize = windowSize; this->windowSize = windowSize;
this->nearPlane = nearPlane; this->nearPlane = nearPlane;
this->farPlane = farPlane; this->farPlane = farPlane;
this->cube_size = cube_size; this->cube_size = cube_size;
this->maxShadowRenderCount = maxShadowRenderCount;
} }
Graphics::Graphics() { Graphics::Graphics() {
@ -41,7 +46,10 @@ void Graphics::init(Level* level) {
depthShader = ShaderProgramCreator("depth") depthShader = ShaderProgramCreator("depth")
.attributeLocations(vao->getAttributeLocations()).create(); .attributeLocations(vao->getAttributeLocations()).create();
depthTexture = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT16)); depthCubeShader = ShaderProgramCreator("depth_cube")
.attributeLocations(vao->getAttributeLocations()).create();
depthTexture = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT24));
depthTexture->setMinFilter(GL_NEAREST); depthTexture->setMinFilter(GL_NEAREST);
depthTexture->setMagFilter(GL_NEAREST); depthTexture->setMagFilter(GL_NEAREST);
depthTexture->setWrapS(GL_CLAMP_TO_EDGE); depthTexture->setWrapS(GL_CLAMP_TO_EDGE);
@ -52,11 +60,18 @@ void Graphics::init(Level* level) {
framebuffer->setDepthTexture(depthTexture); framebuffer->setDepthTexture(depthTexture);
framebuffer->validate(); framebuffer->validate();
/*depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(level->getLights()->size()); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &number_of_texture_units);
for (unsigned int i = 0; i<depth_cubeMaps.size(); i++) {*/ printf("Your graphics card supports %d texture units.\n", number_of_texture_units);
depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(std::min(int(level->getLights()->size()), 1)); // Exit if we need more texture units
for (unsigned int i = 0; i<1 && i<depth_cubeMaps.size(); i++) { if (number_of_texture_units < 12) {
depth_cubeMaps.at(i) = SharedTextureCubeMap(new TextureCubeMap(glm::vec2(cube_size, cube_size), GL_DEPTH_COMPONENT16)); printf("You need at least 12 texture units to run this application. Exiting\n");
exit(-1);
}
// always generate and bind 32 cube maps, because otherwise the shader won't work
depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(10);
for (unsigned int i = 0; i<depth_cubeMaps.size(); i++) {
depth_cubeMaps.at(i) = SharedTextureCubeMap(new TextureCubeMap(glm::vec2(cube_size, cube_size), GL_DEPTH_COMPONENT24));
depth_cubeMaps.at(i)->setMinFilter(GL_NEAREST); depth_cubeMaps.at(i)->setMinFilter(GL_NEAREST);
depth_cubeMaps.at(i)->setMagFilter(GL_NEAREST); depth_cubeMaps.at(i)->setMagFilter(GL_NEAREST);
depth_cubeMaps.at(i)->setWrapS(GL_CLAMP_TO_EDGE); depth_cubeMaps.at(i)->setWrapS(GL_CLAMP_TO_EDGE);
@ -66,12 +81,17 @@ void Graphics::init(Level* level) {
framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject()); framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject());
depthTexture_cube = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT16)); lightingShader->use();
depthTexture_cube->setMinFilter(GL_NEAREST);
depthTexture_cube->setMagFilter(GL_NEAREST); lightingShader->setTexture("shadowMap", depthTexture, 1);
depthTexture_cube->setWrapS(GL_CLAMP_TO_EDGE);
depthTexture_cube->setWrapT(GL_CLAMP_TO_EDGE); if (level->getLights()->size() > 0) {
depthTexture_cube->setCompareMode(GL_COMPARE_REF_TO_TEXTURE); for(unsigned int i = 0; i<depth_cubeMaps.size(); i++){
// start with texture unit 2 because the first two are used by the texture and the directional shadow map
lightingShader->setTexture("shadowMap_cube" + std::to_string(i), depth_cubeMaps.at(i), i+2);
}
}
updateClosestLights();
} }
glm::uvec2 Graphics::getWindowSize() { glm::uvec2 Graphics::getWindowSize() {
@ -81,29 +101,35 @@ glm::uvec2 Graphics::getWindowSize() {
void Graphics::render(double time) void Graphics::render(double time)
{ {
// At first render shadows // At first render shadows
depthShader->use(); depthCubeShader->use();
depthCubeShader->setUniform("farPlane", farPlane);
// render depth textures for point lights // render depth textures for point lights
glViewport(0, 0, cube_size, cube_size); 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::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 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(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(); framebuffer_cube->bind();
//for (unsigned int i_pointlight = 0; i_pointlight<level->getLights()->size(); i_pointlight++) { for (unsigned int i_pointlight = 0; i_pointlight<closestLights.size() && i_pointlight < maxShadowRenderCount; i_pointlight++) {
for (unsigned int i_pointlight = 0; i_pointlight<1 && i_pointlight<level->getLights()->size(); i_pointlight++) {
// render each side of the cube // render each side of the cube
for (int i_face = 0; i_face<6; i_face++) { for (int i_face = 0; i_face<6; i_face++) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i_face, depth_cubeMaps.at(i_pointlight)->getObjectName(), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i_face, depth_cubeMaps.at(i_pointlight)->getObjectName(), 0);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
glm::mat4 depthViewProjectionMatrix_face = depthProjectionMatrix_pointlights * glm::lookAt(level->getLights()->at(i_pointlight).getPosition(), glm::mat4 viewMatrix = glm::lookAt(closestLights.at(i_pointlight).getPosition(),
level->getLights()->at(i_pointlight).getPosition() + looking_directions[i_face], glm::vec3(0.0f, 1.0f, 0.0f)); closestLights.at(i_pointlight).getPosition() + looking_directions[i_face], upvectors[i_face]);
level->render(depthShader, false, &depthViewProjectionMatrix_face); glm::mat4 depthViewProjectionMatrix_face = depthProjectionMatrix_pointlights * viewMatrix;
std::vector<glm::mat4> viewMatrixVector = std::vector<glm::mat4>();
viewMatrixVector.push_back(viewMatrix);
level->render(depthCubeShader, false, &depthViewProjectionMatrix_face, &viewMatrixVector);
if (!framebuffer_cube->isFrameBufferObjectComplete()) { if (!framebuffer_cube->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n"); printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
} }
} }
} }
// render depth texture for sun // render depth texture for sun
depthShader->use();
glViewport(0, 0, windowSize.x, windowSize.y); glViewport(0, 0, windowSize.x, windowSize.y);
// far pass // far pass
@ -123,18 +149,15 @@ void Graphics::render(double time)
lightingShader->use(); lightingShader->use();
if (level->getLights()->size() > 0) {
lightingShader->setTexture("shadowMap_cube", depth_cubeMaps.at(0), 4);
}
//set lighting parameters //set lighting parameters
// TODO look into doing this less often, offload to another thread? // 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? // TODO figure out how to deal with bigger numbers of lights. load the nearest on demand?
double nextUpdate = lastUpdate + lightUpdateDelay; double nextUpdate = lastUpdate + lightUpdateDelay;
if (time >= nextUpdate) if (time >= nextUpdate)
{ {
updateLights(); updateShaderLights();
lastUpdate = time; lastUpdate = time;
} }
@ -146,9 +169,6 @@ void Graphics::render(double time)
0.5, 0.5, 0.5, 1.0 0.5, 0.5, 0.5, 1.0
); );
glm::mat4 depthBiasVP = biasMatrix*depthViewProjectionMatrix; glm::mat4 depthBiasVP = biasMatrix*depthViewProjectionMatrix;
lightingShader->setTexture("shadowMap", depthTexture, 1);
lightingShader->setUniform("farPlane", farPlane); lightingShader->setUniform("farPlane", farPlane);
// set fog Parameters // set fog Parameters
@ -157,7 +177,7 @@ void Graphics::render(double time)
// set Material Parameters // set Material Parameters
lightingShader->setUniform("ambientColor", level->getAmbientLight()); lightingShader->setUniform("ambientColor", level->getAmbientLight());
lightingShader->setUniform("camera", level->getCameraPosition()); lightingShader->setUniform("camera", level->getPhysics()->getCameraPosition());
//set view and projection matrix //set view and projection matrix
glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level); glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level);
@ -169,28 +189,49 @@ void Graphics::render(double time)
level->render(lightingShader, true, &lightingViewProjectionMatrix, &shadowVPs); level->render(lightingShader, true, &lightingViewProjectionMatrix, &shadowVPs);
} }
void Graphics::updateLights() { bool Graphics::compareLightDistances(Light a, Light b) {
if (level->getLights()->size() > 0) { if (glm::distance(this->level->getCameraCenter()->getPosition(), a.getPosition()) <
lightingShader->setUniform("lightCount", (int) level->getLights()->size()); glm::distance(this->level->getCameraCenter()->getPosition(), b.getPosition())) {
return true;
}
else {
return false;
}
}
void Graphics::updateClosestLights() {
closestLights = std::vector<Light>(*level->getLights());
std::sort(closestLights.begin(),
closestLights.end(),
[this](Light a, Light b) {return compareLightDistances(a, b); });
closestLights = std::vector<Light>(&closestLights[0],
&closestLights[31]);
}
void Graphics::updateShaderLights() {
updateClosestLights();
if (closestLights.size() > 0) {
lightingShader->setUniform("lightCount", (int) closestLights.size());
lightingShader->setUniform("maxShadowRenderCount", std::min((int) closestLights.size(), (int)maxShadowRenderCount));
// Build light position array // Build light position array
glm::vec3 lightSources[level->getLights()->size()]; glm::vec3 lightSources[closestLights.size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) { for(unsigned int i = 0; i<closestLights.size(); i++) {
lightSources[i] = level->getLights()->at(i).getPosition(); lightSources[i] = closestLights.at(i).getPosition();
} }
glUniform3fv(lightingShader->getUniformLocation("lightSources"), glUniform3fv(lightingShader->getUniformLocation("lightSources"),
sizeof(lightSources), (GLfloat*) lightSources); sizeof(lightSources), (GLfloat*) lightSources);
// Build light colour array // Build light colour array
glm::vec3 lightColours[level->getLights()->size()]; glm::vec3 lightColours[closestLights.size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) { for(unsigned int i = 0; i<closestLights.size(); i++) {
lightColours[i] = level->getLights()->at(i).getColour(); lightColours[i] = closestLights.at(i).getColour();
} }
glUniform3fv(lightingShader->getUniformLocation("lightColors"), glUniform3fv(lightingShader->getUniformLocation("lightColors"),
sizeof(lightColours), (GLfloat*) lightColours); sizeof(lightColours), (GLfloat*) lightColours);
// Build light attenuation array // Build light attenuation array
float lightIntensities[level->getLights()->size()]; float lightIntensities[closestLights.size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) { for(unsigned int i = 0; i<closestLights.size(); i++) {
lightIntensities[i] = level->getLights()->at(i).getIntensity(); lightIntensities[i] = closestLights.at(i).getIntensity();
} }
glUniform1fv(lightingShader->getUniformLocation("lightIntensities"), glUniform1fv(lightingShader->getUniformLocation("lightIntensities"),
sizeof(lightIntensities), (GLfloat*) lightIntensities); sizeof(lightIntensities), (GLfloat*) lightIntensities);
@ -213,7 +254,8 @@ void Graphics::resize(glm::uvec2 windowSize) {
glm::mat4 Graphics::buildViewMatrix(Level* level) { glm::mat4 Graphics::buildViewMatrix(Level* level) {
//construct lookAt (cameraPosition = cameraCenter + cameraVector) //construct lookAt (cameraPosition = cameraCenter + cameraVector)
return glm::lookAt(level->getCamera()->getPosition(), level->getCamera()->getPosition() + level->getCamera()->getDirection(), glm::vec3(0.0f, 1.0f, 0.0f)); if(level->getCamera()->getIsPhysicsCamera())
return glm::lookAt(level->getCamera()->getPosition(), level->getCamera()->getPosition() + level->getCamera()->getDirection(), glm::vec3(0.0f, 1.0f, 0.0f));
return glm::lookAt((level->getCameraCenter()->getPosition() + level->getCamera()->getVector()), return glm::lookAt((level->getCameraCenter()->getPosition() + level->getCamera()->getVector()),
level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f)); level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f));
@ -222,3 +264,25 @@ glm::mat4 Graphics::buildViewMatrix(Level* level) {
float Graphics::getFarPlane() { float Graphics::getFarPlane() {
return farPlane; return farPlane;
} }
void Graphics::saveDepthBufferToDisk(int face, std::string filename) {
printf("Starting saving of depth buffer...\n");
float *depthbuffer = new float[1024*1024];
std::vector<unsigned char> image (1024 * 1024 * 4);
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_DEPTH_COMPONENT, GL_FLOAT, depthbuffer);
for (unsigned int i = 0; i<1024*1024; i++) {
image[i * 4 + 0] = depthbuffer[i] * 255;
image[i * 4 + 1] = depthbuffer[i] * 255;
image[i * 4 + 2] = depthbuffer[i] * 255;
image[i * 4 + 3] = 255;
}
unsigned error = lodepng::encode(filename.c_str(), image, 1024, 1024);
if (error) {
std::cout << "Encoder error " << error << ": " << lodepng_error_text(error) << std::endl;
}
else {
printf("Saving complete!\n");
}
delete [] depthbuffer;
}

View File

@ -10,7 +10,7 @@
class Graphics { class Graphics {
public: public:
Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size); Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, unsigned int maxShadowRenderCount);
Graphics(); Graphics();
void init(Level* level); void init(Level* level);
void render(double time); void render(double time);
@ -19,20 +19,27 @@ class Graphics {
void resize(glm::uvec2 windowSize); void resize(glm::uvec2 windowSize);
float getFarPlane(); float getFarPlane();
private: private:
void updateLights(); void updateShaderLights();
void updateClosestLights();
bool compareLightDistances(Light a, Light b);
void saveDepthBufferToDisk(int face, std::string);
double lastUpdate; double lastUpdate;
glm::uvec2 windowSize; glm::uvec2 windowSize;
float nearPlane; float nearPlane;
float farPlane; float farPlane;
// pointer to either use the vector from the level or from here
std::vector<Light> closestLights;
ACGL::OpenGL::SharedShaderProgram lightingShader; ACGL::OpenGL::SharedShaderProgram lightingShader;
ACGL::OpenGL::SharedShaderProgram depthCubeShader;
ACGL::OpenGL::SharedShaderProgram depthShader; ACGL::OpenGL::SharedShaderProgram depthShader;
ACGL::OpenGL::SharedTexture2D depthTexture; ACGL::OpenGL::SharedTexture2D depthTexture;
ACGL::OpenGL::SharedFrameBufferObject framebuffer; ACGL::OpenGL::SharedFrameBufferObject framebuffer;
std::vector<ACGL::OpenGL::SharedTextureCubeMap> depth_cubeMaps; std::vector<ACGL::OpenGL::SharedTextureCubeMap> depth_cubeMaps;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube; ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube;
ACGL::OpenGL::SharedTexture2D depthTexture_cube;
int cube_size; int cube_size;
unsigned int maxShadowRenderCount;
Level* level; Level* level;
int number_of_texture_units = 0;
}; };
#endif #endif

View File

@ -56,7 +56,7 @@ void Level::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass,
} }
} }
void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPressed, bool sPressed, bool dPressed) { void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPressed, bool sPressed, bool dPressed,bool kPressed, bool lPressed) {
// Ignore first two mouse updates, because they are incorrect // Ignore first two mouse updates, because they are incorrect
// DON'T try to move this functionallity elsewhere // DON'T try to move this functionallity elsewhere
static int i = 0; static int i = 0;
@ -84,6 +84,11 @@ void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPre
physics.rollRight(camera.getVector(),strength); physics.rollRight(camera.getVector(),strength);
} }
if(kPressed)
camera.setIsPhysicsCamera(true);
if(lPressed)
camera.setIsPhysicsCamera(false);
physics.takeUpdateStep(runTime); physics.takeUpdateStep(runTime);
cameraCenter->setPosition(physics.getPos(0)); cameraCenter->setPosition(physics.getPos(0));

View File

@ -24,7 +24,7 @@ class Level {
Level(); Level();
~Level(); ~Level();
void load(); void load();
void update(float runTime, glm::vec2 mouseDelta,bool wPressed, bool aPressed,bool sPressed, bool dPressed); void update(float runTime, glm::vec2 mouseDelta,bool wPressed, bool aPressed,bool sPressed, bool dPressed, bool kPressed, bool lPressed);
void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass, void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass,
glm::mat4* viewProjectionMatrix, std::vector<glm::mat4>* shadowVPs=0); glm::mat4* viewProjectionMatrix, std::vector<glm::mat4>* shadowVPs=0);
glm::vec3 getAmbientLight(); glm::vec3 getAmbientLight();

View File

@ -5,7 +5,7 @@ Loader::Loader() {
} }
void Loader::loadConfig(Application* application) { void Loader::loadConfig(Application* application) {
int windowWidth, windowHeight, shadowCubeSize; int windowWidth, windowHeight, shadowCubeSize, maxShadowRenderCount;
float farPlane; float farPlane;
std::string compositionsPath, shaderPath, geometryPath, texturePath, scriptPath, heightmapPath, levelXmlPath; std::string compositionsPath, shaderPath, geometryPath, texturePath, scriptPath, heightmapPath, levelXmlPath;
XMLDocument* config = new XMLDocument(); XMLDocument* config = new XMLDocument();
@ -20,6 +20,7 @@ void Loader::loadConfig(Application* application) {
errorCheck(resolution->FirstChildElement("height")->QueryIntText(&windowHeight)); errorCheck(resolution->FirstChildElement("height")->QueryIntText(&windowHeight));
errorCheck(config->FirstChildElement("shadowCubeSize")->QueryIntText(&shadowCubeSize)); errorCheck(config->FirstChildElement("shadowCubeSize")->QueryIntText(&shadowCubeSize));
errorCheck(config->FirstChildElement("farPlane")->QueryFloatText(&farPlane)); errorCheck(config->FirstChildElement("farPlane")->QueryFloatText(&farPlane));
errorCheck(config->FirstChildElement("maxShadowRenderCount")->QueryIntText(&maxShadowRenderCount));
const char* charCompositionsPath = config->FirstChildElement("compositionsPath")->GetText(); const char* charCompositionsPath = config->FirstChildElement("compositionsPath")->GetText();
if(charCompositionsPath == NULL){ if(charCompositionsPath == NULL){
@ -74,6 +75,7 @@ void Loader::loadConfig(Application* application) {
application->setWindowHeight(windowHeight); application->setWindowHeight(windowHeight);
application->setShadowCubeSize(shadowCubeSize); application->setShadowCubeSize(shadowCubeSize);
application->setFarPlane(farPlane); application->setFarPlane(farPlane);
application->setMaxShadowRenderCount(maxShadowRenderCount);
application->setCompositionsPath(compositionsPath); application->setCompositionsPath(compositionsPath);
application->setShaderPath(shaderPath); application->setShaderPath(shaderPath);
application->setGeometryPath(geometryPath); application->setGeometryPath(geometryPath);

View File

@ -161,16 +161,19 @@ int main( int argc, char *argv[] )
int stateA = glfwGetKey(window, GLFW_KEY_A); int stateA = glfwGetKey(window, GLFW_KEY_A);
int stateS = glfwGetKey(window, GLFW_KEY_S); int stateS = glfwGetKey(window, GLFW_KEY_S);
int stateD = glfwGetKey(window, GLFW_KEY_D); int stateD = glfwGetKey(window, GLFW_KEY_D);
int stateK = glfwGetKey(window, GLFW_KEY_K);
int stateL = glfwGetKey(window, GLFW_KEY_L);
double xpos, ypos; double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos); glfwGetCursorPos(window, &xpos, &ypos);
glfwSetCursorPos(window, app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2); glfwSetCursorPos(window, app.getGraphics()->getWindowSize().x/2, app.getGraphics()->getWindowSize().y/2);
app.getLevel()->update(now - lastUpdate, app.getLevel()->update(now - lastUpdate,
glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2, glm::vec2((float)ypos-app.getGraphics()->getWindowSize().y/2,
(float)xpos-app.getGraphics()->getWindowSize().x/2), (float)xpos-app.getGraphics()->getWindowSize().x/2),
stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS); stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS,stateK == GLFW_PRESS,stateL == GLFW_PRESS);
} }
else { else {
app.getLevel()->update(now - lastUpdate, glm::vec2(0.0f, 0.0f), false, false, false, false); app.getLevel()->update(now - lastUpdate, glm::vec2(0.0f, 0.0f), false, false, false, false,false,false);
if (app.isLocked()) { if (app.isLocked()) {
app.ignoredOneMouseUpdate(); app.ignoredOneMouseUpdate();
} }

View File

@ -14,7 +14,7 @@ Object::~Object() {
} }
void Object::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass, void Object::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass,
glm::mat4* viewProjectionMatrix, std::vector<glm::mat4>* shadowVPs) { glm::mat4* viewProjectionMatrix, std::vector<glm::mat4>* additionalMatrices) {
if (!renderable) { if (!renderable) {
return; return;
} }
@ -27,15 +27,20 @@ void Object::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass,
shader->setUniform("shininess", material.getShininess()); shader->setUniform("shininess", material.getShininess());
shader->setTexture("uTexture", material.getReference(), 0); shader->setTexture("uTexture", material.getReference(), 0);
// set model matrix // set model matrix
shader->setUniform( "modelMatrix", modelMatrix); shader->setUniform("modelMatrix", modelMatrix);
// set shadowMVPs // set shadowMVPs
glm::mat4 shadowMVPs[5]; glm::mat4 shadowMVPs[5];
for(unsigned int i = 0; (i<shadowVPs->size() && i<5); i++) { for(unsigned int i = 0; (i<additionalMatrices->size() && i<5); i++) {
shadowMVPs[i] = shadowVPs->at(i) * modelMatrix; shadowMVPs[i] = additionalMatrices->at(i) * modelMatrix;
} }
glUniformMatrix4fv(shader->getUniformLocation("shadowMVPs"), glUniformMatrix4fv(shader->getUniformLocation("shadowMVPs"),
sizeof(shadowMVPs), false, (GLfloat*) shadowMVPs); sizeof(shadowMVPs), false, (GLfloat*) shadowMVPs);
} }
else {
if (additionalMatrices) {
shader->setUniform("modelViewMatrix", additionalMatrices->at(0) * modelMatrix);
}
}
glm::mat4 mvp = (*viewProjectionMatrix) * modelMatrix; glm::mat4 mvp = (*viewProjectionMatrix) * modelMatrix;
shader->setUniform("modelViewProjectionMatrix", mvp); shader->setUniform("modelViewProjectionMatrix", mvp);
// draw // draw

View File

@ -16,7 +16,7 @@ class Object : public Entity {
Object(); Object();
~Object(); ~Object();
void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass, void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass,
glm::mat4* viewProjcetionMatrix, std::vector<glm::mat4>* shadowVPs); glm::mat4* viewProjcetionMatrix, std::vector<glm::mat4>* additionalMatrices);
private: private:
Model model; Model model;
Material material; Material material;

View File

@ -204,7 +204,7 @@ void Physics::addTriangleMeshBody(Entity entity, std::string path, float mass, f
btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z))); btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z)));
btVector3 inertia(0,0,0); btVector3 inertia(0,0,0);
if(mass != 0.0 && rotate) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable) if(mass != 0.0)
{ {
shape->calculateLocalInertia((btScalar)mass,inertia); shape->calculateLocalInertia((btScalar)mass,inertia);
} }
@ -219,6 +219,10 @@ void Physics::addTriangleMeshBody(Entity entity, std::string path, float mass, f
world->addRigidBody(body,COL_OBJECTS, objectsPhysicsCollision); world->addRigidBody(body,COL_OBJECTS, objectsPhysicsCollision);
if(!rotate)//rotate lets certain objects get inertia (0,0,0) (not rotateable)
{
body->setAngularFactor(btVector3(0,0,0));
}
if(bodies.size() != indice) if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" ); throw std::invalid_argument( "Bodies out of Sync" );
@ -237,7 +241,7 @@ void Physics::addButton(float width, float height, float length, Entity entity,
btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z))); btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z)));
btVector3 inertia(0,0,0); btVector3 inertia(0,0,0);
if(mass != 0.0 && rotate) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable) if(mass != 0.0) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable)
{ {
box->calculateLocalInertia((btScalar)mass,inertia); box->calculateLocalInertia((btScalar)mass,inertia);
} }
@ -251,6 +255,11 @@ void Physics::addButton(float width, float height, float length, Entity entity,
bodies.push_back(body); bodies.push_back(body);
if(!rotate)
{
body->setAngularFactor(btVector3(0,0,0));
}
if(bodies.size() != indice) if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" ); throw std::invalid_argument( "Bodies out of Sync" );
} }
@ -266,11 +275,12 @@ void Physics::addBox(float width, float height, float length, Entity entity, flo
btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z))); btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(glmQuat.x,glmQuat.y,glmQuat.z,glmQuat.w),btVector3(entity.getPosition().x,entity.getPosition().y,entity.getPosition().z)));
btVector3 inertia(0,0,0); btVector3 inertia(0,0,0);
if(mass != 0.0 && rotate) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable) if(mass != 0.0) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable)
{ {
box->calculateLocalInertia((btScalar)mass,inertia); box->calculateLocalInertia((btScalar)mass,inertia);
} }
btRigidBody::btRigidBodyConstructionInfo info(mass,motion,box,inertia); btRigidBody::btRigidBodyConstructionInfo info(mass,motion,box,inertia);
btRigidBody* body = new btRigidBody(info); btRigidBody* body = new btRigidBody(info);
@ -281,6 +291,11 @@ void Physics::addBox(float width, float height, float length, Entity entity, flo
bodies.push_back(body); bodies.push_back(body);
if(!rotate)
{
body->setAngularFactor(btVector3(0,0,0));
}
if(bodies.size() != indice) if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" ); throw std::invalid_argument( "Bodies out of Sync" );
} }
@ -311,6 +326,11 @@ void Physics::addSphere(float rad, Entity entity, float mass, float dampningL, f
bodies.push_back(body); bodies.push_back(body);
if(!rotate)//rotate lets certain objects get inertia (0,0,0) (not rotateable)
{
body->setAngularFactor(btVector3(0,0,0));
}
body->setSleepingThresholds(0,0); body->setSleepingThresholds(0,0);
if(bodies.size() != indice) if(bodies.size() != indice)
@ -334,6 +354,9 @@ void Physics::addCamera() //Camera Creator automatically called when player is c
cameraBody->setDamping(0.9,0.5); //this damping factor leaves a relativly smoothe system cameraBody->setDamping(0.9,0.5); //this damping factor leaves a relativly smoothe system
info.m_friction = 0;
info.m_restitution = 0;
world->addRigidBody(cameraBody,COL_OBJECTS, objectsPhysicsCollision); world->addRigidBody(cameraBody,COL_OBJECTS, objectsPhysicsCollision);
cameraBody->setGravity(btVector3(0,0,0)); cameraBody->setGravity(btVector3(0,0,0));