From 94e81da5575aa2aa9a3b3cb48053426404f8e5b7 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Tue, 8 Jul 2014 09:44:28 -0700 Subject: [PATCH 1/6] Added local lights to avatar. Added haze to voxel. --- interface/resources/shaders/model.frag | 19 ++- interface/resources/shaders/model.vert | 9 ++ .../resources/shaders/model_normal_map.frag | 7 +- interface/resources/shaders/skin_model.vert | 11 ++ interface/src/avatar/Avatar.cpp | 35 +++++- interface/src/avatar/Avatar.h | 14 ++- interface/src/renderer/Model.cpp | 1 + interface/src/voxels/VoxelSystem.cpp | 118 +++++++++++++++++- interface/src/voxels/VoxelSystem.h | 14 ++- 9 files changed, 218 insertions(+), 10 deletions(-) diff --git a/interface/resources/shaders/model.frag b/interface/resources/shaders/model.frag index 488736abf9..86bc10179c 100644 --- a/interface/resources/shaders/model.frag +++ b/interface/resources/shaders/model.frag @@ -11,6 +11,8 @@ // 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; @@ -20,13 +22,27 @@ 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); 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, localLightPos[i]); + float localLight = step(0.0, localDiffuse); + float localLightVal = localDiffuse * localLight; + + totalLocalLight += (localLightVal * gl_LightSource[i+1].diffuse); + } + 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))), @@ -35,4 +51,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, 0.0); + } diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index da7e9640d9..06ad8a3300 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -11,12 +11,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +const int MAX_LOCAL_LIGHTS = 4; + // the interpolated position 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 @@ -36,4 +41,8 @@ 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_normal_map.frag b/interface/resources/shaders/model_normal_map.frag index 8444f2d6ea..ca0201f6ab 100644 --- a/interface/resources/shaders/model_normal_map.frag +++ b/interface/resources/shaders/model_normal_map.frag @@ -37,9 +37,14 @@ void main(void) { normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); float diffuse = dot(viewNormal, gl_LightSource[0].position); float facingLight = step(0.0, diffuse); + float localDiffuse = dot(viewNormal, gl_LightSource[1].position); + float localLight = step(0.0, localDiffuse); vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient + - gl_FrontLightProduct[0].diffuse * (diffuse * facingLight)); + gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + gl_FrontLightProduct[1].diffuse * (localDiffuse * localLight)); + + + // compute the specular component (sans exponent) float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal)); diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index d68347d33d..44f33da3e2 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -13,6 +13,7 @@ const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; +const int MAX_LOCAL_LIGHTS = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; @@ -25,6 +26,9 @@ 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); @@ -34,6 +38,7 @@ void main(void) { position += clusterMatrix * gl_Vertex * clusterWeight; normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; } + position = gl_ModelViewMatrix * position; normal = normalize(gl_ModelViewMatrix * normal); @@ -47,4 +52,10 @@ 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 9b136980f4..38dbb02a14 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -81,6 +82,16 @@ 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); + _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 1.0f); + } + + // 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; + } glm::vec3 Avatar::getChestPosition() const { @@ -219,7 +230,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { const float GLOW_DISTANCE = 20.0f; const float GLOW_MAX_LOUDNESS = 2500.0f; const float MAX_GLOW = 0.5f; - + float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar()) ? 0.0f : MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS); @@ -230,7 +241,17 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE ? 1.0f : GLOW_FROM_AVERAGE_LOUDNESS; - + + + 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])); + } + // render body if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { renderBody(renderMode, glowLevel); @@ -1107,3 +1128,13 @@ void Avatar::setShowDisplayName(bool showDisplayName) { } +void Avatar::setLocalLightDirection(const glm::vec3& direction, int lightIndex) { + _localLightDirections[lightIndex] = direction; + 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) { + _localLightColors[lightIndex] = color; + qDebug( "set light %d color ( %f, %f, %f )\n", lightIndex, color.x, color.y, color.z ); +} + diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index f20db1019d..059264d43a 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -36,6 +36,8 @@ 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, @@ -154,7 +156,9 @@ public: public slots: void updateCollisionGroups(); - + void setLocalLightDirection(const glm::vec3& direction, int lightIndex); + void setLocalLightColor(const glm::vec4& color, int lightIndex); + signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -174,9 +178,13 @@ protected: glm::vec3 _mouseRayDirection; float _stringLength; bool _moving; ///< set when position is changing - + quint32 _collisionGroups; - + + // always-present local lighting for the avatar + glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; + glm::vec4 _localLightColors[MAX_LOCAL_LIGHTS]; + // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 723297f6b4..6fe57ea705 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1488,6 +1488,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re if (cascadedShadows) { program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances()); } + } else { glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]); program->bind(); diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index ca79967109..109d561306 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include "Application.h" #include "InterfaceConfig.h" #include "Menu.h" @@ -67,7 +69,13 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _inOcclusions(false), _showCulledSharedFaces(false), _usePrimitiveRenderer(false), - _renderer(0) + _renderer(0), + _drawHaze(true), + _updateHaze(false), + _farHazeDistance(300.0f), + _hazeColor(0.24f, 0.27f, 0.34f), + _lastHazeCameraPosition(0.0f, 0.0f, 0.0f), + _lastYawAngle(0.0f) { _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; @@ -108,6 +116,9 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _lastKnownVoxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE; _lastKnownBoundaryLevelAdjust = 0; + + _voxelColors = NULL; + _voxelPositions = NULL; } void VoxelSystem::elementDeleted(OctreeElement* element) { @@ -373,6 +384,9 @@ void VoxelSystem::cleanupVoxelMemory() { delete[] _readVoxelDirtyArray; _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; _readArraysLock.unlock(); + + delete[] _voxelColors; + delete[] _voxelPositions; } } @@ -521,11 +535,17 @@ void VoxelSystem::initVoxelMemory() { _shadowDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances"); _cascadedShadowMapProgram.release(); } + } _renderer = new PrimitiveRenderer(_maxVoxels); _initialized = true; + _voxelColors = new xColor[_maxVoxels]; + memset(_voxelColors, 0, sizeof(xColor) *_maxVoxels); + + _voxelPositions = new glm::vec3[_maxVoxels]; + _writeArraysLock.unlock(); _readArraysLock.unlock(); } @@ -1114,6 +1134,7 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo node->setBufferIndex(nodeIndex); node->setVoxelSystem(this); } + // populate the array with points for the 8 vertices and RGB color for each added vertex updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor()); } @@ -1132,10 +1153,24 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { +// if (nodeIndex < 0 || nodeIndex > 1000) { +// return; +// } + if (_initialized && nodeIndex <= _maxVoxels) { _writeVoxelDirtyArray[nodeIndex] = true; - + + // cache the colors and position + _voxelColors[nodeIndex].red = color[0]; + _voxelColors[nodeIndex].green = color[1]; + _voxelColors[nodeIndex].blue = color[2]; + + // scaled voxel position + _voxelPositions[nodeIndex] = startVertex * (float)TREE_SCALE; + if (_useVoxelShader) { + // write in position, scale, and color for the voxel + if (_writeVoxelShaderData) { VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex]; writeVerticesAt->x = startVertex.x * TREE_SCALE; @@ -1157,9 +1192,85 @@ void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& } } } + + // want new color for haze + if (_drawHaze) { + _updateHaze = true; + } } } +void VoxelSystem::updateHazeColors() { + + // only update when player moves + if (_lastHazeCameraPosition != Application::getInstance()->getAvatar()->getPosition()) { + _updateHaze = true; + _lastHazeCameraPosition = Application::getInstance()->getAvatar()->getPosition(); + } + + // update when yaw angle changes + float avatarYaw = Application::getInstance()->getAvatar()->getBodyYaw(); + if (_lastYawAngle != avatarYaw) { + _updateHaze = true; + _lastYawAngle = avatarYaw; + } + + if (!_updateHaze) { + return; + } + + glm::vec3 cameraPosition = Application::getInstance()->getAvatar()->getPosition(); + float* hazeColor = glm::value_ptr(_hazeColor); + GLubyte* writeColorsAt = _writeColorsArray; + + // update voxel color + int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; + for (int i = 0; i < _voxelsInWriteArrays; i++) { + + float distanceToCamera = glm::length(_voxelPositions[i] - cameraPosition); + if(distanceToCamera > _farHazeDistance) { + distanceToCamera = _farHazeDistance; + } + + // how much haze there is at the distance + float hazeStrength = 1.0f - distanceToCamera / _farHazeDistance; + + // [0, 1] clamp + if (hazeStrength > 1.0f) { + hazeStrength = 1.0f; + } + else if (hazeStrength < 0.0f) { + hazeStrength = 0.0f; + } + + // color [0.0, 1.0] + float floatColor[] = {(float)_voxelColors[i].red / 255.0f, (float)_voxelColors[i].green / 255.0f, (float)_voxelColors[i].blue / 255.0f }; + assert(i >= 0 && i < _maxVoxels); + + // color * haze_strength + haze_color * (1.0 - haze_strength) + float oneMinusHazeStrength = 1.0f - hazeStrength; + nodeColor colorWithHaze = { + (unsigned char)((floatColor[0] * hazeStrength + hazeColor[0] * oneMinusHazeStrength) * 255.0f), + (unsigned char)((floatColor[1] * hazeStrength + hazeColor[1] * oneMinusHazeStrength) * 255.0f), + (unsigned char)((floatColor[2] * hazeStrength + hazeColor[2] * oneMinusHazeStrength) * 255.0f), + }; + + for (int j = 0; j < vertexPointsPerVoxel/3; j++ ) { + *(writeColorsAt + j*3) = colorWithHaze[0]; + *(writeColorsAt + j*3+1) = colorWithHaze[1]; + *(writeColorsAt + j*3+2) = colorWithHaze[2]; + } + + writeColorsAt += vertexPointsPerVoxel; + } + + copyWrittenDataToReadArraysFullVBOs(); + _voxelsDirty = true; + _readRenderFullVBO = true; + _updateHaze = false; + +} + glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const { const float* identityVertex = identityVertices + index * 3; return startVertex + glm::vec3(identityVertex[0], identityVertex[1], identityVertex[2]) * voxelScale; @@ -1340,6 +1451,9 @@ void VoxelSystem::render() { return; } + if (!_useVoxelShader && _drawHaze) { + updateHazeColors(); + } updateVBOs(); // if not don't... then do... diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index ae8752605a..08f44a4d92 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -273,7 +273,19 @@ private: static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask - + + // haze + xColor* _voxelColors; ///< Cached Voxel Colors + glm::vec3* _voxelPositions; ///< Cached Voxel Positions + bool _drawHaze; + bool _updateHaze; + float _farHazeDistance; + glm::vec3 _hazeColor; + glm::vec3 _lastHazeCameraPosition; + float _lastYawAngle; + + + void updateHazeColors(); }; #endif // hifi_VoxelSystem_h From 1baa187a668e240b0ca8f33ea831c407f4a05ac5 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Tue, 8 Jul 2014 10:37:42 -0700 Subject: [PATCH 2/6] add javascript example for changing avatar's local lights. --- examples/avatarLocalLight.js | 125 +++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 examples/avatarLocalLight.js diff --git a/examples/avatarLocalLight.js b/examples/avatarLocalLight.js new file mode 100644 index 0000000000..600713a037 --- /dev/null +++ b/examples/avatarLocalLight.js @@ -0,0 +1,125 @@ +// +// avatarLocalLight.js +// +// Created by Tony Peng on July 2nd, 2014 +// Copyright 2014 High Fidelity, Inc. +// +// Set the local light direction and color on the avatar +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +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 currentSelection = 0; +var currentNumLights = 1; + +function keyPressEvent(event) { + + var choice = parseInt(event.text); + + if (event.text == "1") { + currentSelection = 0; + print("selection = " + currentSelection); + } + else if (event.text == "2" ) { + currentSelection = 1; + print("selection = " + currentSelection); + } + else if (event.text == "3" ) { + currentSelection = 2; + print("selection = " + currentSelection); + } + else if (event.text == "4" ) { + currentSelection = 3; + print("selection = " + currentSelection); + } + else if (event.text == "5" ) { + localLightColors[currentSelection].x += 0.01; + if ( localLightColors[currentSelection].x > 1.0) { + localLightColors[currentSelection].x = 0.0; + } + + MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + } + else if (event.text == "6" ) { + localLightColors[currentSelection].y += 0.01; + if ( localLightColors[currentSelection].y > 1.0) { + localLightColors[currentSelection].y = 0.0; + } + + MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + } + else if (event.text == "7" ) { + localLightColors[currentSelection].z += 0.01; + if ( localLightColors[currentSelection].z > 1.0) { + localLightColors[currentSelection].z = 0.0; + } + + MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection); + } + else if (event.text == "8" ) { + localLightDirections[currentSelection].x += 0.01; + if (localLightDirections[currentSelection].x > 1.0) { + localLightDirections[currentSelection].x = -1.0; + } + + MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + } + else if (event.text == "9" ) { + localLightDirections[currentSelection].x -= 0.01; + if (localLightDirections[currentSelection].x < -1.0) { + localLightDirections[currentSelection].x = 1.0; + } + + MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + } + else if (event.text == "[" ) { + localLightDirections[currentSelection].y += 0.01; + if (localLightDirections[currentSelection].y > 1.0) { + localLightDirections[currentSelection].y = -1.0; + } + + MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + } + else if (event.text == "]" ) { + localLightDirections[currentSelection].y -= 0.01; + if (localLightDirections[currentSelection].y < -1.0) { + localLightDirections[currentSelection].y = 1.0; + } + + MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection); + } + else if (event.text == "+" ) { + if (currentNumLights + 1 < 4) { + + // default light + localLightColors[currentNumLights].x = 0.1; + localLightColors[currentNumLights].y = 0.1; + localLightColors[currentNumLights].z = 0.1; + + MyAvatar.setLocalLightColor(localLightColors[currentNumLights], currentNumLights); + MyAvatar.setLocalLightDirection(localLightDirections[currentNumLights], currentNumLights); + + ++currentNumLights; + } + } + 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); + + --currentNumLights; + } + } + +} + +Controller.keyPressEvent.connect(keyPressEvent); From 4e04cecd8c9b3b7291aa63d0b41d49b68d7e69f5 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Tue, 8 Jul 2014 12:28:44 -0700 Subject: [PATCH 3/6] Use glFog for haze (better performance). --- interface/src/voxels/VoxelSystem.cpp | 122 ++++----------------------- interface/src/voxels/VoxelSystem.h | 8 -- 2 files changed, 16 insertions(+), 114 deletions(-) diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 109d561306..ee8b306ef3 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -70,12 +70,9 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _showCulledSharedFaces(false), _usePrimitiveRenderer(false), _renderer(0), - _drawHaze(true), - _updateHaze(false), + _drawHaze(false), _farHazeDistance(300.0f), - _hazeColor(0.24f, 0.27f, 0.34f), - _lastHazeCameraPosition(0.0f, 0.0f, 0.0f), - _lastYawAngle(0.0f) + _hazeColor(0.24f, 0.27f, 0.34f) { _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0; @@ -116,9 +113,6 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree) _lastKnownVoxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE; _lastKnownBoundaryLevelAdjust = 0; - - _voxelColors = NULL; - _voxelPositions = NULL; } void VoxelSystem::elementDeleted(OctreeElement* element) { @@ -384,9 +378,7 @@ void VoxelSystem::cleanupVoxelMemory() { delete[] _readVoxelDirtyArray; _writeVoxelDirtyArray = _readVoxelDirtyArray = NULL; _readArraysLock.unlock(); - - delete[] _voxelColors; - delete[] _voxelPositions; + } } @@ -468,6 +460,7 @@ void VoxelSystem::initVoxelMemory() { _readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels]; _memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels); + } else { // Global Normals mode uses a technique of not including normals on any voxel vertices, and instead @@ -540,14 +533,21 @@ void VoxelSystem::initVoxelMemory() { _renderer = new PrimitiveRenderer(_maxVoxels); _initialized = true; - - _voxelColors = new xColor[_maxVoxels]; - memset(_voxelColors, 0, sizeof(xColor) *_maxVoxels); - - _voxelPositions = new glm::vec3[_maxVoxels]; _writeArraysLock.unlock(); _readArraysLock.unlock(); + + // fog for haze + if(_drawHaze) { + 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, 20.0f); + glFogf(GL_FOG_END, _farHazeDistance); + glEnable(GL_FOG); + } } int VoxelSystem::parseData(const QByteArray& packet) { @@ -1152,22 +1152,10 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex, float voxelScale, const nodeColor& color) { - -// if (nodeIndex < 0 || nodeIndex > 1000) { -// return; -// } if (_initialized && nodeIndex <= _maxVoxels) { _writeVoxelDirtyArray[nodeIndex] = true; - // cache the colors and position - _voxelColors[nodeIndex].red = color[0]; - _voxelColors[nodeIndex].green = color[1]; - _voxelColors[nodeIndex].blue = color[2]; - - // scaled voxel position - _voxelPositions[nodeIndex] = startVertex * (float)TREE_SCALE; - if (_useVoxelShader) { // write in position, scale, and color for the voxel @@ -1193,84 +1181,9 @@ void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& } } - // want new color for haze - if (_drawHaze) { - _updateHaze = true; - } } } -void VoxelSystem::updateHazeColors() { - - // only update when player moves - if (_lastHazeCameraPosition != Application::getInstance()->getAvatar()->getPosition()) { - _updateHaze = true; - _lastHazeCameraPosition = Application::getInstance()->getAvatar()->getPosition(); - } - - // update when yaw angle changes - float avatarYaw = Application::getInstance()->getAvatar()->getBodyYaw(); - if (_lastYawAngle != avatarYaw) { - _updateHaze = true; - _lastYawAngle = avatarYaw; - } - - if (!_updateHaze) { - return; - } - - glm::vec3 cameraPosition = Application::getInstance()->getAvatar()->getPosition(); - float* hazeColor = glm::value_ptr(_hazeColor); - GLubyte* writeColorsAt = _writeColorsArray; - - // update voxel color - int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - for (int i = 0; i < _voxelsInWriteArrays; i++) { - - float distanceToCamera = glm::length(_voxelPositions[i] - cameraPosition); - if(distanceToCamera > _farHazeDistance) { - distanceToCamera = _farHazeDistance; - } - - // how much haze there is at the distance - float hazeStrength = 1.0f - distanceToCamera / _farHazeDistance; - - // [0, 1] clamp - if (hazeStrength > 1.0f) { - hazeStrength = 1.0f; - } - else if (hazeStrength < 0.0f) { - hazeStrength = 0.0f; - } - - // color [0.0, 1.0] - float floatColor[] = {(float)_voxelColors[i].red / 255.0f, (float)_voxelColors[i].green / 255.0f, (float)_voxelColors[i].blue / 255.0f }; - assert(i >= 0 && i < _maxVoxels); - - // color * haze_strength + haze_color * (1.0 - haze_strength) - float oneMinusHazeStrength = 1.0f - hazeStrength; - nodeColor colorWithHaze = { - (unsigned char)((floatColor[0] * hazeStrength + hazeColor[0] * oneMinusHazeStrength) * 255.0f), - (unsigned char)((floatColor[1] * hazeStrength + hazeColor[1] * oneMinusHazeStrength) * 255.0f), - (unsigned char)((floatColor[2] * hazeStrength + hazeColor[2] * oneMinusHazeStrength) * 255.0f), - }; - - for (int j = 0; j < vertexPointsPerVoxel/3; j++ ) { - *(writeColorsAt + j*3) = colorWithHaze[0]; - *(writeColorsAt + j*3+1) = colorWithHaze[1]; - *(writeColorsAt + j*3+2) = colorWithHaze[2]; - } - - writeColorsAt += vertexPointsPerVoxel; - } - - copyWrittenDataToReadArraysFullVBOs(); - _voxelsDirty = true; - _readRenderFullVBO = true; - _updateHaze = false; - -} - glm::vec3 VoxelSystem::computeVoxelVertex(const glm::vec3& startVertex, float voxelScale, int index) const { const float* identityVertex = identityVertices + index * 3; return startVertex + glm::vec3(identityVertex[0], identityVertex[1], identityVertex[2]) * voxelScale; @@ -1451,9 +1364,6 @@ void VoxelSystem::render() { return; } - if (!_useVoxelShader && _drawHaze) { - updateHazeColors(); - } updateVBOs(); // if not don't... then do... diff --git a/interface/src/voxels/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h index 08f44a4d92..9f61e0579c 100644 --- a/interface/src/voxels/VoxelSystem.h +++ b/interface/src/voxels/VoxelSystem.h @@ -275,17 +275,9 @@ private: static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask // haze - xColor* _voxelColors; ///< Cached Voxel Colors - glm::vec3* _voxelPositions; ///< Cached Voxel Positions bool _drawHaze; - bool _updateHaze; float _farHazeDistance; glm::vec3 _hazeColor; - glm::vec3 _lastHazeCameraPosition; - float _lastYawAngle; - - - void updateHazeColors(); }; #endif // hifi_VoxelSystem_h From e212f9f42eb56e7faf4722241f5eef8cd4090a94 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Tue, 8 Jul 2014 12:48:01 -0700 Subject: [PATCH 4/6] Change fog start to use default value. --- interface/src/voxels/VoxelSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index ee8b306ef3..e76a1cee7f 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -544,7 +544,7 @@ void VoxelSystem::initVoxelMemory() { glFogfv(GL_FOG_COLOR, fogColor); glFogf(GL_FOG_DENSITY, 0.25f); glHint(GL_FOG_HINT, GL_DONT_CARE); - glFogf(GL_FOG_START, 20.0f); + glFogf(GL_FOG_START, 0.0f); glFogf(GL_FOG_END, _farHazeDistance); glEnable(GL_FOG); } From 56eadcb0dcae9d48e5054a97c76cb5ab2c194047 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Wed, 9 Jul 2014 12:05:34 -0700 Subject: [PATCH 5/6] 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); From ef4b95c6e0b1c50da01fce0bce9312e4ce5b8077 Mon Sep 17 00:00:00 2001 From: TonyPeng Date: Wed, 9 Jul 2014 13:27:42 -0700 Subject: [PATCH 6/6] Merged from master. Get rid of redundant GL fog states. Moved local light parameters to shader uniform arrays. --- examples/avatarLocalLight.js | 8 ++++---- interface/resources/shaders/model.frag | 2 +- interface/resources/shaders/model.vert | 1 + interface/resources/shaders/model_specular_map.frag | 3 ++- interface/resources/shaders/skin_model.vert | 1 - interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/Avatar.h | 2 +- interface/src/renderer/Model.cpp | 2 +- interface/src/renderer/Model.h | 4 ++-- interface/src/renderer/ProgramObject.cpp | 2 +- interface/src/renderer/ProgramObject.h | 2 +- interface/src/voxels/VoxelSystem.cpp | 2 +- 12 files changed, 16 insertions(+), 15 deletions(-) diff --git a/examples/avatarLocalLight.js b/examples/avatarLocalLight.js index 69b491d430..57f9d84ffe 100644 --- a/examples/avatarLocalLight.js +++ b/examples/avatarLocalLight.js @@ -23,19 +23,19 @@ function keyPressEvent(event) { if (event.text == "1") { currentSelection = 0; - print("selection = " + currentSelection); + print("light election = " + currentSelection); } else if (event.text == "2" ) { currentSelection = 1; - print("selection = " + currentSelection); + print("light selection = " + currentSelection); } else if (event.text == "3" ) { currentSelection = 2; - print("selection = " + currentSelection); + print("light selection = " + currentSelection); } else if (event.text == "4" ) { currentSelection = 3; - print("selection = " + currentSelection); + print("light selection = " + currentSelection); } else if (event.text == "5" ) { localLightColors[currentSelection].x += 0.01; diff --git a/interface/resources/shaders/model.frag b/interface/resources/shaders/model.frag index 95afaa0e5f..468a892686 100644 --- a/interface/resources/shaders/model.frag +++ b/interface/resources/shaders/model.frag @@ -16,7 +16,7 @@ uniform sampler2D diffuseMap; // local lights -const int MAX_LOCAL_LIGHTS = 2; // 2 lights for now, will probably need more later on +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]; diff --git a/interface/resources/shaders/model.vert b/interface/resources/shaders/model.vert index 789c90817b..13eee2fa3d 100644 --- a/interface/resources/shaders/model.vert +++ b/interface/resources/shaders/model.vert @@ -39,3 +39,4 @@ void main(void) { // use standard pipeline transform gl_Position = ftransform(); } + diff --git a/interface/resources/shaders/model_specular_map.frag b/interface/resources/shaders/model_specular_map.frag index 7038ea84f7..329da65e9e 100644 --- a/interface/resources/shaders/model_specular_map.frag +++ b/interface/resources/shaders/model_specular_map.frag @@ -12,6 +12,7 @@ // const int MAX_LOCAL_LIGHTS = 2; +uniform int numLocalLights; uniform vec3 localLightDirections[MAX_LOCAL_LIGHTS]; uniform vec3 localLightColors[MAX_LOCAL_LIGHTS]; @@ -35,7 +36,7 @@ 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++) { + 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; diff --git a/interface/resources/shaders/skin_model.vert b/interface/resources/shaders/skin_model.vert index 1ce1baa76f..943daf9061 100644 --- a/interface/resources/shaders/skin_model.vert +++ b/interface/resources/shaders/skin_model.vert @@ -13,7 +13,6 @@ const int MAX_CLUSTERS = 128; const int INDICES_PER_VERTEX = 4; -const int MAX_LOCAL_LIGHTS = 4; uniform mat4 clusterMatrices[MAX_CLUSTERS]; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index e6bd204505..83105c9022 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -86,7 +86,7 @@ void Avatar::init() { for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) { _localLightColors[i] = glm::vec3(0.0f, 0.0f, 0.0f); - _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 1.0f); + _localLightDirections[i] = glm::vec3(0.0f, 0.0f, 0.0f); } glm::vec3 darkGrayColor(0.3f, 0.3f, 0.3f); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 79718c40df..31161e657b 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -184,7 +184,7 @@ protected: // always-present local lighting for the avatar glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS]; - int _numLocalLights; + int _numLocalLights; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 053e928ca3..8b8557709c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1489,7 +1489,7 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances()); } - // local light + // local light uniforms skinProgram->setUniformValue("numLocalLights", _numLocalLights); skinProgram->setUniformArray("localLightDirections", _localLightDirections, MAX_LOCAL_LIGHTS); skinProgram->setUniformArray("localLightColors", _localLightColors, MAX_LOCAL_LIGHTS); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 89b8843cf9..9e2e0d8348 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -166,8 +166,8 @@ protected: glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS]; glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS]; - int _numLocalLights; - + int _numLocalLights; + QVector _jointStates; class MeshState { diff --git a/interface/src/renderer/ProgramObject.cpp b/interface/src/renderer/ProgramObject.cpp index bcc80960d7..16b3461ad0 100644 --- a/interface/src/renderer/ProgramObject.cpp +++ b/interface/src/renderer/ProgramObject.cpp @@ -26,7 +26,7 @@ void ProgramObject::setUniform(const char* name, const glm::vec3& value) { 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++) { + for (int i = 0; i < count; i++) { assert(index < count*3); const float* valPtr = glm::value_ptr(values[i]); floatVal[index++] = valPtr[0]; diff --git a/interface/src/renderer/ProgramObject.h b/interface/src/renderer/ProgramObject.h index 17d0ee0d22..8e66ce9bc9 100644 --- a/interface/src/renderer/ProgramObject.h +++ b/interface/src/renderer/ProgramObject.h @@ -23,7 +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); + 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 2354bbf13e..6c19cfd4c2 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -540,7 +540,7 @@ void VoxelSystem::initVoxelMemory() { _readArraysLock.unlock(); // fog for haze - if(_drawHaze) { + if (_drawHaze) { GLfloat fogColor[] = {_hazeColor.x, _hazeColor.y, _hazeColor.z, 1.0f}; glFogi(GL_FOG_MODE, GL_LINEAR); glFogfv(GL_FOG_COLOR, fogColor);