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.

This commit is contained in:
TonyPeng 2014-07-09 12:05:34 -07:00
parent e212f9f42e
commit 56eadcb0dc
13 changed files with 148 additions and 63 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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; }

View file

@ -109,6 +109,7 @@ public:
void resetShapePositionsToDefaultPose(); // DEBUG method
void renderRagdoll();
protected:
// virtual overrrides from Ragdoll

View file

@ -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);

View file

@ -32,6 +32,8 @@ class Shape;
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
typedef QWeakPointer<AnimationHandle> 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<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
void setLocalLightDirection(const glm::vec3& direction, int lightIndex);
void setLocalLightColor(const glm::vec3& color, int lightIndex);
void setNumLocalLights(int numLocalLights);
protected:
QSharedPointer<NetworkGeometry> _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<JointState> _jointStates;
class MeshState {

View file

@ -10,6 +10,7 @@
//
#include "ProgramObject.h"
#include <glm/gtc/type_ptr.hpp>
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;
}

View file

@ -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

View file

@ -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);