This commit is contained in:
sfroitzheim 2015-02-13 18:18:03 +01:00
commit 1f86981271
25 changed files with 397 additions and 107 deletions

1
.gitignore vendored
View File

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

View File

@ -1,7 +1,7 @@
<!-- Rotations around the three axes are given in degrees.
The objects are first rotated around the z-, then y- and then x-axis. -->
<!-- Marble -->
<!-- Marble: Do not change!(except for mass)-->
<composition>
<typeID>20</typeID>
<ignoreHeightmap>false</ignoreHeightmap>
@ -69,7 +69,7 @@
</object>
<light>
<xOffset>0.0</xOffset>
<yOffset>3</yOffset>
<yOffset>2</yOffset>
<zOffset>0.0</zOffset>
<rColour>1.0</rColour>
<gColour>1.0</gColour>
@ -415,7 +415,7 @@
<yRot>0.0</yRot>
<zRot>0.0</zRot>
<scale>1.5</scale>
<mass>0.0</mass>
<mass>100.0</mass>
</object>
</composition>

View File

@ -1315,6 +1315,13 @@
<idGreen>1</idGreen>
<idBlue>205</idBlue>
<typeID>120</typeID>
<positionConstraint>
<objectNum>0</objectNum>
<xPosition>159.5</xPosition>
<yPosition>30</yPosition>
<zPosition>17.5</zPosition>
<strength>10.0</strength>
</positionConstraint>
<trigger>
<name>-</name>
<xPosition>0</xPosition>
@ -2881,6 +2888,13 @@
<idGreen>1</idGreen>
<idBlue>133</idBlue>
<typeID>220</typeID>
<positionConstraint>
<objectNum>0</objectNum>
<xPosition>81.5</xPosition>
<yPosition>25.0</yPosition>
<zPosition>17.5.0</zPosition>
<strength>1000.0</strength>
</positionConstraint>
<trigger>
<name>-</name>
<xPosition>0</xPosition>

View File

@ -5,3 +5,8 @@ This will be a Marble Race Game developed for the Softwarepraktikum at the RWTH
##Building
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.
##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
out float fragmentDepth;
out float gl_FragDepth;
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 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 float ambientFactor;
uniform float diffuseFactor;
@ -17,6 +26,7 @@ uniform float specularFactor;
uniform vec3 camera;
uniform float shininess;
uniform int lightCount;
uniform int maxShadowRenderCount;
uniform vec3 directionalLightVector;
uniform vec3 directionalColor;
uniform float directionalIntensity;
@ -70,9 +80,10 @@ float samplePointShadow(samplerCubeShadow shadowMap, vec3 lightDirection) {
float A = -(farPlane+nearPlane)/(farPlane-nearPlane);
float B = -2*(farPlane*nearPlane)/(farPlane - nearPlane);
float compValue = 0.5*(-A*length(lightDirection) + B)/length(lightDirection) + 0.5;
float bias = 0.005;
vec3 vector = vec3(-lightDirection.x, -lightDirection.y, lightDirection.z);
return texture(shadowMap, vec4(vector , compValue - bias));
float bias = 0.001*tan(acos(clamp(dot(vNormal, -directionalLightVector), 0.0, 1.0)));
bias = clamp(bias, 0.0, 0.01);
//return texture(shadowMap, vec4(lightDirection , length(lightDirection)/farPlane - bias));
return texture(shadowMap, vec4(lightDirection , compValue - bias));
}
float distanceToBorder(vec2 vector) {
@ -91,11 +102,13 @@ void main()
// direction lighting
if(length(directionalLightVector)>0.0f) {
vec3 directionalVector = normalize(directionalLightVector);
float directionalVisibility = sampleDirectionalShadow(shadowMap, shadowCoord);
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));
specularColor += clamp(pow((dot((cameraVector+directionalVector),normalize(vNormal))/(length(cameraVector+directionalVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*directionalIntensity*directionalColor;
specularColor += clamp(pow((dot((cameraVector+directionalVector),normalize(vNormal))/
(length(cameraVector+directionalVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*directionalIntensity*directionalColor*directionalVisibility;
}
// point lights
@ -103,24 +116,50 @@ void main()
for(int i = 0; i<lightCount; i++) {
vec3 lightDirection = vec3(fragPosition) - lightSources[i];
float distance = length(lightDirection);
float pointVisibility = 1.0f;
// 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));
float intensity = clamp(exp(-(1/lightIntensities[i])*distance), 0.0, 1.0);
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));
specularColor += clamp(pow((dot((cameraVector+lightVector),normalize(vNormal))/(length(cameraVector+lightVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*intensity*lightColors[i];
visibility = samplePointShadow(shadowMap_cube, lightDirection);
specularColor += clamp(pow((dot((cameraVector+lightVector),normalize(vNormal))/
(length(cameraVector+lightVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*intensity*lightColors[i]*pointVisibility;
}
}
// shadows
visibility *= sampleDirectionalShadow(shadowMap, shadowCoord);
specularColor *= visibility;
diffuseColor *= visibility;
vec3 finalColor = specularColor + diffuseColor + ambientColor;
float distanceCameraCenter = distance(cameraCenter, vec3(fragPosition));

View File

@ -5,7 +5,7 @@ Application::Application() {
Loader loader = Loader();
//load the config.xml
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()
@ -14,7 +14,8 @@ void Application::init()
std::srand(std::time(NULL));
// choose Level TODO: Choose this in a menu
std::string heightmapFilePath = heightmapPath + "heightmapLvl1.png";
this->level = Level(heightmapFilePath);
std::string levelXmlFilePath = levelXmlPath + "Level1.xml";
this->level = Level(heightmapFilePath, levelXmlFilePath);
level.getPhysics()->init(geometryPath);
// Don't change this!
ignoredMouseUpdates = 0;
@ -31,7 +32,7 @@ void Application::init()
// load Level
level.load();
Loader loader = Loader();
std::string levelXmlFilePath = levelXmlPath + "Level1.xml";
loader.load(levelXmlFilePath, &level, compositionsPath, scriptPath);
graphics.init(&level);
@ -122,3 +123,7 @@ void Application::setHeightmapPath(std::string heightmapPath) {
void Application::setLevelXmlPath(std::string 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 setShadowCubeSize(int shadowCubeSize);
void setFarPlane(float farPlane);
void setMaxShadowRenderCount(int count);
void setCompositionsPath(std::string compositionsPath);
void setShaderPath(std::string shaderPath);
void setGeometryPath(std::string geometryPath);
@ -38,6 +39,7 @@ class Application {
int windowWidth;
int windowHeight;
int shadowCubeSize;
int maxShadowRenderCount;
float farPlane;
std::string compositionsPath;
std::string shaderPath;

View File

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

View File

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

View File

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

View File

@ -1,7 +1,9 @@
#include "graphics.hh"
#include "lodepng.h"
#include <iomanip>
#include <sstream>
#include <functional>
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
@ -9,11 +11,14 @@ using namespace ACGL::OpenGL;
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->nearPlane = nearPlane;
this->farPlane = farPlane;
this->cube_size = cube_size;
this->maxShadowRenderCount = maxShadowRenderCount;
}
Graphics::Graphics() {
@ -40,8 +45,11 @@ void Graphics::init(Level* level) {
depthShader = ShaderProgramCreator("depth")
.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->setMagFilter(GL_NEAREST);
depthTexture->setWrapS(GL_CLAMP_TO_EDGE);
@ -51,12 +59,19 @@ void Graphics::init(Level* level) {
framebuffer = SharedFrameBufferObject(new FrameBufferObject());
framebuffer->setDepthTexture(depthTexture);
framebuffer->validate();
/*depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(level->getLights()->size());
for (unsigned int i = 0; i<depth_cubeMaps.size(); i++) {*/
depth_cubeMaps = std::vector<ACGL::OpenGL::SharedTextureCubeMap>(std::min(int(level->getLights()->size()), 1));
for (unsigned int i = 0; i<1 && i<depth_cubeMaps.size(); i++) {
depth_cubeMaps.at(i) = SharedTextureCubeMap(new TextureCubeMap(glm::vec2(cube_size, cube_size), GL_DEPTH_COMPONENT16));
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 < 12) {
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)->setMagFilter(GL_NEAREST);
depth_cubeMaps.at(i)->setWrapS(GL_CLAMP_TO_EDGE);
@ -65,13 +80,18 @@ void Graphics::init(Level* level) {
}
framebuffer_cube = SharedFrameBufferObject(new FrameBufferObject());
depthTexture_cube = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH_COMPONENT16));
depthTexture_cube->setMinFilter(GL_NEAREST);
depthTexture_cube->setMagFilter(GL_NEAREST);
depthTexture_cube->setWrapS(GL_CLAMP_TO_EDGE);
depthTexture_cube->setWrapT(GL_CLAMP_TO_EDGE);
depthTexture_cube->setCompareMode(GL_COMPARE_REF_TO_TEXTURE);
lightingShader->use();
lightingShader->setTexture("shadowMap", depthTexture, 1);
if (level->getLights()->size() > 0) {
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() {
@ -81,29 +101,35 @@ glm::uvec2 Graphics::getWindowSize() {
void Graphics::render(double time)
{
// At first render shadows
depthShader->use();
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 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_pointlight<level->getLights()->size(); i_pointlight++) {
for (unsigned int i_pointlight = 0; i_pointlight<1 && i_pointlight<level->getLights()->size(); i_pointlight++) {
for (unsigned int i_pointlight = 0; i_pointlight<closestLights.size() && i_pointlight < maxShadowRenderCount; i_pointlight++) {
// render each side of the cube
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);
glClear(GL_DEPTH_BUFFER_BIT);
glm::mat4 depthViewProjectionMatrix_face = depthProjectionMatrix_pointlights * glm::lookAt(level->getLights()->at(i_pointlight).getPosition(),
level->getLights()->at(i_pointlight).getPosition() + looking_directions[i_face], glm::vec3(0.0f, 1.0f, 0.0f));
level->render(depthShader, false, &depthViewProjectionMatrix_face);
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<glm::mat4> viewMatrixVector = std::vector<glm::mat4>();
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 texture for sun
depthShader->use();
glViewport(0, 0, windowSize.x, windowSize.y);
// far pass
@ -122,19 +148,16 @@ void Graphics::render(double time)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lightingShader->use();
if (level->getLights()->size() > 0) {
lightingShader->setTexture("shadowMap_cube", depth_cubeMaps.at(0), 4);
}
//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();
updateShaderLights();
lastUpdate = time;
}
@ -146,9 +169,6 @@ void Graphics::render(double time)
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasVP = biasMatrix*depthViewProjectionMatrix;
lightingShader->setTexture("shadowMap", depthTexture, 1);
lightingShader->setUniform("farPlane", farPlane);
// set fog Parameters
@ -157,7 +177,7 @@ void Graphics::render(double time)
// set Material Parameters
lightingShader->setUniform("ambientColor", level->getAmbientLight());
lightingShader->setUniform("camera", level->getCameraPosition());
lightingShader->setUniform("camera", level->getPhysics()->getCameraPosition());
//set view and projection matrix
glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level);
@ -169,28 +189,51 @@ void Graphics::render(double time)
level->render(lightingShader, true, &lightingViewProjectionMatrix, &shadowVPs);
}
void Graphics::updateLights() {
if (level->getLights()->size() > 0) {
lightingShader->setUniform("lightCount", (int) level->getLights()->size());
bool Graphics::compareLightDistances(Light a, Light b) {
if (glm::distance(this->level->getCameraCenter()->getPosition(), a.getPosition()) <
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); });
if (level->getLights()->size() > 32) {
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
glm::vec3 lightSources[level->getLights()->size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) {
lightSources[i] = level->getLights()->at(i).getPosition();
glm::vec3 lightSources[closestLights.size()];
for(unsigned int i = 0; i<closestLights.size(); i++) {
lightSources[i] = closestLights.at(i).getPosition();
}
glUniform3fv(lightingShader->getUniformLocation("lightSources"),
sizeof(lightSources), (GLfloat*) lightSources);
// Build light colour array
glm::vec3 lightColours[level->getLights()->size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) {
lightColours[i] = level->getLights()->at(i).getColour();
glm::vec3 lightColours[closestLights.size()];
for(unsigned int i = 0; i<closestLights.size(); i++) {
lightColours[i] = closestLights.at(i).getColour();
}
glUniform3fv(lightingShader->getUniformLocation("lightColors"),
sizeof(lightColours), (GLfloat*) lightColours);
// Build light attenuation array
float lightIntensities[level->getLights()->size()];
for(unsigned int i = 0; i<level->getLights()->size(); i++) {
lightIntensities[i] = level->getLights()->at(i).getIntensity();
float lightIntensities[closestLights.size()];
for(unsigned int i = 0; i<closestLights.size(); i++) {
lightIntensities[i] = closestLights.at(i).getIntensity();
}
glUniform1fv(lightingShader->getUniformLocation("lightIntensities"),
sizeof(lightIntensities), (GLfloat*) lightIntensities);
@ -213,7 +256,8 @@ void Graphics::resize(glm::uvec2 windowSize) {
glm::mat4 Graphics::buildViewMatrix(Level* level) {
//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()),
level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f));
@ -222,3 +266,25 @@ glm::mat4 Graphics::buildViewMatrix(Level* level) {
float Graphics::getFarPlane() {
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 {
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();
void init(Level* level);
void render(double time);
@ -19,20 +19,27 @@ class Graphics {
void resize(glm::uvec2 windowSize);
float getFarPlane();
private:
void updateLights();
void updateShaderLights();
void updateClosestLights();
bool compareLightDistances(Light a, Light b);
void saveDepthBufferToDisk(int face, std::string);
double lastUpdate;
glm::uvec2 windowSize;
float nearPlane;
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 depthCubeShader;
ACGL::OpenGL::SharedShaderProgram depthShader;
ACGL::OpenGL::SharedTexture2D depthTexture;
ACGL::OpenGL::SharedFrameBufferObject framebuffer;
std::vector<ACGL::OpenGL::SharedTextureCubeMap> depth_cubeMaps;
ACGL::OpenGL::SharedFrameBufferObject framebuffer_cube;
ACGL::OpenGL::SharedTexture2D depthTexture_cube;
int cube_size;
unsigned int maxShadowRenderCount;
Level* level;
int number_of_texture_units = 0;
};
#endif

View File

@ -1,11 +1,13 @@
#include "level.hh"
#include "loader.hh"
#include <string>
Level::Level(std::string heightmapFilePath){
Level::Level(std::string heightmapFilePath, std::string xmlFilePath){
this->terrain = Terrain(heightmapFilePath);
// default value
skydomeSize = 50.0f;
physics = Physics();
this->xmlFilePath = xmlFilePath;
}
Level::Level() {
@ -54,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
// DON'T try to move this functionallity elsewhere
static int i = 0;
@ -64,7 +66,7 @@ void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPre
else {
mouseDelta.x = -mouseDelta.x;
camera.updateRotation(mouseDelta/100.0f);
physics.updateCameraPos(mouseDelta, 50);
physics.updateCameraPos(mouseDelta, 50, camera.getDistance());
camera.setPosition(physics.getCameraPosition());
camera.setDirection(physics.getCameraToPlayer());
@ -82,6 +84,11 @@ void Level::update(float runTime, glm::vec2 mouseDelta, bool wPressed, bool aPre
physics.rollRight(camera.getVector(),strength);
}
if(kPressed)
camera.setIsPhysicsCamera(true);
if(lPressed)
camera.setIsPhysicsCamera(false);
physics.takeUpdateStep(runTime);
cameraCenter->setPosition(physics.getPos(0));
@ -162,6 +169,12 @@ void Level::deleteObject(int objectIndex){
}
}
void Level::resetPlayer(){
Loader loader = Loader();
glm::vec3 newPosition = loader.reloadPlayerPosition(xmlFilePath, this);
//TODO cameraCenter.setPosition(newPosition);
}
void Level::setStrength(float strength) {
this->strength = strength;
}

View File

@ -20,11 +20,11 @@ extern "C" {
class Level {
public:
Level(std::string heightmapFilePath);
Level(std::string heightmapFilePath, std::string xmlFilePath);
Level();
~Level();
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,
glm::mat4* viewProjectionMatrix, std::vector<glm::mat4>* shadowVPs=0);
glm::vec3 getAmbientLight();
@ -55,6 +55,7 @@ class Level {
void addTrigger(Trigger trigger);
lua_State* getLuaState();
Terrain* getTerrain();
void resetPlayer();
private:
lua_State* luaState=nullptr;
std::vector<Object*> objects;
@ -71,6 +72,7 @@ class Level {
Terrain terrain;
float skydomeSize;
float strength;
std::string xmlFilePath;
};
#endif

View File

@ -5,7 +5,7 @@ Loader::Loader() {
}
void Loader::loadConfig(Application* application) {
int windowWidth, windowHeight, shadowCubeSize;
int windowWidth, windowHeight, shadowCubeSize, maxShadowRenderCount;
float farPlane;
std::string compositionsPath, shaderPath, geometryPath, texturePath, scriptPath, heightmapPath, levelXmlPath;
XMLDocument* config = new XMLDocument();
@ -20,6 +20,7 @@ void Loader::loadConfig(Application* application) {
errorCheck(resolution->FirstChildElement("height")->QueryIntText(&windowHeight));
errorCheck(config->FirstChildElement("shadowCubeSize")->QueryIntText(&shadowCubeSize));
errorCheck(config->FirstChildElement("farPlane")->QueryFloatText(&farPlane));
errorCheck(config->FirstChildElement("maxShadowRenderCount")->QueryIntText(&maxShadowRenderCount));
const char* charCompositionsPath = config->FirstChildElement("compositionsPath")->GetText();
if(charCompositionsPath == NULL){
@ -74,6 +75,7 @@ void Loader::loadConfig(Application* application) {
application->setWindowHeight(windowHeight);
application->setShadowCubeSize(shadowCubeSize);
application->setFarPlane(farPlane);
application->setMaxShadowRenderCount(maxShadowRenderCount);
application->setCompositionsPath(compositionsPath);
application->setShaderPath(shaderPath);
application->setGeometryPath(geometryPath);
@ -507,6 +509,38 @@ void Loader::load(std::string filePath, Level* level, std::string compositionsPa
}//positionConstraints
}
glm::vec3 Loader::reloadPlayerPosition(std::string filePath, Level* level){
XMLDocument* doc = new XMLDocument();
const char* xmlFile = filePath.c_str();
doc->LoadFile(xmlFile);
if (doc->ErrorID()!=0){
printf("Could not open ObjectSetupXml!\n");
exit(-1);
}
//iterate over all compositions in Level.xml
XMLElement* thisComposition = doc->FirstChildElement("composition");
for(; thisComposition; thisComposition=thisComposition->NextSiblingElement("composition")){
int thisType = 0;
errorCheck(thisComposition->FirstChildElement("typeID")->QueryIntText(&thisType));
if (thisType == 20){
float compXPos, compYOffset, compZPos;
errorCheck(thisComposition->FirstChildElement("xPos")->QueryFloatText(&compXPos));
errorCheck(thisComposition->FirstChildElement("yOffset")->QueryFloatText(&compYOffset));
errorCheck(thisComposition->FirstChildElement("zPos")->QueryFloatText(&compZPos));
compYOffset += level->getTerrain()->getHeightmap()[int(compXPos-0.5+0.5*level->getTerrain()->getHeightmapHeight())]
[int(compZPos-0.5+0.5*level->getTerrain()->getHeightmapWidth())];
glm::vec3 position = glm::vec3(compXPos, compYOffset, compZPos);
return position;
}
}
printf("Level.xml contains no player.");
exit(-1);
}
void Loader::errorCheck(XMLError error){
if (error) {
printf("XMLError: ");

View File

@ -7,8 +7,9 @@
class Loader {
public:
Loader();
void load(std::string filePath, Level* level, std::string compositionsPath, std::string scriptPath);
void loadConfig(Application* application);
void load(std::string filePath, Level* level, std::string compositionsPath, std::string scriptPath);
glm::vec3 reloadPlayerPosition(std::string filePath, Level* level);
private:
void errorCheck(tinyxml2::XMLError error);
};

View File

@ -161,16 +161,19 @@ int main( int argc, char *argv[] )
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,
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);
stateW == GLFW_PRESS,stateA == GLFW_PRESS,stateS == GLFW_PRESS,stateD == GLFW_PRESS,stateK == GLFW_PRESS,stateL == GLFW_PRESS);
}
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()) {
app.ignoredOneMouseUpdate();
}

View File

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

View File

@ -16,7 +16,7 @@ class Object : public Entity {
Object();
~Object();
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:
Model model;
Material material;

View File

@ -42,23 +42,32 @@ void Physics::takeUpdateStep(float timeDiff)
}
btVector3 position = cameraBody->getCenterOfMassPosition() - playerBall->getCenterOfMassPosition(); //gets a vector from the player to the camera
btVector3 position = cameraBody->getCenterOfMassPosition() - playerBall->getCenterOfMassPosition(); //gets a vector from the player to the camera
position.normalize();
position *= 5;
position += playerBall->getCenterOfMassPosition(); //is the position 5 units away from the player in the direction of the camera
position *= cameraDistance;
position += playerBall->getCenterOfMassPosition(); //is the position cameraDistance away from the player in the direction of the camera
//prevent the camera from being dragged along on the ground
if (position.getY() < playerBall->getCenterOfMassPosition().getY() + 1)
position.setY(playerBall->getCenterOfMassPosition().getY() + 1);
if (position.getY() < playerBall->getCenterOfMassPosition().getY() + cameraDistance/2)
position.setY(playerBall->getCenterOfMassPosition().getY() + cameraDistance/2);
btVector3 dir = cameraBody->getCenterOfMassPosition() - position;
float str = 50 * dir.length() / cameraBody->getInvMass(); //getInvMass() returns the inverted mass
cameraBody->applyCentralForce(-dir*str); //scale the force by camera mass
/*if(dir.length() > -0.1f && dir.length() < 0.1f)
{
cameraBody->setLinearVelocity(btVector3(0,0,0));
world->stepSimulation(timeDiff);
return;
}*/
cameraBody->setLinearVelocity(btVector3(0,0,0));
cameraBody->applyCentralForce(-dir*str*10) ; //scale the force by camera mass
counter=0;
float speed = cameraBody->getLinearVelocity().length();
if(speed>20.0f)
{
printf("%f , %f \n", speed, position.length());
position = cameraBody->getLinearVelocity();
position.normalize();
cameraBody->setLinearVelocity(position*20);
@ -205,7 +214,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)));
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);
}
@ -220,6 +229,10 @@ void Physics::addTriangleMeshBody(Entity entity, std::string path, float mass, f
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)
throw std::invalid_argument( "Bodies out of Sync" );
@ -238,7 +251,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)));
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);
}
@ -252,6 +265,11 @@ void Physics::addButton(float width, float height, float length, Entity entity,
bodies.push_back(body);
if(!rotate)
{
body->setAngularFactor(btVector3(0,0,0));
}
if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" );
}
@ -267,11 +285,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)));
btVector3 inertia(0,0,0);
if(mass != 0.0)
if(mass != 0.0) //&& rotate lets certain objects get inertia (0,0,0) (not rotateable)
{
box->calculateLocalInertia((btScalar)mass,inertia);
}
btRigidBody::btRigidBodyConstructionInfo info(mass,motion,box,inertia);
btRigidBody* body = new btRigidBody(info);
@ -282,6 +301,11 @@ void Physics::addBox(float width, float height, float length, Entity entity, flo
bodies.push_back(body);
if(!rotate)
{
body->setAngularFactor(btVector3(0,0,0));
}
if(bodies.size() != indice)
throw std::invalid_argument( "Bodies out of Sync" );
}
@ -312,6 +336,11 @@ void Physics::addSphere(float rad, Entity entity, float mass, float dampningL, f
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);
if(bodies.size() != indice)
@ -326,7 +355,7 @@ void Physics::addCamera() //Camera Creator automatically called when player is c
btVector3 direction(1,1,1);
direction.normalize();
direction*=5; //create a offset of lenth 5 so we have a stable camera at the beginning
direction*=cameraDistance; //create a offset of length 5 so we have a stable camera at the beginning
btDefaultMotionState* motion = new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),playerBall->getCenterOfMassPosition()+direction));
btRigidBody::btRigidBodyConstructionInfo info(0.001,motion,sphere,inertia);
@ -335,6 +364,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
info.m_friction = 0;
info.m_restitution = 0;
world->addRigidBody(cameraBody,COL_OBJECTS, objectsPhysicsCollision);
cameraBody->setGravity(btVector3(0,0,0));
@ -377,15 +409,16 @@ glm::mat4 Physics::getRotation(int i)
}
//these are used to apply a force to the camera body according to the movement of the mouse
void Physics::updateCameraPos(glm::vec2 mouseMovement, float strength)
void Physics::updateCameraPos(glm::vec2 mouseMovement, float strength, float distance)
{
this->cameraDistance = distance;
//note: in mouseMovement x and y are flipped in contrast to bullet
btVector3 change = playerBall->getCenterOfMassPosition()-cameraBody->getCenterOfMassPosition();
change.setY(0);
change.normalize(); //normalize so that the distance between camera and body does not matter
change *= (mouseMovement.y); //we start with left/right movement because this needs to be calculated via a crossproduct, and the up down value would alter that
change = btCross(btVector3(0,1,0),change);
change.setY(mouseMovement.x/5); //scaleing because otherwise oup/down much stronger then left right
change.setY(mouseMovement.x); //scaleing because otherwise oup/down much stronger then left right
change *= strength / cameraBody->getInvMass();
cameraBody->applyCentralForce(change);
@ -444,6 +477,17 @@ void Physics::addStaticGroundPlane()
} //not needed anymoer, but still good for debugging
void Physics::forceMove(glm::vec3 newPosition, unsigned indice)//ugly, but needed for reset
{
bodies[indice]->setCenterOfMassTransform(btTransform(btQuaternion(0,0,0,1),btVector3(newPosition.x,newPosition.y,newPosition.z)));
}
void Physics::forceMoveCamera(glm::vec3 newPosition)
{
cameraBody->setCenterOfMassTransform(btTransform(btQuaternion(0,0,0,1),btVector3(newPosition.x,newPosition.y,newPosition.z)));
}
void Physics::kill() //delete dynamically allocated memory
{
if (world == NULL) {

View File

@ -54,7 +54,7 @@ class Physics {
glm::vec3 getPos(int i);
glm::mat4 getRotation(int i);
void addStaticGroundPlane();
void updateCameraPos(glm::vec2 mouseMovement, float strength);
void updateCameraPos(glm::vec2 mouseMovement, float strength, float distance);
glm::vec3 getCameraPosition();
void addRigidBodyFromFile(Entity entity, float mass, float dampningL, float dampningA, std::string modelLocation, unsigned indice);
void addTriangleMeshBody(Entity entity, std::string path, float mass, float dampningL, float dampningA, unsigned indice, float scaling,bool rotate);
@ -68,6 +68,8 @@ class Physics {
glm::vec3 getCameraToPlayer();
void kill();
void addButtonFrame(Entity entity);
void forceMove(glm::vec3 newPosition, unsigned indice);
void forceMoveCamera(glm::vec3 newPosition);
struct positionConstraint{btRigidBody* body; float strength; btVector3 position;};
@ -90,6 +92,7 @@ class Physics {
int terrainPhysicsCollision = 2;
int counter = 0;
std::string geometryPath;
float cameraDistance = 5; //distance of the camera to the player.
};
enum collisionTypes{

View File

@ -82,6 +82,7 @@ void Terrain::makeTriangleMesh(){
}
ab->setDataElements(numVertices, abData);
delete abData;
this->triangleMesh = std::make_shared<ACGL::OpenGL::VertexArrayObject>();
this->triangleMesh->bind();
this->triangleMesh->setMode(GL_TRIANGLE_STRIP);