From 62884f1f4fca9f2e8a9f511d2fb13b036c9816ee Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 24 Mar 2014 13:15:03 -0700 Subject: [PATCH] Don't use textures/fancy shaders when rendering shadow map. Closes #2270. --- interface/interface_en.ts | 12 +-- interface/resources/shaders/model_shadow.frag | 14 ++++ interface/resources/shaders/model_shadow.vert | 14 ++++ .../resources/shaders/skin_model_shadow.vert | 27 +++++++ interface/src/Application.cpp | 4 +- interface/src/avatar/Avatar.cpp | 27 ++++--- interface/src/avatar/Avatar.h | 7 +- interface/src/avatar/AvatarManager.cpp | 14 ++-- interface/src/avatar/AvatarManager.h | 4 +- interface/src/avatar/FaceModel.cpp | 7 -- interface/src/avatar/FaceModel.h | 1 - interface/src/avatar/Head.cpp | 4 +- interface/src/avatar/Head.h | 2 +- interface/src/avatar/MyAvatar.cpp | 12 +-- interface/src/avatar/MyAvatar.h | 4 +- interface/src/avatar/SkeletonModel.cpp | 11 --- interface/src/avatar/SkeletonModel.h | 1 - interface/src/renderer/Model.cpp | 81 ++++++++++++------- interface/src/renderer/Model.h | 7 +- 19 files changed, 159 insertions(+), 94 deletions(-) create mode 100644 interface/resources/shaders/model_shadow.frag create mode 100644 interface/resources/shaders/model_shadow.vert create mode 100644 interface/resources/shaders/skin_model_shadow.vert diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 34e3614716..74ac030afc 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,12 +14,12 @@ - + Open Script - + JavaScript Files (*.js) @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/resources/shaders/model_shadow.frag b/interface/resources/shaders/model_shadow.frag new file mode 100644 index 0000000000..bcb597b13c --- /dev/null +++ b/interface/resources/shaders/model_shadow.frag @@ -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); +} diff --git a/interface/resources/shaders/model_shadow.vert b/interface/resources/shaders/model_shadow.vert new file mode 100644 index 0000000000..ae7e871887 --- /dev/null +++ b/interface/resources/shaders/model_shadow.vert @@ -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(); +} diff --git a/interface/resources/shaders/skin_model_shadow.vert b/interface/resources/shaders/skin_model_shadow.vert new file mode 100644 index 0000000000..b9ef05ad8a --- /dev/null +++ b/interface/resources/shaders/skin_model_shadow.vert @@ -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; +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9563cbf3b4..994423b9c4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2210,7 +2210,7 @@ void Application::updateShadowMap() { glTranslatef(translation.x, translation.y, translation.z); - _avatarManager.renderAvatars(true); + _avatarManager.renderAvatars(Avatar::SHADOW_RENDER_MODE); _particles.render(); glPopMatrix(); @@ -2388,7 +2388,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { } 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) { // Render the world box diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 75a8386ea9..2b94947928 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -189,10 +189,11 @@ static TextRenderer* textRenderer(TextRendererType type) { return displayNameRenderer; } -void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) { +void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { // simple frustum check float boundingRadius = getBillboardSize(); - if (Application::getInstance()->getViewFrustum()->sphereInFrustum(cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) { + if (Application::getInstance()->getViewFrustum()->sphereInFrustum( + cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) { return; } @@ -202,11 +203,11 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) { { // glow when moving far away 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 if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - renderBody(forShadowMap); + renderBody(renderMode); } if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { _skeletonModel.renderCollisionProxies(0.7f); @@ -230,7 +231,8 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) { float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); 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); glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); @@ -242,8 +244,8 @@ void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) { } const float DISPLAYNAME_DISTANCE = 10.0f; - setShowDisplayName(!forShadowMap && distanceToTarget < DISPLAYNAME_DISTANCE); - if (forShadowMap) { + setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE); + if (renderMode != NORMAL_RENDER_MODE) { return; } renderDisplayName(); @@ -306,17 +308,16 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody(bool forShadowMap) { +void Avatar::renderBody(RenderMode renderMode) { if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { // render the billboard until both models are loaded - if (forShadowMap) { - return; + if (renderMode != SHADOW_RENDER_MODE) { + renderBillboard(); } - renderBillboard(); return; } - _skeletonModel.render(1.0f); - getHead()->render(1.0f); + _skeletonModel.render(1.0f, renderMode == SHADOW_RENDER_MODE); + getHead()->render(1.0f, renderMode == SHADOW_RENDER_MODE); getHand()->render(false); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 638bff6e32..25600e0943 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -74,7 +74,10 @@ public: void init(); 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 void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } @@ -181,7 +184,7 @@ protected: float getPelvisToHeadLength() const; void renderDisplayName(); - virtual void renderBody(bool forShadowMap); + virtual void renderBody(RenderMode renderMode); private: diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 29b23e1f5b..9147a08dbd 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -72,7 +72,7 @@ void AvatarManager::updateOtherAvatars(float 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), "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); @@ -85,13 +85,13 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly if (!avatar->isInitialized()) { continue; } - avatar->render(cameraPosition, forShadowMapOrMirror); + avatar->render(cameraPosition, renderMode); avatar->setDisplayingLookatVectors(renderLookAtVectors); } - renderAvatarFades(cameraPosition, forShadowMapOrMirror); + renderAvatarFades(cameraPosition, renderMode); } else { // just render myAvatar - _myAvatar->render(cameraPosition, forShadowMapOrMirror); + _myAvatar->render(cameraPosition, renderMode); _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 - Glower glower(forShadowMap ? 0.0f : 1.0f); + Glower glower(renderMode == Avatar::NORMAL_RENDER_MODE ? 1.0f : 0.0f); foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) { Avatar* avatar = static_cast(fadingAvatar.data()); if (avatar != static_cast(_myAvatar.data())) { - avatar->render(cameraPosition, forShadowMap); + avatar->render(cameraPosition, renderMode); } } } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 455153b92a..06494f309c 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -29,7 +29,7 @@ public: MyAvatar* getMyAvatar() { return _myAvatar.data(); } void updateOtherAvatars(float deltaTime); - void renderAvatars(bool forShadowMapOrMirror = false, bool selfAvatarOnly = false); + void renderAvatars(Avatar::RenderMode renderMode, bool selfAvatarOnly = false); void clearOtherAvatars(); @@ -45,7 +45,7 @@ private: void processKillAvatar(const QByteArray& datagram); void simulateAvatarFades(float deltaTime); - void renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap); + void renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode); // virtual override AvatarHash::iterator erase(const AvatarHash::iterator& iterator); diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index db6c3fe98d..19faa0da42 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -45,13 +45,6 @@ void FaceModel::simulate(float deltaTime) { 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) { // get the rotation axes in joint space and use them to adjust the rotation glm::mat3 axes = glm::mat3_cast(_rotation); diff --git a/interface/src/avatar/FaceModel.h b/interface/src/avatar/FaceModel.h index d0f0f6baef..acf2d2baf4 100644 --- a/interface/src/avatar/FaceModel.h +++ b/interface/src/avatar/FaceModel.h @@ -22,7 +22,6 @@ public: FaceModel(Head* owningHead); void simulate(float deltaTime); - bool render(float alpha); protected: diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 44001a2015..4a81df8b74 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -168,8 +168,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _eyePosition = calculateAverageEyePosition(); } -void Head::render(float alpha) { - if (_faceModel.render(alpha) && _renderLookatVectors) { +void Head::render(float alpha, bool forShadowMap) { + if (_faceModel.render(alpha, forShadowMap) && _renderLookatVectors) { renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); } } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index a9ea9b4cc6..60730c8724 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -37,7 +37,7 @@ public: void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); - void render(float alpha); + void render(float alpha, bool forShadowMap); void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setGravity(glm::vec3 gravity) { _gravity = gravity; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a6a7f22896..711e1d32c3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -451,12 +451,12 @@ void MyAvatar::renderDebugBodyPoints() { } // 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 if (!_shouldRender) { return; // exit early } - Avatar::render(cameraPosition, forShadowMapOrMirror); + Avatar::render(cameraPosition, renderMode); } void MyAvatar::renderHeadMouse() const { @@ -639,20 +639,20 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _billboardValid = false; } -void MyAvatar::renderBody(bool forceRenderHead) { +void MyAvatar::renderBody(RenderMode renderMode) { if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } // 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 const float RENDER_HEAD_CUTOFF_DISTANCE = 0.40f; 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)) { - getHead()->render(1.0f); + getHead()->render(1.0f, renderMode == SHADOW_RENDER_MODE); } getHand()->render(true); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 241286a721..cbb625aa2f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -35,8 +35,8 @@ public: void simulate(float deltaTime); void updateFromGyros(float deltaTime); - void render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror = false); - void renderBody(bool forceRenderHead); + void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE); + void renderBody(RenderMode renderMode); void renderDebugBodyPoints(); void renderHeadMouse() const; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 7173cb0b84..9e4740df15 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -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& shapes) const { if (jointIndex == -1) { return; diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 0bcbcef2ea..514b5daf1c 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -23,7 +23,6 @@ public: SkeletonModel(Avatar* owningAvatar); void simulate(float deltaTime, bool fullUpdate = true); - bool render(float alpha); /// \param jointIndex index of hand joint /// \param shapes[out] list in which is stored pointers to hand shapes diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 16b5c167d9..690b19ee5e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -43,11 +43,14 @@ Model::~Model() { ProgramObject Model::_program; ProgramObject Model::_normalMapProgram; +ProgramObject Model::_shadowProgram; ProgramObject Model::_skinProgram; ProgramObject Model::_skinNormalMapProgram; +ProgramObject Model::_skinShadowProgram; int Model::_normalMapTangentLocation; Model::SkinLocations Model::_skinLocations; Model::SkinLocations Model::_skinNormalMapLocations; +Model::SkinLocations Model::_skinShadowLocations; void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) { program.bind(); @@ -93,6 +96,11 @@ void Model::init() { _normalMapTangentLocation = _normalMapProgram.attributeLocation("tangent"); _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() + "shaders/skin_model.vert"); _skinProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() @@ -108,6 +116,14 @@ void Model::init() { _skinNormalMapProgram.link(); 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()); } -bool Model::render(float alpha) { +bool Model::render(float alpha, bool forShadowMap) { // render the attachments foreach (Model* attachment, _attachments) { attachment->render(alpha); @@ -198,13 +214,13 @@ bool Model::render(float alpha) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f * alpha); - renderMeshes(alpha, false); + renderMeshes(alpha, forShadowMap, false); glDisable(GL_ALPHA_TEST); // render translucent meshes afterwards, with back face culling - renderMeshes(alpha, true); + renderMeshes(alpha, forShadowMap, true); 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 QVector& networkMeshes = _geometry->getMeshes(); @@ -985,7 +1001,12 @@ void Model::renderMeshes(float alpha, bool translucent) { ProgramObject* program = &_program; ProgramObject* skinProgram = &_skinProgram; SkinLocations* skinLocations = &_skinLocations; - if (!mesh.tangents.isEmpty()) { + if (forShadowMap) { + program = &_shadowProgram; + skinProgram = &_skinShadowProgram; + skinLocations = &_skinShadowLocations; + + } else if (!mesh.tangents.isEmpty()) { program = &_normalMapProgram; skinProgram = &_skinNormalMapProgram; skinLocations = &_skinNormalMapLocations; @@ -1018,7 +1039,7 @@ void Model::renderMeshes(float alpha, bool translucent) { } 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->enableAttributeArray(tangentLocation); } @@ -1028,7 +1049,7 @@ void Model::renderMeshes(float alpha, bool translucent) { (mesh.tangents.size() + mesh.colors.size()) * sizeof(glm::vec3))); } else { - if (!mesh.tangents.isEmpty()) { + if (!(mesh.tangents.isEmpty() || forShadowMap)) { activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, 0, 3); activeProgram->enableAttributeArray(tangentLocation); } @@ -1057,31 +1078,33 @@ void Model::renderMeshes(float alpha, bool translucent) { continue; } // apply material properties - glm::vec4 diffuse = glm::vec4(part.diffuseColor, alpha); - glm::vec4 specular = glm::vec4(part.specularColor, alpha); - glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); - glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); - glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular); - glMaterialf(GL_FRONT, GL_SHININESS, part.shininess); - - Texture* diffuseMap = networkPart.diffuseTexture.data(); - if (mesh.isEye) { - if (diffuseMap) { + if (forShadowMap) { + glBindTexture(GL_TEXTURE_2D, 0); + + } else { + glm::vec4 diffuse = glm::vec4(part.diffuseColor, alpha); + glm::vec4 specular = glm::vec4(part.specularColor, alpha); + glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); + glMaterialfv(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, (const float*)&specular); + glMaterialf(GL_FRONT, GL_SHININESS, part.shininess); + + Texture* diffuseMap = networkPart.diffuseTexture.data(); + if (mesh.isEye && diffuseMap) { diffuseMap = (_dilatedTextures[i][j] = static_cast(diffuseMap)->getDilatedTexture(_pupilDilation)).data(); } + glBindTexture(GL_TEXTURE_2D, !diffuseMap ? + Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); + + if (!mesh.tangents.isEmpty()) { + glActiveTexture(GL_TEXTURE1); + Texture* normalMap = networkPart.normalTexture.data(); + glBindTexture(GL_TEXTURE_2D, !normalMap ? + Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); + glActiveTexture(GL_TEXTURE0); + } } - glBindTexture(GL_TEXTURE_2D, !diffuseMap ? - Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID()); - - if (!mesh.tangents.isEmpty()) { - glActiveTexture(GL_TEXTURE1); - Texture* normalMap = networkPart.normalTexture.data(); - glBindTexture(GL_TEXTURE_2D, !normalMap ? - Application::getInstance()->getTextureCache()->getBlueTextureID() : normalMap->getID()); - glActiveTexture(GL_TEXTURE0); - } - glDrawRangeElementsEXT(GL_QUADS, 0, vertexCount - 1, part.quadIndices.size(), GL_UNSIGNED_INT, (void*)offset); offset += part.quadIndices.size() * sizeof(int); 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); } - if (!mesh.tangents.isEmpty()) { + if (!(mesh.tangents.isEmpty() || forShadowMap)) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index f08a6b9fc2..b4f71f14d3 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -58,7 +58,7 @@ public: void createCollisionShapes(); void updateShapePositions(); 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. /// \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 deleteGeometry(); - void renderMeshes(float alpha, bool translucent); + void renderMeshes(float alpha, bool forShadowMap, bool translucent); QSharedPointer _baseGeometry; ///< reference required to prevent collection of base QSharedPointer _nextBaseGeometry; @@ -283,8 +283,10 @@ private: static ProgramObject _program; static ProgramObject _normalMapProgram; + static ProgramObject _shadowProgram; static ProgramObject _skinProgram; static ProgramObject _skinNormalMapProgram; + static ProgramObject _skinShadowProgram; static int _normalMapTangentLocation; @@ -298,6 +300,7 @@ private: static SkinLocations _skinLocations; static SkinLocations _skinNormalMapLocations; + static SkinLocations _skinShadowLocations; static void initSkinProgram(ProgramObject& program, SkinLocations& locations); static QVector createJointStates(const FBXGeometry& geometry);