Implemented basic shadows for sun light. Also fixed bug with far plane always staying the same.

This commit is contained in:
Faerbit 2014-12-04 01:13:59 +01:00
parent fca69b547b
commit 27c2248117
13 changed files with 214 additions and 106 deletions

10
Shader/depth.fsh Normal file
View File

@ -0,0 +1,10 @@
#version 150
out vec4 fragmentDepth;
void main() {
fragmentDepth.r = gl_FragCoord.z;
fragmentDepth.g = gl_FragCoord.z;
fragmentDepth.b = gl_FragCoord.z;
fragmentDepth.a = 1.0;
}

12
Shader/depth.vsh Normal file
View File

@ -0,0 +1,12 @@
#version 150
in vec3 aPosition;
in vec3 aNormal;
in vec3 aTexcoord;
uniform mat4 viewProjectionMatrix;
uniform mat4 modelMatrix;
void main() {
gl_Position = viewProjectionMatrix * modelMatrix * vec4(aPosition, 1.0);
}

View File

@ -3,10 +3,12 @@
in vec3 vNormal;
in vec2 vTexCoord;
in vec4 fragPosition;
in vec4 shadowCoord;
out vec4 oColor;
uniform sampler2D uTexture;
uniform sampler2D shadowMap;
uniform vec3 ambientColor;
uniform float ambientFactor;
uniform float diffuseFactor;
@ -30,6 +32,8 @@ void main()
vec3 diffuseColor = vec3(0.0, 0.0, 0.0);
vec3 specularColor = vec3(0.0, 0.0, 0.0);
// direction lighting
if(length(directionalLightVector)>0.0f) {
vec3 directionalVector = normalize(directionalLightVector);
diffuseColor += clamp(dot(normalize(vNormal), directionalVector)
@ -38,6 +42,8 @@ void main()
specularColor += clamp(pow((dot((cameraVector+directionalVector),normalize(vNormal))/(length(cameraVector+directionalVector)*length(normalize(vNormal)))),shininess), 0.0, 1.0)
*specularFactor*directionalIntensity*directionalColor;
}
// point lights
for(int i = 0; i<lightCount; i++) {
float distance = distance(lightSources[i], vec3(fragPosition));
// only take lights into account with meaningful contribution
@ -52,6 +58,20 @@ void main()
}
}
// shadows
float bias = 0.005;
float visibility = 1.0;
if (shadowCoord.x > 0.0 && shadowCoord.x < 1.0) {
if (shadowCoord.y > 0.0 && shadowCoord.y < 1.0) {
if (texture(shadowMap, shadowCoord.xy).z < shadowCoord.z-bias) {
visibility = 0.5;
}
}
}
specularColor *= visibility;
diffuseColor *= visibility;
vec3 finalColor = specularColor + diffuseColor + ambientColor;
float distanceCameraCenter = distance(cameraCenter, vec3(fragPosition));
float fogFactor = clamp((1.0 - (fogEnd-distanceCameraCenter)/30.0), 0.0, 1.0);

View File

@ -1,8 +1,8 @@
#version 150
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 lightingViewProjectionMatrix;
uniform mat4 shadowMVP;
in vec3 aPosition;
in vec3 aNormal;
@ -11,11 +11,13 @@ in vec2 aTexCoord;
out vec3 vNormal;
out vec2 vTexCoord;
out vec4 fragPosition;
out vec4 shadowCoord;
void main()
{
fragPosition = modelMatrix * vec4(aPosition, 1.0);
vNormal = inverse(transpose(mat3(modelMatrix))) * aNormal;
vTexCoord = aTexCoord;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(aPosition, 1.0);
shadowCoord = shadowMVP * modelMatrix * vec4(aPosition, 1.0);
gl_Position = lightingViewProjectionMatrix * modelMatrix * vec4(aPosition, 1.0);
}

View File

@ -11,7 +11,7 @@ void Application::init()
ignoredMouseUpdates = 0;
cameraLock = true;
// set Skybox size
level.setSkydomeSize((graphics.getFarPlane()/2.0f)-10.0f);
level.setSkydomeSize((graphics.getFarPlane())-31.0f);
// define where shaders and textures can be found:
ACGL::Base::Settings::the()->setResourcePath("../");

0
extern/acgl/include/ACGL/OpenGL/Objects/VertexArrayObject.hh vendored Executable file → Normal file
View File

View File

@ -5,6 +5,8 @@
#include <ACGL/OpenGL/Creator/ShaderProgramCreator.hh>
using namespace ACGL::OpenGL;
Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane) {
this->windowSize = windowSize;
this->nearPlane = nearPlane;
@ -16,17 +18,37 @@ Graphics::Graphics() {
void Graphics::init() {
// construct VAO to give shader correct Attribute locations
ACGL::OpenGL::SharedArrayBuffer ab = std::make_shared<ACGL::OpenGL::ArrayBuffer>();
SharedArrayBuffer ab = SharedArrayBuffer(new ArrayBuffer());
ab->defineAttribute("aPosition", GL_FLOAT, 3);
ab->defineAttribute("aTexCoord", GL_FLOAT, 2);
ab->defineAttribute("aNormal", GL_FLOAT, 3);
ACGL::OpenGL::SharedVertexArrayObject vao = std::make_shared<ACGL::OpenGL::VertexArrayObject>();
SharedVertexArrayObject vao = SharedVertexArrayObject(new VertexArrayObject());
vao->attachAllAttributes(ab);
// look up all shader files starting with 'phong' and build a ShaderProgram from it:
shader = ACGL::OpenGL::ShaderProgramCreator("phong").attributeLocations(
lightingShader = ShaderProgramCreator("phong").attributeLocations(
vao->getAttributeLocations()).create();
shader->use();
depthTexture_depth = SharedTexture2D( new Texture2D(windowSize, GL_DEPTH24_STENCIL8));
depthTexture_depth->setMinFilter(GL_NEAREST);
depthTexture_depth->setMagFilter(GL_NEAREST);
depthTexture_depth->setWrapS(GL_CLAMP_TO_EDGE);
depthTexture_depth->setWrapT(GL_CLAMP_TO_EDGE);
depthTexture_colour = SharedTexture2D( new Texture2D(windowSize));
depthTexture_colour->setMinFilter(GL_LINEAR);
depthTexture_colour->setMagFilter(GL_LINEAR);
depthTexture_colour->setWrapS(GL_CLAMP_TO_EDGE);
depthTexture_colour->setWrapT(GL_CLAMP_TO_EDGE);
framebuffer = SharedFrameBufferObject(new FrameBufferObject());
framebuffer->attachColorTexture("fragmentDepth", depthTexture_colour);
framebuffer->setDepthTexture(depthTexture_depth);
framebuffer->validate();
depthShader = ShaderProgramCreator("depth")
.attributeLocations(vao->getAttributeLocations())
.fragmentDataLocations(framebuffer->getAttachmentLocations())
.create();
}
GLFWwindow* Graphics::getWindow() {
@ -37,6 +59,121 @@ glm::uvec2 Graphics::getWindowSize() {
return windowSize;
}
void Graphics::render(Level* level)
{
// render depth texture for sun
framebuffer->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
depthShader->use();
glm::vec3 sunVector = (level->getCameraCenter()->getPosition() + level->getDirectionalLight()->getPosition());
glm::mat4 depthViewProjectionMatrix = glm::ortho<float>(-20, 20, -20, 20, -20, 40) *
glm::lookAt(sunVector, level->getCameraCenter()->getPosition(), glm::vec3(0,1,0));
depthShader->setUniform("viewProjectionMatrix", depthViewProjectionMatrix);
level->render(depthShader, false);
if (!framebuffer->isFrameBufferObjectComplete()) {
printf("Framebuffer incomplete, unknown error occured during shadow generation!\n");
}
// final render pass
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lightingShader->use();
//set view and projection matrix
glm::mat4 lightingViewProjectionMatrix = buildFrustum(75.0f, 0.1f, farPlane, (float)windowSize.x/(float)windowSize.y) * buildViewMatrix(level);
lightingShader->setUniform("lightingViewProjectionMatrix", lightingViewProjectionMatrix);
// 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
);
glm::mat4 depthBiasMVP = biasMatrix*depthViewProjectionMatrix;
lightingShader->setUniform("shadowMVP", depthBiasMVP);
lightingShader->setTexture("shadowMap", depthTexture_colour, 2);
//set lighting parameters
if (level->getLights().size() > 0) {
lightingShader->setUniform("lightCount", (int) level->getLights().size());
// TODO look into doing this less often
// Build light position array
glm::vec3 lightSources[level->getLights().size()];
for(unsigned int i = 0; i<level->getLights().size(); i++) {
lightSources[i] = level->getLights()[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()[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()[i].getIntensity();
}
glUniform1fv(lightingShader->getUniformLocation("lightIntensities"),
sizeof(lightIntensities), (GLfloat*) lightIntensities);
}
// set directional Light
if(level->getDirectionalLight()) {
lightingShader->setUniform("directionalLightVector",
level->getDirectionalLight()->getPosition());
lightingShader->setUniform("directionalColor",
level->getDirectionalLight()->getColour());
lightingShader->setUniform("directionalIntensity",
level->getDirectionalLight()->getIntensity());
}
// set fog Parameters
lightingShader->setUniform("fogEnd", (farPlane)-35.0f);
lightingShader->setUniform("fogColor", level->getFogColor());
lightingShader->setUniform("cameraCenter", level->getCameraCenter()->getPosition());
// set Material Parameters
lightingShader->setUniform("ambientColor", level->getAmbientLight());
lightingShader->setUniform("camera", level->getCameraPosition());
// render the level
level->render(lightingShader, true);
}
void Graphics::resize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
depthTexture_depth->resize(windowSize);
depthTexture_colour->resize(windowSize);
}
glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) {
float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0);
float top = _near * tan( phiHalfInRadians );
float bottom = -top;
float left = bottom * aspectRatio;
float right = -left;
return glm::frustum(left, right, bottom, top, _near, _far);
}
glm::mat4 Graphics::buildViewMatrix(Level* level) {
//construct lookAt (cameraPosition = cameraCenter + cameraVector
return glm::lookAt((level->getCameraCenter()->getPosition() + level->getCamera()->getVector()),
level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f));
}
float Graphics::getFarPlane() {
return farPlane;
}
void Graphics::setGLFWHintsForOpenGLVersion( unsigned int _version )
{
#ifdef __APPLE__
@ -90,87 +227,3 @@ bool Graphics::createWindow()
ACGL::init();
return true;
}
void Graphics::render(Level* level)
{
// clear the framebuffer:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set view and projection matrix
shader->setUniform("projectionMatrix", buildFrustum(75.0f, 0.1f, 100.0f, (float)windowSize.x/(float)windowSize.y) );
shader->setUniform("viewMatrix", buildViewMatrix(level));
//set lighting parameters
if (level->getLights().size() > 0) {
shader->setUniform("lightCount", (int) level->getLights().size());
// TODO look into doing this less often
// Build light position array
glm::vec3 lightSources[level->getLights().size()];
for(unsigned int i = 0; i<level->getLights().size(); i++) {
lightSources[i] = level->getLights()[i].getPosition();
}
glUniform3fv(shader->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()[i].getColour();
}
glUniform3fv(shader->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()[i].getIntensity();
}
glUniform1fv(shader->getUniformLocation("lightIntensities"),
sizeof(lightIntensities), (GLfloat*) lightIntensities);
}
// set directional Light
if(level->getDirectionalLight()) {
shader->setUniform("directionalLightVector",
level->getDirectionalLight()->getPosition());
shader->setUniform("directionalColor",
level->getDirectionalLight()->getColour());
shader->setUniform("directionalIntensity",
level->getDirectionalLight()->getIntensity());
}
// set fog Parameters
shader->setUniform("fogEnd", (farPlane/2.0f)-10.0f);
shader->setUniform("fogColor", level->getFogColor());
shader->setUniform("cameraCenter", level->getCameraCenter()->getPosition());
// set Material Parameters
shader->setUniform("ambientColor", level->getAmbientLight());
shader->setUniform("camera", level->getCameraPosition());
// render the level
level->render(shader);
}
void Graphics::setWindowSize(glm::uvec2 windowSize) {
this->windowSize = windowSize;
}
glm::mat4 Graphics::buildFrustum( float phiInDegree, float _near, float _far, float aspectRatio) {
float phiHalfInRadians = 0.5*phiInDegree * (M_PI/180.0);
float top = _near * tan( phiHalfInRadians );
float bottom = -top;
float left = bottom * aspectRatio;
float right = -left;
return glm::frustum(left, right, bottom, top, _near, _far);
}
glm::mat4 Graphics::buildViewMatrix(Level* level) {
//construct lookAt (cameraPosition = cameraCenter + cameraVector
return glm::lookAt((level->getCameraCenter()->getPosition() + level->getCamera()->getVector()),
level->getCameraCenter()->getPosition(), glm::vec3(0.0f, 1.0f, 0.0f));
}
float Graphics::getFarPlane() {
return farPlane;
}

View File

@ -4,6 +4,8 @@
#include <GLFW/glfw3.h>
#include <ACGL/Math/Math.hh>
#include <ACGL/OpenGL/Objects/FrameBufferObject.hh>
#include "level.hh"
class Graphics {
@ -18,15 +20,19 @@ class Graphics {
glm::uvec2 getWindowSize();
bool createWindow();
GLFWwindow* getWindow();
void setWindowSize(glm::uvec2 windowSize);
void resize(glm::uvec2 windowSize);
float getFarPlane();
ACGL::OpenGL::SharedFrameBufferObject framebuffer;
private:
void setGLFWHintsForOpenGLVersion( unsigned int _version );
glm::uvec2 windowSize;
float nearPlane;
float farPlane;
GLFWwindow* window;
ACGL::OpenGL::SharedShaderProgram shader;
ACGL::OpenGL::SharedShaderProgram lightingShader;
ACGL::OpenGL::SharedShaderProgram depthShader;
ACGL::OpenGL::SharedTexture2D depthTexture_depth;
ACGL::OpenGL::SharedTexture2D depthTexture_colour;
};
#endif

View File

@ -96,9 +96,12 @@ void Level::load() {
physics.addTerrain(terrain.getHeightmapWidth(), terrain.getHeightmapHeight(), terrain.getHeightmap());
}
void Level::render(ACGL::OpenGL::SharedShaderProgram shader) {
void Level::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass) {
for(unsigned int i = 0; i<objects.size(); i++) {
objects.at(i)->render(shader);
// do not project shadow of skydome
if(lightingPass || objects.at(i) != skydome) {
objects.at(i)->render(shader, lightingPass);
}
}
}

View File

@ -17,7 +17,7 @@ class Level {
~Level();
void load();
void update(float runTime, glm::vec2 mouseDelta,bool wPressed, bool aPressed,bool sPressed, bool dPressed);
void render(ACGL::OpenGL::SharedShaderProgram shader);
void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass);
glm::vec3 getAmbientLight();
Light* getDirectionalLight();
std::vector<Light> getLights();

View File

@ -3,10 +3,10 @@
#include <iomanip>
#include <sstream>
void resizeCallback(GLFWwindow* window, int newWidth, int newHeight)
static void resizeCallback(GLFWwindow* window, int newWidth, int newHeight)
{
// store the new window size and adjust the viewport:
app.getGraphics()->setWindowSize(glm::uvec2( newWidth, newHeight));
app.getGraphics()->resize(glm::uvec2( newWidth, newHeight));
glViewport( 0, 0, newWidth, newHeight);
}

View File

@ -12,13 +12,15 @@ Object::Object() {
Object::~Object() {
}
void Object::render(ACGL::OpenGL::SharedShaderProgram shader) {
void Object::render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass) {
if (lightingPass) {
// set lightning parameters for this object
shader->setUniform("ambientFactor", material.getAmbientFactor());
shader->setUniform("diffuseFactor", material.getDiffuseFactor());
shader->setUniform("specularFactor", material.getSpecularFactor());
shader->setUniform("shininess", material.getShininess());
shader->setTexture("uTexture", material.getReference(), 0);
shader->setUniform("ambientFactor", material.getAmbientFactor());
shader->setUniform("diffuseFactor", material.getDiffuseFactor());
shader->setUniform("specularFactor", material.getSpecularFactor());
shader->setUniform("shininess", material.getShininess());
shader->setTexture("uTexture", material.getReference(), 0);
}
// set model matrix
glm::mat4 modelMatrix = glm::translate(getPosition()) * getRotation() * glm::scale<float>(glm::vec3(model.getScale()));
shader->setUniform( "modelMatrix", modelMatrix);

View File

@ -15,7 +15,7 @@ class Object : public Entity {
glm::vec3 position, glm::vec3 rotation);
Object();
~Object();
void render(ACGL::OpenGL::SharedShaderProgram shader);
void render(ACGL::OpenGL::SharedShaderProgram shader, bool lightingPass);
private:
Model model;
Material material;