mirror of
https://github.com/JulianGro/overte.git
synced 2025-05-05 18:28:00 +02:00
Merge pull request #2468 from ey6es/master
Cull against shadow volume when rendering avatar shadows, don't use textures/fancy shaders when rendering shadow map.
This commit is contained in:
commit
763976e723
22 changed files with 260 additions and 120 deletions
|
@ -4,22 +4,22 @@
|
||||||
<context>
|
<context>
|
||||||
<name>Application</name>
|
<name>Application</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Application.cpp" line="1364"/>
|
<location filename="src/Application.cpp" line="1368"/>
|
||||||
<source>Export Voxels</source>
|
<source>Export Voxels</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Application.cpp" line="1365"/>
|
<location filename="src/Application.cpp" line="1369"/>
|
||||||
<source>Sparse Voxel Octree Files (*.svo)</source>
|
<source>Sparse Voxel Octree Files (*.svo)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Application.cpp" line="3577"/>
|
<location filename="src/Application.cpp" line="3596"/>
|
||||||
<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="3578"/>
|
<location filename="src/Application.cpp" line="3597"/>
|
||||||
<source>JavaScript Files (*.js)</source>
|
<source>JavaScript Files (*.js)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -113,18 +113,18 @@
|
||||||
<context>
|
<context>
|
||||||
<name>Menu</name>
|
<name>Menu</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="439"/>
|
<location filename="src/Menu.cpp" line="449"/>
|
||||||
<source>Open .ini config file</source>
|
<source>Open .ini config file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="441"/>
|
<location filename="src/Menu.cpp" line="451"/>
|
||||||
<location filename="src/Menu.cpp" line="453"/>
|
<location filename="src/Menu.cpp" line="463"/>
|
||||||
<source>Text files (*.ini)</source>
|
<source>Text files (*.ini)</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/Menu.cpp" line="451"/>
|
<location filename="src/Menu.cpp" line="461"/>
|
||||||
<source>Save .ini config file</source>
|
<source>Save .ini config file</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
@ -132,28 +132,28 @@
|
||||||
<context>
|
<context>
|
||||||
<name>QObject</name>
|
<name>QObject</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/ImportDialog.cpp" line="22"/>
|
<location filename="src/ui/ImportDialog.cpp" line="22"/>
|
||||||
<location filename="src/ImportDialog.cpp" line="23"/>
|
<location filename="src/ui/ImportDialog.cpp" line="23"/>
|
||||||
<source>Import Voxels</source>
|
<source>Import Voxels</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/ImportDialog.cpp" line="24"/>
|
<location filename="src/ui/ImportDialog.cpp" line="24"/>
|
||||||
<source>Loading ...</source>
|
<source>Loading ...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/ImportDialog.cpp" line="25"/>
|
<location filename="src/ui/ImportDialog.cpp" line="25"/>
|
||||||
<source>Place voxels</source>
|
<source>Place voxels</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/ImportDialog.cpp" line="26"/>
|
<location filename="src/ui/ImportDialog.cpp" line="26"/>
|
||||||
<source><b>Import</b> %1 as voxels</source>
|
<source><b>Import</b> %1 as voxels</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="src/ImportDialog.cpp" line="27"/>
|
<location filename="src/ui/ImportDialog.cpp" line="27"/>
|
||||||
<source>Cancel</source>
|
<source>Cancel</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
|
14
interface/resources/shaders/model_shadow.frag
Normal file
14
interface/resources/shaders/model_shadow.frag
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_shadow.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Andrzej Kapolka on 3/24/14.
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// fixed color for now (we may eventually want to use texture alpha)
|
||||||
|
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
}
|
14
interface/resources/shaders/model_shadow.vert
Normal file
14
interface/resources/shaders/model_shadow.vert
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_shadow.vert
|
||||||
|
// vertex shader
|
||||||
|
//
|
||||||
|
// Created by Andrzej Kapolka on 3/24/14.
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// just use standard pipeline transform
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
27
interface/resources/shaders/skin_model_shadow.vert
Normal file
27
interface/resources/shaders/skin_model_shadow.vert
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// skin_model_shadow.vert
|
||||||
|
// vertex shader
|
||||||
|
//
|
||||||
|
// Created by Andrzej Kapolka on 3/24/14.
|
||||||
|
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
const int MAX_CLUSTERS = 128;
|
||||||
|
const int INDICES_PER_VERTEX = 4;
|
||||||
|
|
||||||
|
uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
||||||
|
|
||||||
|
attribute vec4 clusterIndices;
|
||||||
|
attribute vec4 clusterWeights;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 position = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
for (int i = 0; i < INDICES_PER_VERTEX; i++) {
|
||||||
|
mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])];
|
||||||
|
float clusterWeight = clusterWeights[i];
|
||||||
|
position += clusterMatrix * gl_Vertex * clusterWeight;
|
||||||
|
}
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * position;
|
||||||
|
}
|
|
@ -2167,21 +2167,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]);
|
||||||
|
@ -2194,8 +2195,19 @@ 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();
|
||||||
|
@ -2205,16 +2217,14 @@ void Application::updateShadowMap() {
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glm::vec3 axis = glm::axis(rotation);
|
glm::vec3 axis = glm::axis(inverseRotation);
|
||||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
// 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(true);
|
|
||||||
_particles.render();
|
_particles.render();
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
@ -2392,7 +2402,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
||||||
_avatarManager.renderAvatars(mirrorMode, selfAvatarOnly);
|
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);
|
||||||
|
|
||||||
if (!selfAvatarOnly) {
|
if (!selfAvatarOnly) {
|
||||||
// Render the world box
|
// Render the world box
|
||||||
|
|
|
@ -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; }
|
||||||
|
@ -390,6 +391,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;
|
||||||
|
|
|
@ -189,10 +189,12 @@ static TextRenderer* textRenderer(TextRendererType type) {
|
||||||
return displayNameRenderer;
|
return displayNameRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) {
|
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(cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) {
|
ViewFrustum* frustum = (renderMode == Avatar::SHADOW_RENDER_MODE) ?
|
||||||
|
Application::getInstance()->getShadowViewFrustum() : Application::getInstance()->getViewFrustum();
|
||||||
|
if (frustum->sphereInFrustum(_position, boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,11 +204,11 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) {
|
||||||
{
|
{
|
||||||
// glow when moving far away
|
// glow when moving far away
|
||||||
const float GLOW_DISTANCE = 20.0f;
|
const float GLOW_DISTANCE = 20.0f;
|
||||||
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f);
|
Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
||||||
|
|
||||||
// render body
|
// render body
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||||
renderBody(forShadowMap);
|
renderBody(renderMode);
|
||||||
}
|
}
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
|
||||||
_skeletonModel.renderCollisionProxies(0.7f);
|
_skeletonModel.renderCollisionProxies(0.7f);
|
||||||
|
@ -230,7 +232,8 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) {
|
||||||
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
||||||
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
||||||
|
|
||||||
if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
if (renderMode == NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
|
||||||
|
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
||||||
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
|
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glTranslatef(_position.x, _position.y, _position.z);
|
glTranslatef(_position.x, _position.y, _position.z);
|
||||||
|
@ -242,8 +245,8 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const float DISPLAYNAME_DISTANCE = 10.0f;
|
const float DISPLAYNAME_DISTANCE = 10.0f;
|
||||||
setShowDisplayName(!forShadowMap && distanceToTarget < DISPLAYNAME_DISTANCE);
|
setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
|
||||||
if (forShadowMap) {
|
if (renderMode != NORMAL_RENDER_MODE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
renderDisplayName();
|
renderDisplayName();
|
||||||
|
@ -306,17 +309,16 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
return glm::angleAxis(angle * proportion, axis);
|
return glm::angleAxis(angle * proportion, axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::renderBody(bool forShadowMap) {
|
void Avatar::renderBody(RenderMode renderMode) {
|
||||||
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
// render the billboard until both models are loaded
|
// render the billboard until both models are loaded
|
||||||
if (forShadowMap) {
|
if (renderMode != SHADOW_RENDER_MODE) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
renderBillboard();
|
renderBillboard();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_skeletonModel.render(1.0f);
|
_skeletonModel.render(1.0f, renderMode == SHADOW_RENDER_MODE);
|
||||||
getHead()->render(1.0f);
|
getHead()->render(1.0f, renderMode == SHADOW_RENDER_MODE);
|
||||||
getHand()->render(false);
|
getHand()->render(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,10 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
virtual void render(const glm::vec3& cameraPosition, bool forShadowMap);
|
|
||||||
|
enum RenderMode { NORMAL_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE };
|
||||||
|
|
||||||
|
virtual void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
|
||||||
|
|
||||||
//setters
|
//setters
|
||||||
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); }
|
||||||
|
@ -181,7 +184,7 @@ protected:
|
||||||
float getPelvisToHeadLength() const;
|
float getPelvisToHeadLength() const;
|
||||||
|
|
||||||
void renderDisplayName();
|
void renderDisplayName();
|
||||||
virtual void renderBody(bool forShadowMap);
|
virtual void renderBody(RenderMode renderMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
simulateAvatarFades(deltaTime);
|
simulateAvatarFades(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly) {
|
void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly) {
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::renderAvatars()");
|
"Application::renderAvatars()");
|
||||||
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
|
bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors);
|
||||||
|
@ -85,13 +85,13 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly
|
||||||
if (!avatar->isInitialized()) {
|
if (!avatar->isInitialized()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
avatar->render(cameraPosition, forShadowMapOrMirror);
|
avatar->render(cameraPosition, renderMode);
|
||||||
avatar->setDisplayingLookatVectors(renderLookAtVectors);
|
avatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||||
}
|
}
|
||||||
renderAvatarFades(cameraPosition, forShadowMapOrMirror);
|
renderAvatarFades(cameraPosition, renderMode);
|
||||||
} else {
|
} else {
|
||||||
// just render myAvatar
|
// just render myAvatar
|
||||||
_myAvatar->render(cameraPosition, forShadowMapOrMirror);
|
_myAvatar->render(cameraPosition, renderMode);
|
||||||
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
|
_myAvatar->setDisplayingLookatVectors(renderLookAtVectors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,14 +114,14 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap) {
|
void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode) {
|
||||||
// render avatar fades
|
// render avatar fades
|
||||||
Glower glower(forShadowMap ? 0.0f : 1.0f);
|
Glower glower(renderMode == Avatar::NORMAL_RENDER_MODE ? 1.0f : 0.0f);
|
||||||
|
|
||||||
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) {
|
||||||
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
Avatar* avatar = static_cast<Avatar*>(fadingAvatar.data());
|
||||||
if (avatar != static_cast<Avatar*>(_myAvatar.data())) {
|
if (avatar != static_cast<Avatar*>(_myAvatar.data())) {
|
||||||
avatar->render(cameraPosition, forShadowMap);
|
avatar->render(cameraPosition, renderMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public:
|
||||||
MyAvatar* getMyAvatar() { return _myAvatar.data(); }
|
MyAvatar* getMyAvatar() { return _myAvatar.data(); }
|
||||||
|
|
||||||
void updateOtherAvatars(float deltaTime);
|
void updateOtherAvatars(float deltaTime);
|
||||||
void renderAvatars(bool forShadowMapOrMirror = false, bool selfAvatarOnly = false);
|
void renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly = false);
|
||||||
|
|
||||||
void clearOtherAvatars();
|
void clearOtherAvatars();
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ private:
|
||||||
void processKillAvatar(const QByteArray& datagram);
|
void processKillAvatar(const QByteArray& datagram);
|
||||||
|
|
||||||
void simulateAvatarFades(float deltaTime);
|
void simulateAvatarFades(float deltaTime);
|
||||||
void renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap);
|
void renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode);
|
||||||
|
|
||||||
// virtual override
|
// virtual override
|
||||||
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
AvatarHash::iterator erase(const AvatarHash::iterator& iterator);
|
||||||
|
|
|
@ -45,13 +45,6 @@ void FaceModel::simulate(float deltaTime) {
|
||||||
Model::simulate(deltaTime, true, newJointStates);
|
Model::simulate(deltaTime, true, newJointStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FaceModel::render(float alpha) {
|
|
||||||
if (!Model::render(alpha)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
// get the rotation axes in joint space and use them to adjust the rotation
|
// get the rotation axes in joint space and use them to adjust the rotation
|
||||||
glm::mat3 axes = glm::mat3_cast(_rotation);
|
glm::mat3 axes = glm::mat3_cast(_rotation);
|
||||||
|
|
|
@ -22,7 +22,6 @@ public:
|
||||||
FaceModel(Head* owningHead);
|
FaceModel(Head* owningHead);
|
||||||
|
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
bool render(float alpha);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
|
@ -168,8 +168,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
||||||
_eyePosition = calculateAverageEyePosition();
|
_eyePosition = calculateAverageEyePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Head::render(float alpha) {
|
void Head::render(float alpha, bool forShadowMap) {
|
||||||
if (_faceModel.render(alpha) && _renderLookatVectors) {
|
if (_faceModel.render(alpha, forShadowMap) && _renderLookatVectors) {
|
||||||
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
|
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void reset();
|
void reset();
|
||||||
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
void simulate(float deltaTime, bool isMine, bool billboard = false);
|
||||||
void render(float alpha);
|
void render(float alpha, bool forShadowMap);
|
||||||
void setScale(float scale);
|
void setScale(float scale);
|
||||||
void setPosition(glm::vec3 position) { _position = position; }
|
void setPosition(glm::vec3 position) { _position = position; }
|
||||||
void setGravity(glm::vec3 gravity) { _gravity = gravity; }
|
void setGravity(glm::vec3 gravity) { _gravity = gravity; }
|
||||||
|
|
|
@ -450,12 +450,12 @@ void MyAvatar::renderDebugBodyPoints() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
void MyAvatar::render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror) {
|
void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
// don't render if we've been asked to disable local rendering
|
// don't render if we've been asked to disable local rendering
|
||||||
if (!_shouldRender) {
|
if (!_shouldRender) {
|
||||||
return; // exit early
|
return; // exit early
|
||||||
}
|
}
|
||||||
Avatar::render(cameraPosition, forShadowMapOrMirror);
|
Avatar::render(cameraPosition, renderMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::renderHeadMouse() const {
|
void MyAvatar::renderHeadMouse() const {
|
||||||
|
@ -638,20 +638,20 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
_billboardValid = false;
|
_billboardValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::renderBody(bool forceRenderHead) {
|
void MyAvatar::renderBody(RenderMode renderMode) {
|
||||||
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
|
||||||
return; // wait until both models are loaded
|
return; // wait until both models are loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the body's voxels and head
|
// Render the body's voxels and head
|
||||||
_skeletonModel.render(1.0f);
|
_skeletonModel.render(1.0f, renderMode == SHADOW_RENDER_MODE);
|
||||||
|
|
||||||
// Render head so long as the camera isn't inside it
|
// Render head so long as the camera isn't inside it
|
||||||
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.40f;
|
const float RENDER_HEAD_CUTOFF_DISTANCE = 0.40f;
|
||||||
Camera* myCamera = Application::getInstance()->getCamera();
|
Camera* myCamera = Application::getInstance()->getCamera();
|
||||||
if (forceRenderHead || (glm::length(myCamera->getPosition() - getHead()->calculateAverageEyePosition()) >
|
if (renderMode != NORMAL_RENDER_MODE || (glm::length(myCamera->getPosition() - getHead()->calculateAverageEyePosition()) >
|
||||||
RENDER_HEAD_CUTOFF_DISTANCE * _scale)) {
|
RENDER_HEAD_CUTOFF_DISTANCE * _scale)) {
|
||||||
getHead()->render(1.0f);
|
getHead()->render(1.0f, renderMode == SHADOW_RENDER_MODE);
|
||||||
}
|
}
|
||||||
getHand()->render(true);
|
getHand()->render(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ public:
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
void updateFromGyros(float deltaTime);
|
void updateFromGyros(float deltaTime);
|
||||||
|
|
||||||
void render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror = false);
|
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
|
||||||
void renderBody(bool forceRenderHead);
|
void renderBody(RenderMode renderMode);
|
||||||
void renderDebugBodyPoints();
|
void renderDebugBodyPoints();
|
||||||
void renderHeadMouse() const;
|
void renderHeadMouse() const;
|
||||||
|
|
||||||
|
|
|
@ -62,17 +62,6 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkeletonModel::render(float alpha) {
|
|
||||||
|
|
||||||
if (_jointStates.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Model::render(alpha);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkeletonModel::getHandShapes(int jointIndex, QVector<const Shape*>& shapes) const {
|
void SkeletonModel::getHandShapes(int jointIndex, QVector<const Shape*>& shapes) const {
|
||||||
if (jointIndex == -1) {
|
if (jointIndex == -1) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -23,7 +23,6 @@ public:
|
||||||
SkeletonModel(Avatar* owningAvatar);
|
SkeletonModel(Avatar* owningAvatar);
|
||||||
|
|
||||||
void simulate(float deltaTime, bool fullUpdate = true);
|
void simulate(float deltaTime, bool fullUpdate = true);
|
||||||
bool render(float alpha);
|
|
||||||
|
|
||||||
/// \param jointIndex index of hand joint
|
/// \param jointIndex index of hand joint
|
||||||
/// \param shapes[out] list in which is stored pointers to hand shapes
|
/// \param shapes[out] list in which is stored pointers to hand shapes
|
||||||
|
|
|
@ -43,11 +43,14 @@ Model::~Model() {
|
||||||
|
|
||||||
ProgramObject Model::_program;
|
ProgramObject Model::_program;
|
||||||
ProgramObject Model::_normalMapProgram;
|
ProgramObject Model::_normalMapProgram;
|
||||||
|
ProgramObject Model::_shadowProgram;
|
||||||
ProgramObject Model::_skinProgram;
|
ProgramObject Model::_skinProgram;
|
||||||
ProgramObject Model::_skinNormalMapProgram;
|
ProgramObject Model::_skinNormalMapProgram;
|
||||||
|
ProgramObject Model::_skinShadowProgram;
|
||||||
int Model::_normalMapTangentLocation;
|
int Model::_normalMapTangentLocation;
|
||||||
Model::SkinLocations Model::_skinLocations;
|
Model::SkinLocations Model::_skinLocations;
|
||||||
Model::SkinLocations Model::_skinNormalMapLocations;
|
Model::SkinLocations Model::_skinNormalMapLocations;
|
||||||
|
Model::SkinLocations Model::_skinShadowLocations;
|
||||||
|
|
||||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) {
|
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) {
|
||||||
program.bind();
|
program.bind();
|
||||||
|
@ -93,6 +96,11 @@ void Model::init() {
|
||||||
_normalMapTangentLocation = _normalMapProgram.attributeLocation("tangent");
|
_normalMapTangentLocation = _normalMapProgram.attributeLocation("tangent");
|
||||||
_normalMapProgram.release();
|
_normalMapProgram.release();
|
||||||
|
|
||||||
|
_shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");
|
||||||
|
_shadowProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() +
|
||||||
|
"shaders/model_shadow.frag");
|
||||||
|
_shadowProgram.link();
|
||||||
|
|
||||||
_skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath()
|
_skinProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath()
|
||||||
+ "shaders/skin_model.vert");
|
+ "shaders/skin_model.vert");
|
||||||
_skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath()
|
_skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath()
|
||||||
|
@ -108,6 +116,14 @@ void Model::init() {
|
||||||
_skinNormalMapProgram.link();
|
_skinNormalMapProgram.link();
|
||||||
|
|
||||||
initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations);
|
initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations);
|
||||||
|
|
||||||
|
_skinShadowProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
|
Application::resourcesPath() + "shaders/skin_model_shadow.vert");
|
||||||
|
_skinShadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
Application::resourcesPath() + "shaders/model_shadow.frag");
|
||||||
|
_skinShadowProgram.link();
|
||||||
|
|
||||||
|
initSkinProgram(_skinShadowProgram, _skinShadowLocations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +183,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||||
simulate(deltaTime, fullUpdate, updateGeometry());
|
simulate(deltaTime, fullUpdate, updateGeometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::render(float alpha) {
|
bool Model::render(float alpha, bool forShadowMap) {
|
||||||
// render the attachments
|
// render the attachments
|
||||||
foreach (Model* attachment, _attachments) {
|
foreach (Model* attachment, _attachments) {
|
||||||
attachment->render(alpha);
|
attachment->render(alpha);
|
||||||
|
@ -198,13 +214,13 @@ bool Model::render(float alpha) {
|
||||||
glEnable(GL_ALPHA_TEST);
|
glEnable(GL_ALPHA_TEST);
|
||||||
glAlphaFunc(GL_GREATER, 0.5f * alpha);
|
glAlphaFunc(GL_GREATER, 0.5f * alpha);
|
||||||
|
|
||||||
renderMeshes(alpha, false);
|
renderMeshes(alpha, forShadowMap, false);
|
||||||
|
|
||||||
glDisable(GL_ALPHA_TEST);
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
// render translucent meshes afterwards, with back face culling
|
// render translucent meshes afterwards, with back face culling
|
||||||
|
|
||||||
renderMeshes(alpha, true);
|
renderMeshes(alpha, forShadowMap, true);
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
@ -960,7 +976,7 @@ void Model::deleteGeometry() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::renderMeshes(float alpha, bool translucent) {
|
void Model::renderMeshes(float alpha, bool forShadowMap, bool translucent) {
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||||
|
|
||||||
|
@ -985,7 +1001,12 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
ProgramObject* program = &_program;
|
ProgramObject* program = &_program;
|
||||||
ProgramObject* skinProgram = &_skinProgram;
|
ProgramObject* skinProgram = &_skinProgram;
|
||||||
SkinLocations* skinLocations = &_skinLocations;
|
SkinLocations* skinLocations = &_skinLocations;
|
||||||
if (!mesh.tangents.isEmpty()) {
|
if (forShadowMap) {
|
||||||
|
program = &_shadowProgram;
|
||||||
|
skinProgram = &_skinShadowProgram;
|
||||||
|
skinLocations = &_skinShadowLocations;
|
||||||
|
|
||||||
|
} else if (!mesh.tangents.isEmpty()) {
|
||||||
program = &_normalMapProgram;
|
program = &_normalMapProgram;
|
||||||
skinProgram = &_skinNormalMapProgram;
|
skinProgram = &_skinNormalMapProgram;
|
||||||
skinLocations = &_skinNormalMapLocations;
|
skinLocations = &_skinNormalMapLocations;
|
||||||
|
@ -1018,7 +1039,7 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.blendshapes.isEmpty()) {
|
if (mesh.blendshapes.isEmpty()) {
|
||||||
if (!mesh.tangents.isEmpty()) {
|
if (!(mesh.tangents.isEmpty() || forShadowMap)) {
|
||||||
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
||||||
activeProgram->enableAttributeArray(tangentLocation);
|
activeProgram->enableAttributeArray(tangentLocation);
|
||||||
}
|
}
|
||||||
|
@ -1028,7 +1049,7 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
(mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
|
(mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3)));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (!mesh.tangents.isEmpty()) {
|
if (!(mesh.tangents.isEmpty() || forShadowMap)) {
|
||||||
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, 0, 3);
|
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, 0, 3);
|
||||||
activeProgram->enableAttributeArray(tangentLocation);
|
activeProgram->enableAttributeArray(tangentLocation);
|
||||||
}
|
}
|
||||||
|
@ -1057,6 +1078,10 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// apply material properties
|
// apply material properties
|
||||||
|
if (forShadowMap) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
glm::vec4 diffuse = glm::vec4(part.diffuseColor, alpha);
|
glm::vec4 diffuse = glm::vec4(part.diffuseColor, alpha);
|
||||||
glm::vec4 specular = glm::vec4(part.specularColor, alpha);
|
glm::vec4 specular = glm::vec4(part.specularColor, alpha);
|
||||||
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||||
|
@ -1065,12 +1090,10 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
glMaterialf(GL_FRONT, GL_SHININESS, part.shininess);
|
glMaterialf(GL_FRONT, GL_SHININESS, part.shininess);
|
||||||
|
|
||||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||||
if (mesh.isEye) {
|
if (mesh.isEye && diffuseMap) {
|
||||||
if (diffuseMap) {
|
|
||||||
diffuseMap = (_dilatedTextures[i][j] =
|
diffuseMap = (_dilatedTextures[i][j] =
|
||||||
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
static_cast<DilatableNetworkTexture*>(diffuseMap)->getDilatedTexture(_pupilDilation)).data();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
glBindTexture(GL_TEXTURE_2D, !diffuseMap ?
|
glBindTexture(GL_TEXTURE_2D, !diffuseMap ?
|
||||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
||||||
|
|
||||||
|
@ -1081,7 +1104,7 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID());
|
Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID());
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset);
|
||||||
offset += part.quadIndices.size() * sizeof(int);
|
offset += part.quadIndices.size() * sizeof(int);
|
||||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertexCount - 1, part.triangleIndices.size(),
|
||||||
|
@ -1096,7 +1119,7 @@ void Model::renderMeshes(float alpha, bool translucent) {
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mesh.tangents.isEmpty()) {
|
if (!(mesh.tangents.isEmpty() || forShadowMap)) {
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
void createCollisionShapes();
|
void createCollisionShapes();
|
||||||
void updateShapePositions();
|
void updateShapePositions();
|
||||||
void simulate(float deltaTime, bool fullUpdate = true);
|
void simulate(float deltaTime, bool fullUpdate = true);
|
||||||
bool render(float alpha);
|
bool render(float alpha = 1.0f, bool forShadowMap = false);
|
||||||
|
|
||||||
/// Sets the URL of the model to render.
|
/// Sets the URL of the model to render.
|
||||||
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
/// \param fallback the URL of a fallback model to render if the requested model fails to load
|
||||||
|
@ -261,7 +261,7 @@ private:
|
||||||
|
|
||||||
void applyNextGeometry();
|
void applyNextGeometry();
|
||||||
void deleteGeometry();
|
void deleteGeometry();
|
||||||
void renderMeshes(float alpha, bool translucent);
|
void renderMeshes(float alpha, bool forShadowMap, bool translucent);
|
||||||
|
|
||||||
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
QSharedPointer<NetworkGeometry> _baseGeometry; ///< reference required to prevent collection of base
|
||||||
QSharedPointer<NetworkGeometry> _nextBaseGeometry;
|
QSharedPointer<NetworkGeometry> _nextBaseGeometry;
|
||||||
|
@ -283,8 +283,10 @@ private:
|
||||||
|
|
||||||
static ProgramObject _program;
|
static ProgramObject _program;
|
||||||
static ProgramObject _normalMapProgram;
|
static ProgramObject _normalMapProgram;
|
||||||
|
static ProgramObject _shadowProgram;
|
||||||
static ProgramObject _skinProgram;
|
static ProgramObject _skinProgram;
|
||||||
static ProgramObject _skinNormalMapProgram;
|
static ProgramObject _skinNormalMapProgram;
|
||||||
|
static ProgramObject _skinShadowProgram;
|
||||||
|
|
||||||
static int _normalMapTangentLocation;
|
static int _normalMapTangentLocation;
|
||||||
|
|
||||||
|
@ -298,6 +300,7 @@ private:
|
||||||
|
|
||||||
static SkinLocations _skinLocations;
|
static SkinLocations _skinLocations;
|
||||||
static SkinLocations _skinNormalMapLocations;
|
static SkinLocations _skinNormalMapLocations;
|
||||||
|
static SkinLocations _skinShadowLocations;
|
||||||
|
|
||||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations);
|
static void initSkinProgram(ProgramObject& program, SkinLocations& locations);
|
||||||
static QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
static QVector<JointState> createJointStates(const FBXGeometry& geometry);
|
||||||
|
|
|
@ -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