From 56eadcb0dcae9d48e5054a97c76cb5ab2c194047 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Wed, 9 Jul 2014 12:05:34 -0700 Subject: [PATCH] Get rid of redundant GL calls for fog. Enable and disable fog during rendering stage of voxels. Moved the local light parameters to shader uniform arrays. --- examples/avatarLocalLight.js | 29 +++++----- interface/resources/shaders/model.frag | 17 +++--- interface/resources/shaders/model.vert | 7 --- .../resources/shaders/model_specular_map.frag | 18 ++++++- interface/resources/shaders/skin_model.vert | 9 ---- interface/src/avatar/Avatar.cpp | 54 ++++++++++++++----- interface/src/avatar/Avatar.h | 13 ++--- interface/src/avatar/SkeletonModel.h | 1 + interface/src/renderer/Model.cpp | 22 +++++++- interface/src/renderer/Model.h | 10 ++++ interface/src/renderer/ProgramObject.cpp | 15 ++++++ interface/src/renderer/ProgramObject.h | 1 + interface/src/voxels/VoxelSystem.cpp | 15 ++++-- 13 files changed, 148 insertions(+), 63 deletions(-) diff --git a/examples/avatarLocalLight.js b/examples/avatarLocalLight.js index 600713a037..69b491d430 100644 --- a/examples/avatarLocalLight.js +++ b/examples/avatarLocalLight.js @@ -11,10 +11,11 @@ // var localLightDirections = [ {x: 1.0, y:0.0, z: 0.0}, {x: 0.0, y:1.0, z: 1.0}, {x: 0.0, y:0.0, z: 1.0}, {x: 1.0, y:1.0, z: 1.0} ]; -var localLightColors = [ {x: 0.0, y:0.0, z: 0.0, w: 1.0}, {x: 0.0, y:0.0, z: 0.0, w: 1.0}, {x: 0.0, y:0.0, z: 0.0, w: 1.0}, {x: 0.0, y:0.0, z: 0.0, w: 1.0} ]; +var localLightColors = [ {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0} ]; var currentSelection = 0; var currentNumLights = 1; +var maxNumLights = 2; function keyPressEvent(event) { @@ -92,34 +93,34 @@ function keyPressEvent(event) { MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); } - else if (event.text == "+" ) { - if (currentNumLights + 1 < 4) { - + else if (event.text == "," ) { + if (currentNumLights + 1 <= maxNumLights) { + var darkGrayColor = {x:0.3, y:0.3, z:0.3}; + // default light - localLightColors[currentNumLights].x = 0.1; - localLightColors[currentNumLights].y = 0.1; - localLightColors[currentNumLights].z = 0.1; + localLightColors[currentNumLights].x = darkGrayColor.x; + localLightColors[currentNumLights].y = darkGrayColor.y; + localLightColors[currentNumLights].z = darkGrayColor.z; + MyAvatar.addLocalLight(); MyAvatar.setLocalLightColor(localLightColors[currentNumLights], currentNumLights); MyAvatar.setLocalLightDirection(localLightDirections[currentNumLights], currentNumLights); - + ++currentNumLights; } } - else if (event.text == "-" ) { + else if (event.text == "." ) { if (currentNumLights - 1 >= 0 ) { // no light contribution localLightColors[currentNumLights - 1].x = 0.0; localLightColors[currentNumLights - 1].y = 0.0; localLightColors[currentNumLights - 1].z = 0.0; - - MyAvatar.setLocalLightColor(localLightColors[currentNumLights - 1], currentNumLights - 1); - + + MyAvatar.removeLocalLight(); --currentNumLights; } - } - + } } Controller.keyPressEvent.connect(keyPressEvent); diff --git a/interface/resources/shaders/model.frag b/interface/resources/shaders/model.frag index 86bc10179c..95afaa0e5f 100644 --- a/interface/resources/shaders/model.frag +++ b/interface/resources/shaders/model.frag @@ -11,20 +11,22 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -const int MAX_LOCAL_LIGHTS = 4; // the diffuse texture uniform sampler2D diffuseMap; +// local lights +const int MAX_LOCAL_LIGHTS = 2; // 2 lights for now, will probably need more later on +uniform int numLocalLights; +uniform vec3 localLightDirections[MAX_LOCAL_LIGHTS]; +uniform vec3 localLightColors[MAX_LOCAL_LIGHTS]; + // the interpolated position varying vec4 position; // the interpolated normal varying vec4 normal; -// static local light position -varying vec4 localLightPos[MAX_LOCAL_LIGHTS]; - void main(void) { // compute the base color based on OpenGL lighting model vec4 normalizedNormal = normalize(normal); @@ -33,12 +35,12 @@ void main(void) { // the local light that is always present vec4 totalLocalLight = vec4(0.0, 0.0, 0.0, 1.0); - for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { - float localDiffuse = dot(normalizedNormal, localLightPos[i]); + for (int i = 0; i < numLocalLights; i++) { + float localDiffuse = dot(normalizedNormal, vec4(localLightDirections[i], 1.0)); float localLight = step(0.0, localDiffuse); float localLightVal = localDiffuse * localLight; - totalLocalLight += (localLightVal * gl_LightSource[i+1].diffuse); + totalLocalLight += (localLightVal * vec4( localLightColors[i], 0.0)); } vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + @@ -51,5 +53,4 @@ void main(void) { // modulate texture by base color and add specular contribution gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb, 0.0); - } diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 06ad8a3300..789c90817b 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -19,9 +19,6 @@ varying vec4 position; // the interpolated normal varying vec4 normal; -// local light position that is always present -varying vec4 localLightPos[MAX_LOCAL_LIGHTS]; - void main(void) { // transform and store the normal for interpolation @@ -41,8 +38,4 @@ void main(void) { // use standard pipeline transform gl_Position = ftransform(); - - for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { - localLightPos[i] = gl_ModelViewMatrixInverse * gl_LightSource[i+1].position; - } } diff --git a/interface/resources/shaders/model_specular_map.frag b/interface/resources/shaders/model_specular_map.frag index a07324cd1b..7038ea84f7 100644 --- a/interface/resources/shaders/model_specular_map.frag +++ b/interface/resources/shaders/model_specular_map.frag @@ -10,6 +10,10 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_LOCAL_LIGHTS = 2; + +uniform vec3 localLightDirections[MAX_LOCAL_LIGHTS]; +uniform vec3 localLightColors[MAX_LOCAL_LIGHTS]; // the diffuse texture uniform sampler2D diffuseMap; @@ -28,8 +32,19 @@ void main(void) { vec4 normalizedNormal = normalize(normal); float diffuse = dot(normalizedNormal, gl_LightSource[0].position); float facingLight = step(0.0, diffuse); + + // the local light that is always present + vec4 totalLocalLight = vec4(0.0, 0.0, 0.0, 1.0); + for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { + float localDiffuse = dot(normalizedNormal, vec4(localLightDirections[i], 1.0)); + float localLight = step(0.0, localDiffuse); + float localLightVal = localDiffuse * localLight; + + totalLocalLight += (localLightVal * vec4( localLightColors[i], 0.0)); + } + vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + totalLocalLight); // compute the specular component (sans exponent) float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))), @@ -38,4 +53,5 @@ void main(void) { // modulate texture by base color and add specular contribution gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) * gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0); + } diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 44f33da3e2..1ce1baa76f 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -26,9 +26,6 @@ varying vec4 position; // the interpolated normal varying vec4 normal; -// static local light position (inverse from eye space) -varying vec4 localLightPos[MAX_LOCAL_LIGHTS]; - void main(void) { position = vec4(0.0, 0.0, 0.0, 0.0); normal = vec4(0.0, 0.0, 0.0, 0.0); @@ -52,10 +49,4 @@ void main(void) { gl_TexCoord[1] = vec4(dot(gl_EyePlaneS[0], position), dot(gl_EyePlaneT[0], position), dot(gl_EyePlaneR[0], position), 1.0); gl_Position = gl_ProjectionMatrix * position; - - // inverse view to make the light source position static - for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { - localLightPos[i] = gl_ModelViewMatrixInverse * gl_LightSource[i+1].position; - } - } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 38dbb02a14..e6bd204505 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -61,7 +61,8 @@ Avatar::Avatar() : _moving(false), _collisionGroups(0), _initialized(false), - _shouldRenderBillboard(true) + _shouldRenderBillboard(true), + _numLocalLights(1) { // we may have been created in the network thread, but we live in the main thread moveToThread(Application::getInstance()->thread()); @@ -82,16 +83,23 @@ void Avatar::init() { _initialized = true; _shouldRenderBillboard = (getLODDistance() >= BILLBOARD_LOD_DISTANCE); initializeHair(); - + for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { - _localLightColors[i] = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + _localLightColors[i] = glm::vec3(0.0f, 0.0f, 0.0f); _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 1.0f); } + + glm::vec3 darkGrayColor(0.3f, 0.3f, 0.3f); + glm::vec3 greenColor(0.0f, 1.0f, 0.0f); + glm::vec3 directionX(1.0f, 0.0f, 0.0f); + glm::vec3 directionY(0.0f, 1.0f, 0.0f); + + // initialize local lights + _localLightColors[0] = darkGrayColor; + _localLightColors[1] = greenColor; - // initialize first light - _localLightColors[0].r = 0.2f; _localLightColors[0].g = 0.2f, _localLightColors[0].b = 0.2f; - _localLightDirections[0].x = 1.0f; _localLightDirections[0].y = 0.0f; _localLightDirections[0].z = 0.0f; - + _localLightDirections[0] = directionX; + _localLightDirections[1] = directionY; } glm::vec3 Avatar::getChestPosition() const { @@ -243,13 +251,19 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { : GLOW_FROM_AVERAGE_LOUDNESS; + // local lights directions and colors + getSkeletonModel().setNumLocalLights(_numLocalLights); + getHead()->getFaceModel().setNumLocalLights(_numLocalLights); for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { glm::vec3 normalized = glm::normalize(_localLightDirections[i]); - glm::vec4 localLight = glm::vec4(normalized, 1.0f); - // local light parameters - glLightfv(GL_LIGHT1 + i, GL_POSITION, glm::value_ptr(localLight)); - glLightfv(GL_LIGHT1 + i, GL_DIFFUSE, glm::value_ptr(_localLightColors[i])); + // body + getSkeletonModel().setLocalLightColor(_localLightColors[i], i); + getSkeletonModel().setLocalLightDirection(normalized, i); + + // head + getHead()->getFaceModel().setLocalLightColor(_localLightColors[i], i); + getHead()->getFaceModel().setLocalLightDirection(_localLightDirections[i], i); } // render body @@ -1133,8 +1147,24 @@ void Avatar::setLocalLightDirection(const glm::vec3& direction, int lightIndex) qDebug( "set light %d direction ( %f, %f, %f )\n", lightIndex, direction.x, direction.y, direction.z ); } -void Avatar::setLocalLightColor(const glm::vec4& color, int lightIndex) { +void Avatar::setLocalLightColor(const glm::vec3& color, int lightIndex) { _localLightColors[lightIndex] = color; qDebug( "set light %d color ( %f, %f, %f )\n", lightIndex, color.x, color.y, color.z ); } +void Avatar::addLocalLight() { + if (_numLocalLights + 1 <= MAX_LOCAL_LIGHTS) { + ++_numLocalLights; + } + + qDebug("ADD LOCAL LIGHT (numLocalLights = %d)\n", _numLocalLights); +} + +void Avatar::removeLocalLight() { + if (_numLocalLights - 1 >= 0) { + --_numLocalLights; + } + + qDebug("REMOVE LOCAL LIGHT (numLocalLights = %d)\n", _numLocalLights); +} + diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 059264d43a..79718c40df 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -36,8 +36,6 @@ const int HAIR_STRANDS = 150; // Number of strands of hair const int HAIR_LINKS = 10; // Number of links in a hair strand const int HAIR_MAX_CONSTRAINTS = 2; // Hair verlet is connected to at most how many others -const int MAX_LOCAL_LIGHTS = 6; - enum DriveKeys { FWD = 0, BACK, @@ -157,8 +155,10 @@ public: public slots: void updateCollisionGroups(); void setLocalLightDirection(const glm::vec3& direction, int lightIndex); - void setLocalLightColor(const glm::vec4& color, int lightIndex); - + void setLocalLightColor(const glm::vec3& color, int lightIndex); + void addLocalLight(); + void removeLocalLight(); + signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -183,8 +183,9 @@ protected: // always-present local lighting for the avatar glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; - glm::vec4 _localLightColors[MAX_LOCAL_LIGHTS]; - + glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS]; + int _numLocalLights; + // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 76d0d45efa..7a88d890ac 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -109,6 +109,7 @@ public: void resetShapePositionsToDefaultPose(); // DEBUG method void renderRagdoll(); + protected: // virtual overrrides from Ragdoll diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 6fe57ea705..053e928ca3 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1489,14 +1489,18 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances()); } - } else { + // local light + skinProgram->setUniformValue("numLocalLights", _numLocalLights); + skinProgram->setUniformArray("localLightDirections", _localLightDirections, MAX_LOCAL_LIGHTS); + skinProgram->setUniformArray("localLightColors", _localLightColors, MAX_LOCAL_LIGHTS); + } else { glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); program->bind(); if (cascadedShadows) { program->setUniform(shadowDistancesLocation, Application::getInstance()->getShadowDistances()); } } - + if (mesh.blendshapes.isEmpty()) { if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) { activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3); @@ -1623,6 +1627,20 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re } } +void Model::setLocalLightDirection(const glm::vec3& direction, int lightIndex) { + assert(lightIndex >= 0 && lightIndex < MAX_LOCAL_LIGHTS); + _localLightDirections[lightIndex] = direction; +} + +void Model::setLocalLightColor(const glm::vec3& color, int lightIndex) { + assert(lightIndex >= 0 && lightIndex < MAX_LOCAL_LIGHTS); + _localLightColors[lightIndex] = color; +} + +void Model::setNumLocalLights(int numLocalLights) { + _numLocalLights = numLocalLights; +} + void AnimationHandle::setURL(const QUrl& url) { if (_url != url) { _animation = Application::getInstance()->getAnimationCache()->getAnimation(_url = url); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 5e29b869e0..89b8843cf9 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -32,6 +32,8 @@ class Shape; typedef QSharedPointer AnimationHandlePointer; typedef QWeakPointer WeakAnimationHandlePointer; +const int MAX_LOCAL_LIGHTS = 2; + /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { Q_OBJECT @@ -143,6 +145,10 @@ public: /// Sets blended vertices computed in a separate thread. void setBlendedVertices(const QVector& vertices, const QVector& normals); + void setLocalLightDirection(const glm::vec3& direction, int lightIndex); + void setLocalLightColor(const glm::vec3& color, int lightIndex); + void setNumLocalLights(int numLocalLights); + protected: QSharedPointer _geometry; @@ -158,6 +164,10 @@ protected: bool _showTrueJointTransforms; int _rootIndex; + glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; + glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS]; + int _numLocalLights; + QVector _jointStates; class MeshState { diff --git a/interface/src/renderer/ProgramObject.cpp b/interface/src/renderer/ProgramObject.cpp index b88be69f07..bcc80960d7 100644 --- a/interface/src/renderer/ProgramObject.cpp +++ b/interface/src/renderer/ProgramObject.cpp @@ -10,6 +10,7 @@ // #include "ProgramObject.h" +#include ProgramObject::ProgramObject(QObject* parent) : QGLShaderProgram(parent) { } @@ -22,3 +23,17 @@ void ProgramObject::setUniform(const char* name, const glm::vec3& value) { setUniformValue(name, value.x, value.y, value.z); } +void ProgramObject::setUniformArray(const char* name, const glm::vec3* values, int count) { + GLfloat* floatVal = new GLfloat[count*3]; + int index = 0; + for(int i = 0; i < count; i++) { + assert(index < count*3); + const float* valPtr = glm::value_ptr(values[i]); + floatVal[index++] = valPtr[0]; + floatVal[index++] = valPtr[1]; + floatVal[index++] = valPtr[2]; + } + + setUniformValueArray(name, floatVal, count, 3); + delete[] floatVal; +} diff --git a/interface/src/renderer/ProgramObject.h b/interface/src/renderer/ProgramObject.h index 21e01ac8b3..17d0ee0d22 100644 --- a/interface/src/renderer/ProgramObject.h +++ b/interface/src/renderer/ProgramObject.h @@ -23,6 +23,7 @@ public: void setUniform(int location, const glm::vec3& value); void setUniform(const char* name, const glm::vec3& value); + void setUniformArray(const char* name, const glm::vec3* values, int count); }; #endif // hifi_ProgramObject_h diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index e76a1cee7f..2354bbf13e 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -59,6 +59,8 @@ GLubyte identityIndicesRight[] = { 1, 2, 6, 1, 6, 5 }; GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 }; GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 }; +static glm::vec3 grayColor = glm::vec3(0.3f, 0.3f, 0.3f); + VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) : NodeData(), _treeScale(treeScale), @@ -72,7 +74,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _renderer(0), _drawHaze(false), _farHazeDistance(300.0f), - _hazeColor(0.24f, 0.27f, 0.34f) + _hazeColor(grayColor) { _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; @@ -542,11 +544,8 @@ void VoxelSystem::initVoxelMemory() { GLfloat fogColor[] = {_hazeColor.x, _hazeColor.y, _hazeColor.z, 1.0f}; glFogi(GL_FOG_MODE, GL_LINEAR); glFogfv(GL_FOG_COLOR, fogColor); - glFogf(GL_FOG_DENSITY, 0.25f); - glHint(GL_FOG_HINT, GL_DONT_CARE); glFogf(GL_FOG_START, 0.0f); glFogf(GL_FOG_END, _farHazeDistance); - glEnable(GL_FOG); } } @@ -1431,6 +1430,10 @@ void VoxelSystem::render() { } } else if (!_usePrimitiveRenderer) { + if (_drawHaze) { + glEnable(GL_FOG); + } + PerformanceWarning warn(showWarnings, "render().. TRIANGLES..."); { @@ -1502,6 +1505,10 @@ void VoxelSystem::render() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } + + if (_drawHaze) { + glDisable(GL_FOG); + } } else { applyScaleAndBindProgram(texture);