mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 16:41:02 +02:00
When rendering avatar shadows, check bounds against shadow frustum. Closes
This commit is contained in:
parent
20de297704
commit
210af25396
6 changed files with 96 additions and 20 deletions
|
@ -14,12 +14,12 @@
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Application.cpp" line="3580"/>
|
<location filename="src/Application.cpp" line="3591"/>
|
||||||
<source>Open Script</source>
|
<source>Open Script</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Application.cpp" line="3581"/>
|
<location filename="src/Application.cpp" line="3592"/>
|
||||||
<source>JavaScript Files (*.js)</source>
|
<source>JavaScript Files (*.js)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
|
@ -2138,6 +2138,7 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
|
||||||
viewFrustum.setOrientation(rotation);
|
viewFrustum.setOrientation(rotation);
|
||||||
|
|
||||||
// Also make sure it's got the correct lens details from the camera
|
// Also make sure it's got the correct lens details from the camera
|
||||||
|
viewFrustum.setOrthographic(false);
|
||||||
viewFrustum.setAspectRatio(aspectRatio);
|
viewFrustum.setAspectRatio(aspectRatio);
|
||||||
viewFrustum.setFieldOfView(fov); // degrees
|
viewFrustum.setFieldOfView(fov); // degrees
|
||||||
viewFrustum.setNearClip(nearClip);
|
viewFrustum.setNearClip(nearClip);
|
||||||
|
@ -2163,21 +2164,22 @@ void Application::updateShadowMap() {
|
||||||
glViewport(0, 0, fbo->width(), fbo->height());
|
glViewport(0, 0, fbo->width(), fbo->height());
|
||||||
|
|
||||||
glm::vec3 lightDirection = -getSunDirection();
|
glm::vec3 lightDirection = -getSunDirection();
|
||||||
glm::quat rotation = glm::inverse(rotationBetween(IDENTITY_FRONT, lightDirection));
|
glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection);
|
||||||
glm::vec3 translation = glm::vec3();
|
glm::quat inverseRotation = glm::inverse(rotation);
|
||||||
float nearScale = 0.0f;
|
float nearScale = 0.0f;
|
||||||
const float MAX_SHADOW_DISTANCE = 2.0f;
|
const float MAX_SHADOW_DISTANCE = 2.0f;
|
||||||
float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
|
float farScale = (MAX_SHADOW_DISTANCE - _viewFrustum.getNearClip()) /
|
||||||
|
(_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
|
||||||
loadViewFrustum(_myCamera, _viewFrustum);
|
loadViewFrustum(_myCamera, _viewFrustum);
|
||||||
glm::vec3 points[] = {
|
glm::vec3 points[] = {
|
||||||
rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale) + translation),
|
inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale)),
|
||||||
rotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) + translation) };
|
inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale)) };
|
||||||
glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||||
for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
|
for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
|
||||||
minima = glm::min(minima, points[i]);
|
minima = glm::min(minima, points[i]);
|
||||||
|
@ -2190,9 +2192,20 @@ void Application::updateShadowMap() {
|
||||||
|
|
||||||
// save the combined matrix for rendering
|
// save the combined matrix for rendering
|
||||||
_shadowMatrix = glm::transpose(glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *
|
_shadowMatrix = glm::transpose(glm::translate(glm::vec3(0.5f, 0.5f, 0.5f)) * glm::scale(glm::vec3(0.5f, 0.5f, 0.5f)) *
|
||||||
glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) *
|
glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z) * glm::mat4_cast(inverseRotation));
|
||||||
glm::mat4_cast(rotation) * glm::translate(translation));
|
|
||||||
|
|
||||||
|
// update the shadow view frustum
|
||||||
|
_shadowViewFrustum.setPosition(rotation * ((minima + maxima) * 0.5f));
|
||||||
|
_shadowViewFrustum.setOrientation(rotation);
|
||||||
|
_shadowViewFrustum.setOrthographic(true);
|
||||||
|
_shadowViewFrustum.setWidth(maxima.x - minima.x);
|
||||||
|
_shadowViewFrustum.setHeight(maxima.y - minima.y);
|
||||||
|
_shadowViewFrustum.setNearClip(minima.z);
|
||||||
|
_shadowViewFrustum.setFarClip(maxima.z);
|
||||||
|
_shadowViewFrustum.setEyeOffsetPosition(glm::vec3());
|
||||||
|
_shadowViewFrustum.setEyeOffsetOrientation(glm::quat());
|
||||||
|
_shadowViewFrustum.calculate();
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
@ -2206,9 +2219,7 @@ void Application::updateShadowMap() {
|
||||||
|
|
||||||
// store view matrix without translation, which we'll use for precision-sensitive objects
|
// store view matrix without translation, which we'll use for precision-sensitive objects
|
||||||
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix);
|
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix);
|
||||||
_viewMatrixTranslation = translation;
|
_viewMatrixTranslation = glm::vec3();
|
||||||
|
|
||||||
glTranslatef(translation.x, translation.y, translation.z);
|
|
||||||
|
|
||||||
_avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);
|
_avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE);
|
||||||
_particles.render();
|
_particles.render();
|
||||||
|
|
|
@ -155,6 +155,7 @@ public:
|
||||||
Audio* getAudio() { return &_audio; }
|
Audio* getAudio() { return &_audio; }
|
||||||
Camera* getCamera() { return &_myCamera; }
|
Camera* getCamera() { return &_myCamera; }
|
||||||
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
ViewFrustum* getViewFrustum() { return &_viewFrustum; }
|
||||||
|
ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; }
|
||||||
VoxelSystem* getVoxels() { return &_voxels; }
|
VoxelSystem* getVoxels() { return &_voxels; }
|
||||||
VoxelTree* getVoxelTree() { return _voxels.getTree(); }
|
VoxelTree* getVoxelTree() { return _voxels.getTree(); }
|
||||||
ParticleTreeRenderer* getParticles() { return &_particles; }
|
ParticleTreeRenderer* getParticles() { return &_particles; }
|
||||||
|
@ -385,6 +386,7 @@ private:
|
||||||
|
|
||||||
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
|
||||||
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels, particles)
|
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels, particles)
|
||||||
|
ViewFrustum _shadowViewFrustum;
|
||||||
quint64 _lastQueriedTime;
|
quint64 _lastQueriedTime;
|
||||||
|
|
||||||
Oscilloscope _audioScope;
|
Oscilloscope _audioScope;
|
||||||
|
|
|
@ -192,8 +192,9 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
||||||
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
// simple frustum check
|
// simple frustum check
|
||||||
float boundingRadius = getBillboardSize();
|
float boundingRadius = getBillboardSize();
|
||||||
if (Application::getInstance()->getViewFrustum()->sphereInFrustum(
|
ViewFrustum* frustum = (renderMode == Avatar::SHADOW_RENDER_MODE) ?
|
||||||
cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) {
|
Application::getInstance()->getShadowViewFrustum() : Application::getInstance()->getViewFrustum();
|
||||||
|
if (frustum->sphereInFrustum(_position, boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,9 @@ ViewFrustum::ViewFrustum() :
|
||||||
_direction(IDENTITY_FRONT),
|
_direction(IDENTITY_FRONT),
|
||||||
_up(IDENTITY_UP),
|
_up(IDENTITY_UP),
|
||||||
_right(IDENTITY_RIGHT),
|
_right(IDENTITY_RIGHT),
|
||||||
|
_orthographic(false),
|
||||||
|
_width(1.0f),
|
||||||
|
_height(1.0f),
|
||||||
_fieldOfView(0.0),
|
_fieldOfView(0.0),
|
||||||
_aspectRatio(1.0f),
|
_aspectRatio(1.0f),
|
||||||
_nearClip(0.1f),
|
_nearClip(0.1f),
|
||||||
|
@ -62,6 +65,11 @@ void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
||||||
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
|
// http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
|
||||||
//
|
//
|
||||||
void ViewFrustum::calculate() {
|
void ViewFrustum::calculate() {
|
||||||
|
if (_orthographic) {
|
||||||
|
calculateOrthographic();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// compute the off-axis frustum parameters as we would for glFrustum
|
// compute the off-axis frustum parameters as we would for glFrustum
|
||||||
float left, right, bottom, top, nearVal, farVal;
|
float left, right, bottom, top, nearVal, farVal;
|
||||||
glm::vec4 nearClipPlane, farClipPlane;
|
glm::vec4 nearClipPlane, farClipPlane;
|
||||||
|
@ -133,6 +141,49 @@ void ViewFrustum::calculate() {
|
||||||
_keyholeBoundingBox = AABox(corner,(_keyholeRadius * 2.0f));
|
_keyholeBoundingBox = AABox(corner,(_keyholeRadius * 2.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::calculateOrthographic() {
|
||||||
|
float halfWidth = _width * 0.5f;
|
||||||
|
float halfHeight = _height * 0.5f;
|
||||||
|
|
||||||
|
// find the corners of the view box in world space
|
||||||
|
glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction)) *
|
||||||
|
glm::translate(_eyeOffsetPosition) * glm::mat4_cast(_eyeOffsetOrientation);
|
||||||
|
_farTopLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, halfHeight, -_farClip, 1.0f));
|
||||||
|
_farTopRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, halfHeight, -_farClip, 1.0f));
|
||||||
|
_farBottomLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, -halfHeight, -_farClip, 1.0f));
|
||||||
|
_farBottomRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, -halfHeight, -_farClip, 1.0f));
|
||||||
|
_nearTopLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, halfHeight, -_nearClip, 1.0f));
|
||||||
|
_nearTopRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, halfHeight, -_nearClip, 1.0f));
|
||||||
|
_nearBottomLeft = glm::vec3(worldMatrix * glm::vec4(-halfWidth, -halfHeight, -_nearClip, 1.0f));
|
||||||
|
_nearBottomRight = glm::vec3(worldMatrix * glm::vec4(halfWidth, -halfHeight, -_nearClip, 1.0f));
|
||||||
|
|
||||||
|
// compute the offset position and axes in world space
|
||||||
|
_offsetPosition = glm::vec3(worldMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
_offsetDirection = glm::vec3(worldMatrix * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
|
||||||
|
_offsetUp = glm::vec3(worldMatrix * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
|
||||||
|
_offsetRight = glm::vec3(worldMatrix * glm::vec4(1.0f, 0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
_planes[TOP_PLANE].set3Points(_nearTopRight, _nearTopLeft, _farTopLeft);
|
||||||
|
_planes[BOTTOM_PLANE].set3Points(_nearBottomLeft, _nearBottomRight, _farBottomRight);
|
||||||
|
_planes[LEFT_PLANE].set3Points(_nearBottomLeft, _farBottomLeft, _farTopLeft);
|
||||||
|
_planes[RIGHT_PLANE].set3Points(_farBottomRight, _nearBottomRight, _nearTopRight);
|
||||||
|
_planes[NEAR_PLANE].set3Points(_nearBottomRight, _nearBottomLeft, _nearTopLeft);
|
||||||
|
_planes[FAR_PLANE].set3Points(_farBottomLeft, _farBottomRight, _farTopRight);
|
||||||
|
|
||||||
|
// Also calculate our projection matrix in case people want to project points...
|
||||||
|
// Projection matrix : Field of View, ratio, display range : near to far
|
||||||
|
glm::mat4 projection = glm::ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, _nearClip, _farClip);
|
||||||
|
glm::vec3 lookAt = _position + _direction;
|
||||||
|
glm::mat4 view = glm::lookAt(_position, lookAt, _up);
|
||||||
|
|
||||||
|
// Our ModelViewProjection : multiplication of our 3 matrices (note: model is identity, so we can drop it)
|
||||||
|
_ourModelViewProjectionMatrix = projection * view; // Remember, matrix multiplication is the other way around
|
||||||
|
|
||||||
|
// Set up our keyhole bounding box...
|
||||||
|
glm::vec3 corner = _position - _keyholeRadius;
|
||||||
|
_keyholeBoundingBox = AABox(corner, (_keyholeRadius * 2.0f));
|
||||||
|
}
|
||||||
|
|
||||||
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||||
const char* ViewFrustum::debugPlaneName (int plane) const {
|
const char* ViewFrustum::debugPlaneName (int plane) const {
|
||||||
switch (plane) {
|
switch (plane) {
|
||||||
|
|
|
@ -41,6 +41,9 @@ public:
|
||||||
const glm::vec3& getRight() const { return _right; }
|
const glm::vec3& getRight() const { return _right; }
|
||||||
|
|
||||||
// setters for lens attributes
|
// setters for lens attributes
|
||||||
|
void setOrthographic(bool orthographic) { _orthographic = orthographic; }
|
||||||
|
void setWidth(float width) { _width = width; }
|
||||||
|
void setHeight(float height) { _height = height; }
|
||||||
void setFieldOfView(float f) { _fieldOfView = f; }
|
void setFieldOfView(float f) { _fieldOfView = f; }
|
||||||
void setAspectRatio(float a) { _aspectRatio = a; }
|
void setAspectRatio(float a) { _aspectRatio = a; }
|
||||||
void setNearClip(float n) { _nearClip = n; }
|
void setNearClip(float n) { _nearClip = n; }
|
||||||
|
@ -50,6 +53,9 @@ public:
|
||||||
void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; }
|
void setEyeOffsetOrientation(const glm::quat& o) { _eyeOffsetOrientation = o; }
|
||||||
|
|
||||||
// getters for lens attributes
|
// getters for lens attributes
|
||||||
|
bool isOrthographic() const { return _orthographic; }
|
||||||
|
float getWidth() const { return _width; }
|
||||||
|
float getHeight() const { return _height; }
|
||||||
float getFieldOfView() const { return _fieldOfView; }
|
float getFieldOfView() const { return _fieldOfView; }
|
||||||
float getAspectRatio() const { return _aspectRatio; }
|
float getAspectRatio() const { return _aspectRatio; }
|
||||||
float getNearClip() const { return _nearClip; }
|
float getNearClip() const { return _nearClip; }
|
||||||
|
@ -114,6 +120,8 @@ private:
|
||||||
ViewFrustum::location sphereInKeyhole(const glm::vec3& center, float radius) const;
|
ViewFrustum::location sphereInKeyhole(const glm::vec3& center, float radius) const;
|
||||||
ViewFrustum::location boxInKeyhole(const AABox& box) const;
|
ViewFrustum::location boxInKeyhole(const AABox& box) const;
|
||||||
|
|
||||||
|
void calculateOrthographic();
|
||||||
|
|
||||||
// camera location/orientation attributes
|
// camera location/orientation attributes
|
||||||
glm::vec3 _position; // the position in TREE_SCALE
|
glm::vec3 _position; // the position in TREE_SCALE
|
||||||
glm::vec3 _positionVoxelScale; // the position in voxel scale
|
glm::vec3 _positionVoxelScale; // the position in voxel scale
|
||||||
|
@ -125,6 +133,9 @@ private:
|
||||||
glm::vec3 _right;
|
glm::vec3 _right;
|
||||||
|
|
||||||
// Lens attributes
|
// Lens attributes
|
||||||
|
bool _orthographic;
|
||||||
|
float _width;
|
||||||
|
float _height;
|
||||||
float _fieldOfView; // degrees
|
float _fieldOfView; // degrees
|
||||||
float _aspectRatio;
|
float _aspectRatio;
|
||||||
float _nearClip;
|
float _nearClip;
|
||||||
|
|
Loading…
Reference in a new issue