Add LightStage for rendering lights

This commit is contained in:
Zach Pomerantz 2016-01-14 12:25:34 -08:00
parent 82f7ea515d
commit 0776ae7e72
5 changed files with 150 additions and 25 deletions

View file

@ -162,6 +162,7 @@ private:
// Used to project points
glm::mat4 _ourModelViewProjectionMatrix;
};
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
#endif // hifi_ViewFrustum_h

View file

@ -69,6 +69,8 @@ void DeferredLightingEffect::init() {
_allocatedLights.push_back(std::make_shared<model::Light>());
model::LightPointer lp = _allocatedLights[0];
// Add the global light to the light stage (for later shadow rendering)
_lightStage.addLight(lp);
lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f));
lp->setColor(glm::vec3(1.0f));
@ -541,10 +543,6 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl
light->setAmbientIntensity(ambientIntensity);
}
model::LightPointer DeferredLightingEffect::getGlobalLight() {
return _allocatedLights[_globalLights.front()];
}
void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
_skybox = skybox;
}

View file

@ -21,6 +21,8 @@
#include "model/Stage.h"
#include "model/Geometry.h"
#include "LightStage.h"
class RenderArgs;
struct LightLocations;
using LightLocationsPtr = std::shared_ptr<LightLocations>;
@ -50,9 +52,11 @@ public:
void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; }
void setGlobalSkybox(const model::SkyboxPointer& skybox);
model::LightPointer getGlobalLight();
const LightStage& getLightStage() { return _lightStage; }
private:
LightStage _lightStage;
DeferredLightingEffect() = default;
model::MeshPointer _spotLightMesh;
@ -72,26 +76,7 @@ private:
gpu::PipelinePointer _spotLight;
LightLocationsPtr _spotLightLocations;
class PointLight {
public:
glm::vec4 position;
float radius;
glm::vec4 ambient;
glm::vec4 diffuse;
glm::vec4 specular;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
};
class SpotLight : public PointLight {
public:
glm::vec3 direction;
float exponent;
float cutoff;
};
typedef std::vector< model::LightPointer > Lights;
using Lights = std::vector<model::LightPointer>;
Lights _allocatedLights;
std::vector<int> _globalLights;

View file

@ -0,0 +1,79 @@
//
// LightStage.cpp
// render-utils/src
//
// Created by Zach Pomerantz on 1/14/2015.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "ViewFrustum.h"
#include "LightStage.h"
LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared<ViewFrustum>() } {
framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE));
map = framebuffer->getDepthStencilBuffer();
}
void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront) {
// Orient the keylight frustum
const auto& direction = glm::normalize(_light->getDirection());
glm::quat orientation;
if (direction == IDENTITY_UP) {
orientation = glm::quat(glm::mat3(IDENTITY_UP, -IDENTITY_FRONT, IDENTITY_RIGHT));
} else {
auto side = glm::normalize(glm::cross(direction, IDENTITY_UP));
auto up = glm::normalize(glm::cross(side, direction));
auto orientation = glm::quat(glm::mat3(direction, up, side));
}
_frustum->setOrientation(orientation);
// Position the keylight frustum
_frustum->setPosition(viewFrustum->getPosition() - 21.0f * direction);
_view = _frustum->getView();
const Transform viewInverse{ _view.getInverseMatrix() };
viewFrustum->calculate();
//const auto nearCorners = viewFrustum->getCorners(0);
const auto nearClip = viewFrustum->getNearClip();
const auto nearCorners = viewFrustum->getCorners(nearClip - 1);
const auto farCorners = viewFrustum->getCorners(nearClip + 20);
vec3 min{ viewInverse.transform(nearCorners.bottomLeft) };
vec3 max{ min };
// Expand keylight frustum to fit view frustum
auto fitFrustum = [&min, &max, &viewInverse](const vec3& viewCorner) {
const auto corner = viewInverse.transform(viewCorner);
min.x = glm::min(min.x, corner.x);
min.y = glm::min(min.y, corner.y);
min.z = glm::min(min.z, corner.z);
max.x = glm::max(max.x, corner.x);
max.y = glm::max(max.y, corner.y);
max.z = glm::max(max.z, corner.z);
};
fitFrustum(nearCorners.bottomLeft);
fitFrustum(nearCorners.bottomRight);
fitFrustum(nearCorners.topLeft);
fitFrustum(nearCorners.topRight);
fitFrustum(farCorners.bottomLeft);
fitFrustum(farCorners.bottomRight);
fitFrustum(farCorners.topLeft);
fitFrustum(farCorners.topRight);
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, -max.z, -min.z);
_frustum->setProjection(ortho);
_projection = ortho;
}
const LightStage::LightPointer& LightStage::addLight(model::LightPointer light) {
Shadow stageShadow{light};
LightPointer stageLight = std::make_shared<Light>(std::move(stageShadow));
lights.push_back(stageLight);
return stageLight;
}

View file

@ -0,0 +1,62 @@
//
// LightStage.h
// render-utils/src
//
// Created by Zach Pomerantz on 1/14/2015.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_render_utils_LightStage_h
#define hifi_render_utils_LightStage_h
#include "gpu/Framebuffer.h"
#include "model/Light.h"
class ViewFrustum;
// Light stage to set up light-related rendering tasks
class LightStage {
public:
class Shadow {
public:
const int MAP_SIZE = 2048;
Shadow(model::LightPointer light);
void setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront);
const std::shared_ptr<ViewFrustum> getFrustum() const { return _frustum; }
const glm::mat4& getProjection() const { return _projection; }
const Transform& getView() const { return _view; }
gpu::FramebufferPointer framebuffer;
gpu::TexturePointer map;
protected:
model::LightPointer _light;
std::shared_ptr<ViewFrustum> _frustum;
glm::mat4 _projection;
Transform _view;
};
using ShadowPointer = std::shared_ptr<Shadow>;
class Light {
public:
Light(Shadow&& shadow) : shadow{ shadow } {}
model::LightPointer light;
Shadow shadow;
};
using LightPointer = std::shared_ptr<Light>;
using Lights = std::vector<LightPointer>;
const LightPointer& addLight(model::LightPointer light);
// TODO: removeLight
Lights lights;
};
#endif