Improve shadows
- Treat lights with radius of 1000 and higher as directional - Use orthographic projection for directional shadow lights
This commit is contained in:
parent
874a4006b6
commit
e3b5f3eba1
18 changed files with 239 additions and 140 deletions
|
@ -35,7 +35,7 @@ namespace game {
|
||||||
|
|
||||||
AnimatedCamera::AnimatedCamera(SceneGraph *sceneGraph, float aspect) : _sceneGraph(sceneGraph), _aspect(aspect) {
|
AnimatedCamera::AnimatedCamera(SceneGraph *sceneGraph, float aspect) : _sceneGraph(sceneGraph), _aspect(aspect) {
|
||||||
_sceneGraph = sceneGraph;
|
_sceneGraph = sceneGraph;
|
||||||
_sceneNode = make_shared<CameraSceneNode>(_sceneGraph, glm::mat4(1.0f), _zFar);
|
_sceneNode = make_shared<CameraSceneNode>(_sceneGraph, glm::mat4(1.0f), _aspect, _zNear, _zFar);
|
||||||
updateProjection();
|
updateProjection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace game {
|
||||||
|
|
||||||
DialogCamera::DialogCamera(SceneGraph *sceneGraph, const CameraStyle &style, float aspect, float zNear, float zFar) {
|
DialogCamera::DialogCamera(SceneGraph *sceneGraph, const CameraStyle &style, float aspect, float zNear, float zFar) {
|
||||||
glm::mat4 projection(glm::perspective(glm::radians(style.viewAngle), aspect, zNear, zFar));
|
glm::mat4 projection(glm::perspective(glm::radians(style.viewAngle), aspect, zNear, zFar));
|
||||||
_sceneNode = make_shared<CameraSceneNode>(sceneGraph, projection, zFar);
|
_sceneNode = make_shared<CameraSceneNode>(sceneGraph, projection, aspect, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogCamera::setSpeakerPosition(const glm::vec3 &position) {
|
void DialogCamera::setSpeakerPosition(const glm::vec3 &position) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ static constexpr float kMouseMultiplier = glm::pi<float>() / 4000.0f;
|
||||||
|
|
||||||
FirstPersonCamera::FirstPersonCamera(SceneGraph *sceneGraph, float aspect, float fovy, float zNear, float zFar) {
|
FirstPersonCamera::FirstPersonCamera(SceneGraph *sceneGraph, float aspect, float fovy, float zNear, float zFar) {
|
||||||
glm::mat4 projection(glm::perspective(fovy, aspect, zNear, zFar));
|
glm::mat4 projection(glm::perspective(fovy, aspect, zNear, zFar));
|
||||||
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, projection, zFar);
|
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, projection, aspect, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirstPersonCamera::handle(const SDL_Event &event) {
|
bool FirstPersonCamera::handle(const SDL_Event &event) {
|
||||||
|
|
|
@ -29,14 +29,15 @@ namespace reone {
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
|
static constexpr float kNearPlane = 0.1f;
|
||||||
static constexpr float kFarPlane = 10000.0f;
|
static constexpr float kFarPlane = 10000.0f;
|
||||||
|
|
||||||
StaticCamera::StaticCamera(SceneGraph *sceneGraph, float aspect) : _aspect(aspect) {
|
StaticCamera::StaticCamera(SceneGraph *sceneGraph, float aspect) : _aspect(aspect) {
|
||||||
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, glm::mat4(1.0f), kFarPlane);
|
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, glm::mat4(1.0f), aspect, kNearPlane, kFarPlane);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticCamera::setObject(const PlaceableCamera &object) {
|
void StaticCamera::setObject(const PlaceableCamera &object) {
|
||||||
glm::mat4 projection(glm::perspective(glm::radians(object.fieldOfView()), _aspect, 0.1f, kFarPlane));
|
glm::mat4 projection(glm::perspective(glm::radians(object.fieldOfView()), _aspect, kNearPlane, kFarPlane));
|
||||||
|
|
||||||
_sceneNode->setLocalTransform(object.transform());
|
_sceneNode->setLocalTransform(object.transform());
|
||||||
_sceneNode->setProjection(projection);
|
_sceneNode->setProjection(projection);
|
||||||
|
|
|
@ -36,7 +36,7 @@ static constexpr float kMouseRotationSpeed = 0.001f;
|
||||||
|
|
||||||
ThirdPersonCamera::ThirdPersonCamera(Game *game, SceneGraph *sceneGraph, float aspect, const CameraStyle &style, float zNear, float zFar) : _game(game) {
|
ThirdPersonCamera::ThirdPersonCamera(Game *game, SceneGraph *sceneGraph, float aspect, const CameraStyle &style, float zNear, float zFar) : _game(game) {
|
||||||
glm::mat4 projection(glm::perspective(glm::radians(style.viewAngle), aspect, zNear, zFar));
|
glm::mat4 projection(glm::perspective(glm::radians(style.viewAngle), aspect, zNear, zFar));
|
||||||
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, projection, zFar);
|
_sceneNode = make_unique<CameraSceneNode>(sceneGraph, projection, aspect, zNear, zFar);
|
||||||
_style = style;
|
_style = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ unique_ptr<SceneGraph> SceneBuilder::build() {
|
||||||
_modelScale + _modelOffset.y,
|
_modelScale + _modelOffset.y,
|
||||||
_zNear, _zFar));
|
_zNear, _zFar));
|
||||||
|
|
||||||
auto camera = make_shared<CameraSceneNode>(scene.get(), projection, _zFar);
|
auto camera = make_shared<CameraSceneNode>(scene.get(), projection, _aspect, _zNear, _zFar);
|
||||||
if (_cameraNodeName.empty()) {
|
if (_cameraNodeName.empty()) {
|
||||||
camera->setLocalTransform(_cameraTransform);
|
camera->setLocalTransform(_cameraTransform);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -106,7 +106,7 @@ struct Material {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shadows {
|
struct Shadows {
|
||||||
mat4 matrices[NUM_CUBE_FACES];
|
mat4 lightSpaceMatrices[NUM_CUBE_FACES];
|
||||||
vec4 lightPosition;
|
vec4 lightPosition;
|
||||||
bool lightPresent;
|
bool lightPresent;
|
||||||
float strength;
|
float strength;
|
||||||
|
@ -193,13 +193,15 @@ const float SELFILLUM_THRESHOLD = 0.85;
|
||||||
uniform sampler2D uDiffuse;
|
uniform sampler2D uDiffuse;
|
||||||
uniform sampler2D uLightmap;
|
uniform sampler2D uLightmap;
|
||||||
uniform sampler2D uBumpmap;
|
uniform sampler2D uBumpmap;
|
||||||
|
uniform sampler2D uShadowMap;
|
||||||
uniform samplerCube uEnvmap;
|
uniform samplerCube uEnvmap;
|
||||||
uniform samplerCube uShadowMap;
|
uniform samplerCube uCubeShadowMap;
|
||||||
|
|
||||||
in vec3 fragPosition;
|
in vec3 fragPosition;
|
||||||
in vec3 fragNormal;
|
in vec3 fragNormal;
|
||||||
in vec2 fragTexCoords;
|
in vec2 fragTexCoords;
|
||||||
in vec2 fragLightmapCoords;
|
in vec2 fragLightmapCoords;
|
||||||
|
in vec4 fragPosLightSpace;
|
||||||
in mat3 fragTanSpace;
|
in mat3 fragTanSpace;
|
||||||
|
|
||||||
layout(location = 0) out vec4 fragColor;
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
@ -263,30 +265,57 @@ vec3 getNormalFromBumpmap(vec2 uv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float getShadow() {
|
float getShadow() {
|
||||||
if (!uShadows.lightPresent) return 0.0;
|
|
||||||
|
|
||||||
vec3 fragToLight = fragPosition - uShadows.lightPosition.xyz;
|
|
||||||
float currentDepth = length(fragToLight);
|
|
||||||
|
|
||||||
float shadow = 0.0;
|
float shadow = 0.0;
|
||||||
float bias = 0.1;
|
|
||||||
float samples = 4.0;
|
|
||||||
float offset = 0.1;
|
|
||||||
|
|
||||||
for (float x = -offset; x < offset; x += offset / (samples * 0.5)) {
|
if (uShadows.lightPresent) {
|
||||||
for (float y = -offset; y < offset; y += offset / (samples * 0.5)) {
|
if (uShadows.lightPosition.w == 0.0) {
|
||||||
for (float z = -offset; z < offset; z += offset / (samples * 0.5)) {
|
// Directional light
|
||||||
float closestDepth = texture(uShadowMap, fragToLight + vec3(x, y, z)).r;
|
|
||||||
closestDepth *= SHADOW_FAR_PLANE;
|
|
||||||
|
|
||||||
if (currentDepth - bias > closestDepth) {
|
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||||
shadow += 1.0;
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
float closestDepth = texture(uShadowMap, projCoords.xy).r;
|
||||||
|
float currentDepth = projCoords.z;
|
||||||
|
|
||||||
|
vec2 texelSize = 1.0 / textureSize(uShadowMap, 0);
|
||||||
|
for (int x = -1; x <= 1; ++x) {
|
||||||
|
for (int y = -1; y <= 1; ++y) {
|
||||||
|
float pcfDepth = texture(uShadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
|
||||||
|
shadow += currentDepth > pcfDepth ? 1.0 : 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
shadow /= 9.0;
|
||||||
|
|
||||||
|
if (projCoords.z > 1.0) {
|
||||||
|
shadow = 0.0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Point light
|
||||||
|
|
||||||
|
vec3 fragToLight = fragPosition - uShadows.lightPosition.xyz;
|
||||||
|
float currentDepth = length(fragToLight);
|
||||||
|
|
||||||
|
float bias = 0.1;
|
||||||
|
float samples = 4.0;
|
||||||
|
float offset = 0.1;
|
||||||
|
|
||||||
|
for (float x = -offset; x < offset; x += offset / (samples * 0.5)) {
|
||||||
|
for (float y = -offset; y < offset; y += offset / (samples * 0.5)) {
|
||||||
|
for (float z = -offset; z < offset; z += offset / (samples * 0.5)) {
|
||||||
|
float closestDepth = texture(uCubeShadowMap, fragToLight + vec3(x, y, z)).r;
|
||||||
|
closestDepth *= SHADOW_FAR_PLANE;
|
||||||
|
|
||||||
|
if (currentDepth - bias > closestDepth) {
|
||||||
|
shadow += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shadow /= samples * samples * samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return uShadows.strength * shadow / (samples * samples * samples);
|
return uShadows.strength * shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getLightAttenuation(int light) {
|
float getLightAttenuation(int light) {
|
||||||
|
@ -451,6 +480,7 @@ out vec3 fragPosition;
|
||||||
out vec3 fragNormal;
|
out vec3 fragNormal;
|
||||||
out vec2 fragTexCoords;
|
out vec2 fragTexCoords;
|
||||||
out vec2 fragLightmapCoords;
|
out vec2 fragLightmapCoords;
|
||||||
|
out vec4 fragPosLightSpace;
|
||||||
out mat3 fragTanSpace;
|
out mat3 fragTanSpace;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -485,6 +515,13 @@ void main() {
|
||||||
fragTexCoords = aTexCoords;
|
fragTexCoords = aTexCoords;
|
||||||
fragLightmapCoords = aLightmapCoords;
|
fragLightmapCoords = aLightmapCoords;
|
||||||
|
|
||||||
|
// Compute light space fragment position for directional lights
|
||||||
|
if (uShadows.lightPresent && uShadows.lightPosition.w == 0.0) {
|
||||||
|
fragPosLightSpace = uShadows.lightSpaceMatrices[0] * vec4(fragPosition, 1.0);
|
||||||
|
} else {
|
||||||
|
fragPosLightSpace = vec4(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
|
if (isFeatureEnabled(FEATURE_BUMPMAPS)) {
|
||||||
vec3 T = normalize(vec3(uGeneral.model * vec4(aTangent, 0.0)));
|
vec3 T = normalize(vec3(uGeneral.model * vec4(aTangent, 0.0)));
|
||||||
vec3 B = normalize(vec3(uGeneral.model * vec4(aBitangent, 0.0)));
|
vec3 B = normalize(vec3(uGeneral.model * vec4(aBitangent, 0.0)));
|
||||||
|
@ -592,14 +629,23 @@ layout(triangle_strip, max_vertices=18) out;
|
||||||
out vec4 fragPosition;
|
out vec4 fragPosition;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
for (int face = 0; face < NUM_CUBE_FACES; ++face) {
|
if (uShadows.lightPosition.w == 0.0) {
|
||||||
gl_Layer = face;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
fragPosition = gl_in[i].gl_Position;
|
fragPosition = gl_in[i].gl_Position;
|
||||||
gl_Position = uShadows.matrices[face] * fragPosition;
|
gl_Position = uShadows.lightSpaceMatrices[0] * fragPosition;
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
}
|
}
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
|
} else {
|
||||||
|
for (int face = 0; face < NUM_CUBE_FACES; ++face) {
|
||||||
|
gl_Layer = face;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
fragPosition = gl_in[i].gl_Position;
|
||||||
|
gl_Position = uShadows.lightSpaceMatrices[face] * fragPosition;
|
||||||
|
EmitVertex();
|
||||||
|
}
|
||||||
|
EndPrimitive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)END";
|
)END";
|
||||||
|
@ -1243,6 +1289,7 @@ void Shaders::initTextureUniforms() {
|
||||||
setUniform("uPrefilterMap", TextureUnits::prefilterMap);
|
setUniform("uPrefilterMap", TextureUnits::prefilterMap);
|
||||||
setUniform("uBRDFLookup", TextureUnits::brdfLookup);
|
setUniform("uBRDFLookup", TextureUnits::brdfLookup);
|
||||||
setUniform("uShadowMap", TextureUnits::shadowMap);
|
setUniform("uShadowMap", TextureUnits::shadowMap);
|
||||||
|
setUniform("uCubeShadowMap", TextureUnits::cubeShadowMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shaders::~Shaders() {
|
Shaders::~Shaders() {
|
||||||
|
|
|
@ -103,8 +103,8 @@ struct ShaderMaterial {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderShadows {
|
struct ShaderShadows {
|
||||||
glm::mat4 matrices[kNumCubeFaces];
|
glm::mat4 lightSpaceMatrices[kNumCubeFaces];
|
||||||
glm::vec4 lightPosition { 0.0f };
|
glm::vec4 lightPosition { 0.0f }; /**< W = 0 if light is directional */
|
||||||
int lightPresent { false };
|
int lightPresent { false };
|
||||||
float strength { 1.0f };
|
float strength { 1.0f };
|
||||||
char padding[8];
|
char padding[8];
|
||||||
|
@ -136,7 +136,7 @@ struct CombinedUniforms {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ShaderLight {
|
struct ShaderLight {
|
||||||
glm::vec4 position { 0.0f };
|
glm::vec4 position { 0.0f }; /**< W = 0 if light is directional */
|
||||||
glm::vec4 color { 1.0f };
|
glm::vec4 color { 1.0f };
|
||||||
float multiplier { 1.0f };
|
float multiplier { 1.0f };
|
||||||
float radius { 1.0f };
|
float radius { 1.0f };
|
||||||
|
|
|
@ -88,6 +88,9 @@ void Textures::bindDefaults() {
|
||||||
_default->bind();
|
_default->bind();
|
||||||
|
|
||||||
setActiveTextureUnit(TextureUnits::shadowMap);
|
setActiveTextureUnit(TextureUnits::shadowMap);
|
||||||
|
_default->bind();
|
||||||
|
|
||||||
|
setActiveTextureUnit(TextureUnits::cubeShadowMap);
|
||||||
_defaultCubemap->bind();
|
_defaultCubemap->bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,11 +86,12 @@ struct TextureUnits {
|
||||||
static constexpr int lightmap { 1 };
|
static constexpr int lightmap { 1 };
|
||||||
static constexpr int envmap { 2 };
|
static constexpr int envmap { 2 };
|
||||||
static constexpr int bumpmap { 3 };
|
static constexpr int bumpmap { 3 };
|
||||||
static constexpr int bloom { 5 };
|
static constexpr int bloom { 4 };
|
||||||
static constexpr int irradianceMap { 6 };
|
static constexpr int irradianceMap { 5 };
|
||||||
static constexpr int prefilterMap { 7 };
|
static constexpr int prefilterMap { 6 };
|
||||||
static constexpr int brdfLookup { 8 };
|
static constexpr int brdfLookup { 7 };
|
||||||
static constexpr int shadowMap { 9 };
|
static constexpr int shadowMap { 8 };
|
||||||
|
static constexpr int cubeShadowMap { 9 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class IEventHandler {
|
class IEventHandler {
|
||||||
|
|
|
@ -25,9 +25,11 @@ namespace reone {
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
|
|
||||||
CameraSceneNode::CameraSceneNode(SceneGraph *sceneGraph, const glm::mat4 &projection, float farPlane) :
|
CameraSceneNode::CameraSceneNode(SceneGraph *sceneGraph, glm::mat4 projection, float aspect, float nearPlane, float farPlane) :
|
||||||
SceneNode(SceneNodeType::Camera, sceneGraph),
|
SceneNode(SceneNodeType::Camera, sceneGraph),
|
||||||
_projection(projection),
|
_projection(projection),
|
||||||
|
_aspect(aspect),
|
||||||
|
_nearPlane(nearPlane),
|
||||||
_farPlane(farPlane) {
|
_farPlane(farPlane) {
|
||||||
|
|
||||||
updateFrustum();
|
updateFrustum();
|
||||||
|
@ -46,22 +48,22 @@ void CameraSceneNode::updateView() {
|
||||||
void CameraSceneNode::updateFrustum() {
|
void CameraSceneNode::updateFrustum() {
|
||||||
glm::mat4 vp(_projection * _view);
|
glm::mat4 vp(_projection * _view);
|
||||||
for (int i = 3; i >= 0; --i) {
|
for (int i = 3; i >= 0; --i) {
|
||||||
_frustum[0][i] = vp[i][3] + vp[i][0];
|
_frustumPlanes[0][i] = vp[i][3] + vp[i][0];
|
||||||
_frustum[1][i] = vp[i][3] - vp[i][0];
|
_frustumPlanes[1][i] = vp[i][3] - vp[i][0];
|
||||||
_frustum[2][i] = vp[i][3] + vp[i][1];
|
_frustumPlanes[2][i] = vp[i][3] + vp[i][1];
|
||||||
_frustum[3][i] = vp[i][3] - vp[i][1];
|
_frustumPlanes[3][i] = vp[i][3] - vp[i][1];
|
||||||
_frustum[4][i] = vp[i][3] + vp[i][2];
|
_frustumPlanes[4][i] = vp[i][3] + vp[i][2];
|
||||||
_frustum[5][i] = vp[i][3] - vp[i][2];
|
_frustumPlanes[5][i] = vp[i][3] - vp[i][2];
|
||||||
}
|
}
|
||||||
for (int i = 0; i < kFrustumPlaneCount; ++i) {
|
for (int i = 0; i < kNumFrustumPlanes; ++i) {
|
||||||
_frustum[i] = glm::normalize(_frustum[i]);
|
_frustumPlanes[i] = glm::normalize(_frustumPlanes[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CameraSceneNode::isInFrustum(const glm::vec3 &point) const {
|
bool CameraSceneNode::isInFrustum(const glm::vec3 &point) const {
|
||||||
glm::vec4 point4(point, 1.0f);
|
glm::vec4 point4(point, 1.0f);
|
||||||
for (int i = 0; i < kFrustumPlaneCount; ++i) {
|
for (int i = 0; i < kNumFrustumPlanes; ++i) {
|
||||||
if (glm::dot(_frustum[i], point4) < 0.0f) return false;
|
if (glm::dot(_frustumPlanes[i], point4) < 0.0f) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -70,15 +72,15 @@ bool CameraSceneNode::isInFrustum(const AABB &aabb) const {
|
||||||
glm::vec3 center(aabb.center());
|
glm::vec3 center(aabb.center());
|
||||||
glm::vec3 halfSize(aabb.getSize() * 0.5f);
|
glm::vec3 halfSize(aabb.getSize() * 0.5f);
|
||||||
|
|
||||||
for (int i = 0; i < kFrustumPlaneCount; ++i) {
|
for (int i = 0; i < kNumFrustumPlanes; ++i) {
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x - halfSize.x, center.y - halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x - halfSize.x, center.y - halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x + halfSize.x, center.y - halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x + halfSize.x, center.y - halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x - halfSize.x, center.y + halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x - halfSize.x, center.y + halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x - halfSize.x, center.y - halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x - halfSize.x, center.y - halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x + halfSize.x, center.y + halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x + halfSize.x, center.y + halfSize.y, center.z - halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x + halfSize.x, center.y - halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x + halfSize.x, center.y - halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x - halfSize.x, center.y + halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x - halfSize.x, center.y + halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
if (glm::dot(_frustum[i], glm::vec4(center.x + halfSize.x, center.y + halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
if (glm::dot(_frustumPlanes[i], glm::vec4(center.x + halfSize.x, center.y + halfSize.y, center.z + halfSize.z, 1.0f)) >= 0.0f) continue;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -91,10 +93,6 @@ void CameraSceneNode::setProjection(const glm::mat4 &projection) {
|
||||||
updateFrustum();
|
updateFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CameraSceneNode::setFarPlane(float far) {
|
|
||||||
_farPlane = far;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace scene
|
} // namespace scene
|
||||||
|
|
||||||
} // namespace reone
|
} // namespace reone
|
||||||
|
|
|
@ -25,27 +25,30 @@ namespace reone {
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
|
|
||||||
const int kFrustumPlaneCount = 6;
|
const int kNumFrustumPlanes = 6;
|
||||||
|
|
||||||
class CameraSceneNode : public SceneNode {
|
class CameraSceneNode : public SceneNode {
|
||||||
public:
|
public:
|
||||||
CameraSceneNode(SceneGraph *sceneGraph, const glm::mat4 &projection, float farPlane);
|
CameraSceneNode(SceneGraph *sceneGraph, glm::mat4 projection, float aspect, float nearPlane, float farPlane);
|
||||||
|
|
||||||
bool isInFrustum(const glm::vec3 &point) const;
|
bool isInFrustum(const glm::vec3 &point) const;
|
||||||
bool isInFrustum(const render::AABB &aabb) const;
|
bool isInFrustum(const render::AABB &aabb) const;
|
||||||
|
|
||||||
const glm::mat4 &projection() const { return _projection; }
|
const glm::mat4 &projection() const { return _projection; }
|
||||||
const glm::mat4 &view() const { return _view; }
|
const glm::mat4 &view() const { return _view; }
|
||||||
|
float aspect() const { return _aspect; }
|
||||||
|
float nearPlane() const { return _nearPlane; }
|
||||||
float farPlane() const { return _farPlane; }
|
float farPlane() const { return _farPlane; }
|
||||||
|
|
||||||
void setProjection(const glm::mat4 &projection);
|
void setProjection(const glm::mat4 &projection);
|
||||||
void setFarPlane(float far);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
glm::mat4 _projection { 1.0f };
|
glm::mat4 _projection { 1.0f };
|
||||||
glm::mat4 _view { 1.0f };
|
glm::mat4 _view { 1.0f };
|
||||||
glm::vec4 _frustum[kFrustumPlaneCount];
|
glm::vec4 _frustumPlanes[kNumFrustumPlanes];
|
||||||
float _farPlane { 1.0f };
|
float _aspect { 1.0f };
|
||||||
|
float _nearPlane { 0.0f };
|
||||||
|
float _farPlane { 0.0f };
|
||||||
|
|
||||||
void updateAbsoluteTransform() override;
|
void updateAbsoluteTransform() override;
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
#include "../scenegraph.h"
|
#include "../scenegraph.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace reone {
|
namespace reone {
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
|
@ -30,26 +28,6 @@ LightSceneNode::LightSceneNode(int priority, SceneGraph *sceneGraph) :
|
||||||
_priority(priority) {
|
_priority(priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightSceneNode::setColor(glm::vec3 color) {
|
|
||||||
_color = move(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightSceneNode::setMultiplier(float multiplier) {
|
|
||||||
_multiplier = multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightSceneNode::setRadius(float radius) {
|
|
||||||
_radius = radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightSceneNode::setShadow(bool shadow) {
|
|
||||||
_shadow = shadow;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LightSceneNode::setAmbientOnly(bool ambientOnly) {
|
|
||||||
_ambientOnly = ambientOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace scene
|
} // namespace scene
|
||||||
|
|
||||||
} // namespace reone
|
} // namespace reone
|
||||||
|
|
|
@ -31,17 +31,19 @@ public:
|
||||||
|
|
||||||
bool isShadow() const { return _shadow; }
|
bool isShadow() const { return _shadow; }
|
||||||
bool isAmbientOnly() const { return _ambientOnly; }
|
bool isAmbientOnly() const { return _ambientOnly; }
|
||||||
|
bool isDirectional() const { return _directional; }
|
||||||
|
|
||||||
const glm::vec3 &color() const { return _color; }
|
const glm::vec3 &color() const { return _color; }
|
||||||
int priority() const { return _priority; }
|
int priority() const { return _priority; }
|
||||||
float multiplier() const { return _multiplier; }
|
float multiplier() const { return _multiplier; }
|
||||||
float radius() const { return _radius; }
|
float radius() const { return _radius; }
|
||||||
|
|
||||||
void setColor(glm::vec3 color);
|
void setColor(glm::vec3 color) { _color = std::move(color); }
|
||||||
void setMultiplier(float multiplier);
|
void setMultiplier(float multiplier) { _multiplier = multiplier; }
|
||||||
void setRadius(float radius);
|
void setRadius(float radius) { _radius = radius; }
|
||||||
void setShadow(bool shadow);
|
void setShadow(bool shadow) { _shadow = shadow; }
|
||||||
void setAmbientOnly(bool ambientOnly);
|
void setAmbientOnly(bool ambientOnly) { _ambientOnly = ambientOnly; }
|
||||||
|
void setDirectional(bool directional) { _directional = directional; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _priority;
|
int _priority;
|
||||||
|
@ -51,6 +53,7 @@ private:
|
||||||
float _radius { 1.0f };
|
float _radius { 1.0f };
|
||||||
bool _shadow { false };
|
bool _shadow { false };
|
||||||
bool _ambientOnly { false };
|
bool _ambientOnly { false };
|
||||||
|
bool _directional { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scene
|
} // namespace scene
|
||||||
|
|
|
@ -288,8 +288,11 @@ void ModelNodeSceneNode::drawSingle(bool shadowPass) {
|
||||||
uniforms.lighting->lightCount = static_cast<int>(lights.size());
|
uniforms.lighting->lightCount = static_cast<int>(lights.size());
|
||||||
|
|
||||||
for (int i = 0; i < uniforms.lighting->lightCount; ++i) {
|
for (int i = 0; i < uniforms.lighting->lightCount; ++i) {
|
||||||
|
glm::vec4 position(lights[i]->absoluteTransform()[3]);
|
||||||
|
position.w = lights[i]->isDirectional() ? 0.0f : 1.0f;
|
||||||
|
|
||||||
ShaderLight &shaderLight = uniforms.lighting->lights[i];
|
ShaderLight &shaderLight = uniforms.lighting->lights[i];
|
||||||
shaderLight.position = lights[i]->absoluteTransform()[3];
|
shaderLight.position = move(position);
|
||||||
shaderLight.color = glm::vec4(lights[i]->color(), 1.0f);
|
shaderLight.color = glm::vec4(lights[i]->color(), 1.0f);
|
||||||
shaderLight.multiplier = lights[i]->multiplier();
|
shaderLight.multiplier = lights[i]->multiplier();
|
||||||
shaderLight.radius = lights[i]->radius();
|
shaderLight.radius = lights[i]->radius();
|
||||||
|
|
|
@ -43,6 +43,8 @@ namespace reone {
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
|
|
||||||
|
const float kMinDirectionalLightRadius = 1000.0f;
|
||||||
|
|
||||||
static bool g_debugAABB = false;
|
static bool g_debugAABB = false;
|
||||||
|
|
||||||
ModelSceneNode::ModelSceneNode(ModelUsage usage, const shared_ptr<Model> &model, SceneGraph *sceneGraph, set<string> ignoreNodes) :
|
ModelSceneNode::ModelSceneNode(ModelUsage usage, const shared_ptr<Model> &model, SceneGraph *sceneGraph, set<string> ignoreNodes) :
|
||||||
|
@ -113,12 +115,17 @@ void ModelSceneNode::initModelNodes() {
|
||||||
|
|
||||||
shared_ptr<ModelNode::Light> light(child->light());
|
shared_ptr<ModelNode::Light> light(child->light());
|
||||||
if (light) {
|
if (light) {
|
||||||
|
// Light is considered directional if its radius exceeds a certain threshold
|
||||||
|
float radius = child->lightRadii().getByKeyframeOrElse(0, 1.0f);
|
||||||
|
bool directional = radius >= kMinDirectionalLightRadius;
|
||||||
|
|
||||||
auto lightNode = make_shared<LightSceneNode>(light->priority, _sceneGraph);
|
auto lightNode = make_shared<LightSceneNode>(light->priority, _sceneGraph);
|
||||||
lightNode->setColor(child->lightColors().getByKeyframeOrElse(0, glm::vec3(1.0f)));
|
lightNode->setColor(child->lightColors().getByKeyframeOrElse(0, glm::vec3(1.0f)));
|
||||||
lightNode->setMultiplier(child->lightMultipliers().getByKeyframeOrElse(0, 1.0f));
|
lightNode->setMultiplier(child->lightMultipliers().getByKeyframeOrElse(0, 1.0f));
|
||||||
lightNode->setRadius(child->lightRadii().getByKeyframeOrElse(0, 1.0f));
|
lightNode->setRadius(radius);
|
||||||
lightNode->setShadow(light->shadow);
|
lightNode->setShadow(light->shadow);
|
||||||
lightNode->setAmbientOnly(light->ambientOnly);
|
lightNode->setAmbientOnly(light->ambientOnly);
|
||||||
|
lightNode->setDirectional(directional);
|
||||||
childNode->addChild(lightNode);
|
childNode->addChild(lightNode);
|
||||||
_lightNodeByNumber.insert(make_pair(modelNode->nodeNumber(), lightNode.get()));
|
_lightNodeByNumber.insert(make_pair(modelNode->nodeNumber(), lightNode.get()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,13 +43,19 @@ namespace reone {
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
|
|
||||||
static constexpr float kShadowFarPlane = 10000.0f;
|
const float kShadowNearPlane = 0.0f;
|
||||||
|
const float kShadowFarPlane = 10000.0f;
|
||||||
|
const float kOrthographicScale = 10.0f;
|
||||||
|
|
||||||
static bool g_wireframesEnabled = false;
|
static bool g_wireframesEnabled = false;
|
||||||
static bool g_debugCubeMap = false;
|
static bool g_debugCubeMap = false;
|
||||||
|
|
||||||
WorldRenderPipeline::WorldRenderPipeline(SceneGraph *scene, const GraphicsOptions &opts) :
|
WorldRenderPipeline::WorldRenderPipeline(SceneGraph *scene, const GraphicsOptions &opts) :
|
||||||
_scene(scene), _opts(opts) {
|
_scene(scene), _opts(opts) {
|
||||||
|
|
||||||
|
for (int i = 0; i < kNumCubeFaces; ++i) {
|
||||||
|
_lightSpaceMatrices[i] = glm::mat4(1.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderPipeline::init() {
|
void WorldRenderPipeline::init() {
|
||||||
|
@ -113,19 +119,21 @@ void WorldRenderPipeline::init() {
|
||||||
|
|
||||||
// Shadows framebuffer
|
// Shadows framebuffer
|
||||||
|
|
||||||
_shadowsDepth = make_unique<Texture>("shadows_depth", getTextureProperties(TextureUsage::CubeMapDepthBuffer));
|
_shadowsDepth = make_unique<Texture>("shadows_depth", getTextureProperties(TextureUsage::DepthBuffer));
|
||||||
_shadowsDepth->init();
|
_shadowsDepth->init();
|
||||||
_shadowsDepth->bind();
|
_shadowsDepth->bind();
|
||||||
_shadowsDepth->clearPixels(1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution, PixelFormat::Depth);
|
_shadowsDepth->clearPixels(1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution, PixelFormat::Depth);
|
||||||
|
|
||||||
|
_cubeShadowsDepth = make_unique<Texture>("cubeshadows_depth", getTextureProperties(TextureUsage::CubeMapDepthBuffer));
|
||||||
|
_cubeShadowsDepth->init();
|
||||||
|
_cubeShadowsDepth->bind();
|
||||||
|
_cubeShadowsDepth->clearPixels(1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution, PixelFormat::Depth);
|
||||||
|
|
||||||
_shadows.init();
|
_shadows.init();
|
||||||
_shadows.bind();
|
|
||||||
_shadows.attachDepth(*_shadowsDepth);
|
|
||||||
_shadows.checkCompleteness();
|
|
||||||
_shadows.unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderPipeline::render() {
|
void WorldRenderPipeline::render() {
|
||||||
|
computeLightSpaceMatrices();
|
||||||
drawShadows();
|
drawShadows();
|
||||||
drawGeometry();
|
drawGeometry();
|
||||||
applyHorizontalBlur();
|
applyHorizontalBlur();
|
||||||
|
@ -133,39 +141,8 @@ void WorldRenderPipeline::render() {
|
||||||
drawResult();
|
drawResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderPipeline::drawShadows() {
|
static glm::mat4 getPointLightView(const glm::vec3 &lightPos, CubeMapFace face) {
|
||||||
if (_opts.shadowResolution < 1) return;
|
switch (face) {
|
||||||
|
|
||||||
const LightSceneNode *shadowLight = _scene->shadowLight();
|
|
||||||
if (!shadowLight) return;
|
|
||||||
|
|
||||||
withViewport(glm::ivec4(0, 0, 1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution), [&]() {
|
|
||||||
_shadows.bind();
|
|
||||||
|
|
||||||
glDrawBuffer(GL_NONE);
|
|
||||||
glReadBuffer(GL_NONE);
|
|
||||||
|
|
||||||
glm::mat4 projection(glm::perspective(glm::radians(90.0f), 1.0f, 1.0f, kShadowFarPlane));
|
|
||||||
glm::vec3 lightPosition(shadowLight->absoluteTransform()[3]);
|
|
||||||
|
|
||||||
ShaderUniforms uniforms(Shaders::instance().defaultUniforms());
|
|
||||||
uniforms.combined.featureMask |= UniformFeatureFlags::shadows;
|
|
||||||
uniforms.combined.shadows.lightPosition = glm::vec4(lightPosition, 1.0f);
|
|
||||||
|
|
||||||
for (int i = 0; i < kNumCubeFaces; ++i) {
|
|
||||||
auto side = static_cast<CubeMapFace>(i);
|
|
||||||
uniforms.combined.shadows.matrices[i] = projection * getShadowView(lightPosition, side);
|
|
||||||
}
|
|
||||||
|
|
||||||
_scene->setUniformsPrototype(move(uniforms));
|
|
||||||
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
|
||||||
withDepthTest([this]() { _scene->draw(true); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 WorldRenderPipeline::getShadowView(const glm::vec3 &lightPos, CubeMapFace side) const {
|
|
||||||
switch (side) {
|
|
||||||
case CubeMapFace::PositiveX:
|
case CubeMapFace::PositiveX:
|
||||||
return glm::lookAt(lightPos, lightPos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0));
|
return glm::lookAt(lightPos, lightPos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0));
|
||||||
case CubeMapFace::NegativeX:
|
case CubeMapFace::NegativeX:
|
||||||
|
@ -183,6 +160,65 @@ glm::mat4 WorldRenderPipeline::getShadowView(const glm::vec3 &lightPos, CubeMapF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldRenderPipeline::computeLightSpaceMatrices() {
|
||||||
|
static glm::vec3 up(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
const LightSceneNode *shadowLight = _scene->shadowLight();
|
||||||
|
if (!shadowLight) return;
|
||||||
|
|
||||||
|
shared_ptr<CameraSceneNode> camera(_scene->activeCamera());
|
||||||
|
if (!camera) return;
|
||||||
|
|
||||||
|
glm::vec3 lightPosition(shadowLight->absoluteTransform()[3]);
|
||||||
|
glm::vec3 cameraPosition(camera->absoluteTransform()[3]);
|
||||||
|
|
||||||
|
if (shadowLight->isDirectional()) {
|
||||||
|
glm::mat4 projection(glm::ortho(-kOrthographicScale, kOrthographicScale, -kOrthographicScale, kOrthographicScale, kShadowNearPlane, kShadowFarPlane));
|
||||||
|
glm::mat4 lightView(glm::lookAt(lightPosition, cameraPosition, up));
|
||||||
|
_lightSpaceMatrices[0] = projection * lightView;
|
||||||
|
} else {
|
||||||
|
glm::mat4 projection(glm::perspective(glm::radians(90.0f), 1.0f, kShadowNearPlane, kShadowFarPlane));
|
||||||
|
for (int i = 0; i < kNumCubeFaces; ++i) {
|
||||||
|
glm::mat4 lightView(getPointLightView(lightPosition, static_cast<CubeMapFace>(i)));
|
||||||
|
_lightSpaceMatrices[i] = projection * lightView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldRenderPipeline::drawShadows() {
|
||||||
|
if (_opts.shadowResolution < 1) return;
|
||||||
|
|
||||||
|
const LightSceneNode *shadowLight = _scene->shadowLight();
|
||||||
|
if (!shadowLight) return;
|
||||||
|
|
||||||
|
withViewport(glm::ivec4(0, 0, 1024 * _opts.shadowResolution, 1024 * _opts.shadowResolution), [&]() {
|
||||||
|
_shadows.bind();
|
||||||
|
if (shadowLight->isDirectional()) {
|
||||||
|
_shadows.attachDepth(*_shadowsDepth);
|
||||||
|
} else {
|
||||||
|
_shadows.attachDepth(*_cubeShadowsDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawBuffer(GL_NONE);
|
||||||
|
glReadBuffer(GL_NONE);
|
||||||
|
|
||||||
|
glm::vec4 lightPosition(
|
||||||
|
glm::vec3(shadowLight->absoluteTransform()[3]),
|
||||||
|
shadowLight->isDirectional() ? 0.0f : 1.0f);
|
||||||
|
|
||||||
|
ShaderUniforms uniforms(Shaders::instance().defaultUniforms());
|
||||||
|
uniforms.combined.featureMask |= UniformFeatureFlags::shadows;
|
||||||
|
uniforms.combined.shadows.lightPosition = move(lightPosition);
|
||||||
|
for (int i = 0; i < kNumCubeFaces; ++i) {
|
||||||
|
uniforms.combined.shadows.lightSpaceMatrices[i] = _lightSpaceMatrices[i];
|
||||||
|
}
|
||||||
|
_scene->setUniformsPrototype(move(uniforms));
|
||||||
|
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
withDepthTest([this]() { _scene->draw(true); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void WorldRenderPipeline::drawGeometry() {
|
void WorldRenderPipeline::drawGeometry() {
|
||||||
_geometry.bind();
|
_geometry.bind();
|
||||||
|
|
||||||
|
@ -196,13 +232,30 @@ void WorldRenderPipeline::drawGeometry() {
|
||||||
uniforms.combined.general.view = _scene->activeCamera()->view();
|
uniforms.combined.general.view = _scene->activeCamera()->view();
|
||||||
uniforms.combined.general.cameraPosition = _scene->activeCamera()->absoluteTransform()[3];
|
uniforms.combined.general.cameraPosition = _scene->activeCamera()->absoluteTransform()[3];
|
||||||
uniforms.combined.shadows.lightPresent = static_cast<bool>(shadowLight);
|
uniforms.combined.shadows.lightPresent = static_cast<bool>(shadowLight);
|
||||||
uniforms.combined.shadows.lightPosition = shadowLight ? shadowLight->absoluteTransform()[3] : glm::vec4(0.0f);
|
|
||||||
uniforms.combined.shadows.strength = _scene->shadowStrength();
|
if (shadowLight) {
|
||||||
|
glm::vec4 lightPosition(
|
||||||
|
glm::vec3(shadowLight->absoluteTransform()[3]),
|
||||||
|
shadowLight->isDirectional() ? 0.0f : 1.0f);
|
||||||
|
|
||||||
|
uniforms.combined.shadows.lightPosition = move(lightPosition);
|
||||||
|
uniforms.combined.shadows.strength = _scene->shadowStrength();
|
||||||
|
|
||||||
|
for (int i = 0; i < kNumCubeFaces; ++i) {
|
||||||
|
uniforms.combined.shadows.lightSpaceMatrices[i] = _lightSpaceMatrices[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_scene->setUniformsPrototype(move(uniforms));
|
_scene->setUniformsPrototype(move(uniforms));
|
||||||
|
|
||||||
if (shadowLight) {
|
if (shadowLight) {
|
||||||
setActiveTextureUnit(TextureUnits::shadowMap);
|
if (shadowLight->isDirectional()) {
|
||||||
_shadowsDepth->bind();
|
setActiveTextureUnit(TextureUnits::shadowMap);
|
||||||
|
_shadowsDepth->bind();
|
||||||
|
} else {
|
||||||
|
setActiveTextureUnit(TextureUnits::cubeShadowMap);
|
||||||
|
_cubeShadowsDepth->bind();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
#include "../../render/renderbuffer.h"
|
#include "../../render/renderbuffer.h"
|
||||||
#include "../../render/texture.h"
|
#include "../../render/texture.h"
|
||||||
#include "../../render/types.h"
|
#include "../../render/types.h"
|
||||||
#include "../../scene/scenegraph.h"
|
|
||||||
|
#include "../scenegraph.h"
|
||||||
|
|
||||||
namespace reone {
|
namespace reone {
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ public:
|
||||||
private:
|
private:
|
||||||
SceneGraph *_scene { nullptr };
|
SceneGraph *_scene { nullptr };
|
||||||
render::GraphicsOptions _opts;
|
render::GraphicsOptions _opts;
|
||||||
|
glm::mat4 _lightSpaceMatrices[render::kNumCubeFaces];
|
||||||
|
|
||||||
// Framebuffers
|
// Framebuffers
|
||||||
|
|
||||||
|
@ -59,16 +61,16 @@ private:
|
||||||
std::unique_ptr<render::Texture> _verticalBlurColor;
|
std::unique_ptr<render::Texture> _verticalBlurColor;
|
||||||
std::unique_ptr<render::Texture> _horizontalBlurColor;
|
std::unique_ptr<render::Texture> _horizontalBlurColor;
|
||||||
std::unique_ptr<render::Texture> _shadowsDepth;
|
std::unique_ptr<render::Texture> _shadowsDepth;
|
||||||
|
std::unique_ptr<render::Texture> _cubeShadowsDepth;
|
||||||
|
|
||||||
// END Framebuffers targets
|
// END Framebuffers targets
|
||||||
|
|
||||||
|
void computeLightSpaceMatrices();
|
||||||
void drawShadows();
|
void drawShadows();
|
||||||
void drawGeometry();
|
void drawGeometry();
|
||||||
void applyHorizontalBlur();
|
void applyHorizontalBlur();
|
||||||
void applyVerticalBlur();
|
void applyVerticalBlur();
|
||||||
void drawResult();
|
void drawResult();
|
||||||
|
|
||||||
glm::mat4 getShadowView(const glm::vec3 &lightPos, render::CubeMapFace side) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace scene
|
} // namespace scene
|
||||||
|
|
Loading…
Reference in a new issue