Merge branch 'temp0' of https://github.com/samcake/hifi into temp0

This commit is contained in:
Sam Gateau 2015-02-10 14:36:38 -08:00
commit 01291b61a4
24 changed files with 952 additions and 400 deletions

View file

@ -2603,6 +2603,9 @@ const GLfloat WORLD_AMBIENT_COLOR[] = { 0.525f, 0.525f, 0.6f };
const GLfloat WORLD_DIFFUSE_COLOR[] = { 0.6f, 0.525f, 0.525f };
const GLfloat WORLD_SPECULAR_COLOR[] = { 0.94f, 0.94f, 0.737f, 1.0f };
const glm::vec3 GLOBAL_LIGHT_COLOR = { 0.6f, 0.525f, 0.525f };
const float GLOBAL_LIGHT_INTENSITY = 1.0f;
void Application::setupWorldLight() {
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
@ -2617,6 +2620,7 @@ void Application::setupWorldLight() {
glLightfv(GL_LIGHT0, GL_SPECULAR, WORLD_SPECULAR_COLOR);
glMaterialfv(GL_FRONT, GL_SPECULAR, WORLD_SPECULAR_COLOR);
glMateriali(GL_FRONT, GL_SHININESS, 96);
}
bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) {
@ -2823,7 +2827,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
{
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY);
PROFILE_RANGE("DeferredLighting");
PerformanceTimer perfTimer("lighting");
DependencyManager::get<DeferredLightingEffect>()->render();

View file

@ -1126,7 +1126,7 @@ FBXTexture getTexture(const QString& textureID,
texture.transform.setTranslation(p.translation);
texture.transform.setRotation(glm::quat(glm::radians(p.rotation)));
texture.transform.setScale(p.scaling);
if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) {
if ((p.UVSet != "map1") && (p.UVSet != "UVSet0")) {
texture.texcoordSet = 1;
}
texture.texcoordSetName = p.UVSet;
@ -1555,6 +1555,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping,
if (property.name == propertyName) {
QString v = property.properties.at(0).toString();
if (property.properties.at(0) == "UVSet") {
std::string uvName = property.properties.at(index).toString().toStdString();
tex.assign(tex.UVSet, property.properties.at(index).toString());
} else if (property.properties.at(0) == "CurrentTextureBlendMode") {
tex.assign<uint8_t>(tex.currentTextureBlendMode, property.properties.at(index).value<int>());

View file

@ -85,8 +85,11 @@ bool Texture::Storage::allocateMip(uint16 level) {
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
// Ok we should be able to do that...
allocateMip(level);
_mips[level]->_format = format;
Size allocated = _mips[level]->_sysmem.setData(size, bytes);
auto mip = _mips[level];
mip->_format = format;
Size allocated = mip->_sysmem.setData(size, bytes);
mip->_isGPULoaded = false;
return allocated == size;
}

View file

@ -23,6 +23,7 @@ typedef gpu::BufferView::Index Index;
typedef gpu::BufferView BufferView;
typedef AABox Box;
typedef std::vector< Box > Boxes;
typedef glm::vec3 Vec3;
class Mesh {
public:
@ -35,7 +36,7 @@ public:
typedef gpu::Stream::Format VertexFormat;
typedef std::map< Slot, BufferView > BufferViewMap;
typedef glm::vec3 Vec3;
typedef model::Vec3 Vec3;
Mesh();
Mesh(const Mesh& mesh);

View file

@ -0,0 +1,97 @@
//
// Light.cpp
// libraries/model/src/model
//
// Created by Sam Gateau on 1/26/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Light.h"
using namespace model;
Light::Light() :
_flags(0),
_schemaBuffer(),
_transform() {
// only if created from nothing shall we create the Buffer to store the properties
Schema schema;
_schemaBuffer = gpu::BufferView(new gpu::Buffer(sizeof(Schema), (const gpu::Buffer::Byte*) &schema));
}
Light::Light(const Light& light) :
_flags(light._flags),
_schemaBuffer(light._schemaBuffer),
_transform(light._transform) {
}
Light& Light::operator= (const Light& light) {
_flags = (light._flags);
_schemaBuffer = (light._schemaBuffer);
_transform = (light._transform);
return (*this);
}
Light::~Light() {
}
void Light::setPosition(const Vec3& position) {
_transform.setTranslation(position);
editSchema()._position = Vec4(position, 1.f);
}
void Light::setOrientation(const glm::quat& orientation) {
_transform.setRotation(orientation);
}
void Light::setDirection(const Vec3& direction) {
editSchema()._direction = glm::normalize(direction);
}
const Vec3& Light::getDirection() const {
return getSchema()._direction;
}
void Light::setColor(const Color& color) {
editSchema()._color = color;
}
void Light::setIntensity(float intensity) {
editSchema()._intensity = intensity;
}
void Light::setMaximumRadius(float radius) {
if (radius <= 0.f) {
radius = 1.0f;
}
float CutOffIntensityRatio = 0.05f;
float surfaceRadius = radius / (sqrt(1.0f / CutOffIntensityRatio) - 1.f);
editSchema()._attenuation = Vec4(surfaceRadius, 1.0f/surfaceRadius, CutOffIntensityRatio, radius);
}
void Light::setSpotAngle(float angle) {
if (angle <= 0.f) {
angle = 0.0f;
}
float cosAngle = cos(angle);
editSchema()._spot.x = cos(angle);
editSchema()._spot.y = sin(angle);
editSchema()._spot.z = angle;
}
void Light::setSpotExponent(float exponent) {
if (exponent <= 0.f) {
exponent = 1.0f;
}
editSchema()._spot.w = exponent;
}
void Light::setShowContour(float show) {
if (show <= 0.f) {
show = 0.0f;
}
editSchema()._control.w = show;
}

294
libraries/model/src/model/Light.h Executable file
View file

@ -0,0 +1,294 @@
//
// Light.h
// libraries/model/src/model
//
// Created by Sam Gateau on 12/10/2014.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_model_Light_h
#define hifi_model_Light_h
#include <bitset>
#include <map>
#include <glm/glm.hpp>
#include "Transform.h"
#include "gpu/Resource.h"
#include "gpu/Texture.h"
namespace model {
typedef gpu::BufferView UniformBufferView;
typedef gpu::TextureView TextureView;
typedef glm::vec3 Vec3;
typedef glm::vec4 Vec4;
typedef glm::quat Quat;
class SphericalHarmonics {
public:
glm::vec3 L00 ; float spare0;
glm::vec3 L1m1 ; float spare1;
glm::vec3 L10 ; float spare2;
glm::vec3 L11 ; float spare3;
glm::vec3 L2m2 ; float spare4;
glm::vec3 L2m1 ; float spare5;
glm::vec3 L20 ; float spare6;
glm::vec3 L21 ; float spare7;
glm::vec3 L22 ; float spare8;
static const int NUM_COEFFICIENTS = 9;
enum Preset {
OLD_TOWN_SQUARE = 0,
GRACE_CATHEDRAL,
EUCALYPTUS_GROVE,
ST_PETERS_BASILICA,
UFFIZI_GALLERY,
GALILEOS_TOMB,
VINE_STREET_KITCHEN,
BREEZEWAY,
CAMPUS_SUNSET,
FUNSTON_BEACH_SUNSET,
NUM_PRESET,
};
void assignPreset(int p) {
switch (p) {
case OLD_TOWN_SQUARE: {
L00 = glm::vec3( 0.871297f, 0.875222f, 0.864470f);
L1m1 = glm::vec3( 0.175058f, 0.245335f, 0.312891f);
L10 = glm::vec3( 0.034675f, 0.036107f, 0.037362f);
L11 = glm::vec3(-0.004629f,-0.029448f,-0.048028f);
L2m2 = glm::vec3(-0.120535f,-0.121160f,-0.117507f);
L2m1 = glm::vec3( 0.003242f, 0.003624f, 0.007511f);
L20 = glm::vec3(-0.028667f,-0.024926f,-0.020998f);
L21 = glm::vec3(-0.077539f,-0.086325f,-0.091591f);
L22 = glm::vec3(-0.161784f,-0.191783f,-0.219152f);
}
break;
case GRACE_CATHEDRAL: {
L00 = glm::vec3( 0.79f, 0.44f, 0.54f);
L1m1 = glm::vec3( 0.39f, 0.35f, 0.60f);
L10 = glm::vec3(-0.34f, -0.18f, -0.27f);
L11 = glm::vec3(-0.29f, -0.06f, 0.01f);
L2m2 = glm::vec3(-0.11f, -0.05f, -0.12f);
L2m1 = glm::vec3(-0.26f, -0.22f, -0.47f);
L20 = glm::vec3(-0.16f, -0.09f, -0.15f);
L21 = glm::vec3( 0.56f, 0.21f, 0.14f);
L22 = glm::vec3( 0.21f, -0.05f, -0.30f);
}
break;
case EUCALYPTUS_GROVE: {
L00 = glm::vec3( 0.38f, 0.43f, 0.45f);
L1m1 = glm::vec3( 0.29f, 0.36f, 0.41f);
L10 = glm::vec3( 0.04f, 0.03f, 0.01f);
L11 = glm::vec3(-0.10f, -0.10f, -0.09f);
L2m2 = glm::vec3(-0.06f, -0.06f, -0.04f);
L2m1 = glm::vec3( 0.01f, -0.01f, -0.05f);
L20 = glm::vec3(-0.09f, -0.13f, -0.15f);
L21 = glm::vec3(-0.06f, -0.05f, -0.04f);
L22 = glm::vec3( 0.02f, 0.00f, -0.05f);
}
break;
case ST_PETERS_BASILICA: {
L00 = glm::vec3( 0.36f, 0.26f, 0.23f);
L1m1 = glm::vec3( 0.18f, 0.14f, 0.13f);
L10 = glm::vec3(-0.02f, -0.01f, 0.00f);
L11 = glm::vec3( 0.03f, 0.02f, -0.00f);
L2m2 = glm::vec3( 0.02f, 0.01f, -0.00f);
L2m1 = glm::vec3(-0.05f, -0.03f, -0.01f);
L20 = glm::vec3(-0.09f, -0.08f, -0.07f);
L21 = glm::vec3( 0.01f, 0.00f, 0.00f);
L22 = glm::vec3(-0.08f, -0.03f, -0.00f);
}
break;
case UFFIZI_GALLERY: {
L00 = glm::vec3( 0.32f, 0.31f, 0.35f);
L1m1 = glm::vec3( 0.37f, 0.37f, 0.43f);
L10 = glm::vec3( 0.00f, 0.00f, 0.00f);
L11 = glm::vec3(-0.01f, -0.01f, -0.01f);
L2m2 = glm::vec3(-0.02f, -0.02f, -0.03f);
L2m1 = glm::vec3(-0.01f, -0.01f, -0.01f);
L20 = glm::vec3(-0.28f, -0.28f, -0.32f);
L21 = glm::vec3( 0.00f, 0.00f, 0.00f);
L22 = glm::vec3(-0.24f, -0.24f, -0.28f);
}
break;
case GALILEOS_TOMB: {
L00 = glm::vec3( 1.04f, 0.76f, 0.71f);
L1m1 = glm::vec3( 0.44f, 0.34f, 0.34f);
L10 = glm::vec3(-0.22f, -0.18f, -0.17f);
L11 = glm::vec3( 0.71f, 0.54f, 0.56f);
L2m2 = glm::vec3( 0.64f, 0.50f, 0.52f);
L2m1 = glm::vec3(-0.12f, -0.09f, -0.08f);
L20 = glm::vec3(-0.37f, -0.28f, -0.32f);
L21 = glm::vec3(-0.17f, -0.13f, -0.13f);
L22 = glm::vec3( 0.55f, 0.42f, 0.42f);
}
break;
case VINE_STREET_KITCHEN: {
L00 = glm::vec3( 0.64f, 0.67f, 0.73f);
L1m1 = glm::vec3( 0.28f, 0.32f, 0.33f);
L10 = glm::vec3( 0.42f, 0.60f, 0.77f);
L11 = glm::vec3(-0.05f, -0.04f, -0.02f);
L2m2 = glm::vec3(-0.10f, -0.08f, -0.05f);
L2m1 = glm::vec3( 0.25f, 0.39f, 0.53f);
L20 = glm::vec3( 0.38f, 0.54f, 0.71f);
L21 = glm::vec3( 0.06f, 0.01f, -0.02f);
L22 = glm::vec3(-0.03f, -0.02f, -0.03f);
}
break;
case BREEZEWAY: {
L00 = glm::vec3( 0.32f, 0.36f, 0.38f);
L1m1 = glm::vec3( 0.37f, 0.41f, 0.45f);
L10 = glm::vec3(-0.01f, -0.01f, -0.01f);
L11 = glm::vec3(-0.10f, -0.12f, -0.12f);
L2m2 = glm::vec3(-0.13f, -0.15f, -0.17f);
L2m1 = glm::vec3(-0.01f, -0.02f, 0.02f);
L20 = glm::vec3(-0.07f, -0.08f, -0.09f);
L21 = glm::vec3( 0.02f, 0.03f, 0.03f);
L22 = glm::vec3(-0.29f, -0.32f, -0.36f);
}
break;
case CAMPUS_SUNSET: {
L00 = glm::vec3( 0.79f, 0.94f, 0.98f);
L1m1 = glm::vec3( 0.44f, 0.56f, 0.70f);
L10 = glm::vec3(-0.10f, -0.18f, -0.27f);
L11 = glm::vec3( 0.45f, 0.38f, 0.20f);
L2m2 = glm::vec3( 0.18f, 0.14f, 0.05f);
L2m1 = glm::vec3(-0.14f, -0.22f, -0.31f);
L20 = glm::vec3(-0.39f, -0.40f, -0.36f);
L21 = glm::vec3( 0.09f, 0.07f, 0.04f);
L22 = glm::vec3( 0.67f, 0.67f, 0.52f);
}
break;
case FUNSTON_BEACH_SUNSET: {
L00 = glm::vec3( 0.68f, 0.69f, 0.70f);
L1m1 = glm::vec3( 0.32f, 0.37f, 0.44f);
L10 = glm::vec3(-0.17f, -0.17f, -0.17f);
L11 = glm::vec3(-0.45f, -0.42f, -0.34f);
L2m2 = glm::vec3(-0.17f, -0.17f, -0.15f);
L2m1 = glm::vec3(-0.08f, -0.09f, -0.10f);
L20 = glm::vec3(-0.03f, -0.02f, -0.01f);
L21 = glm::vec3( 0.16f, 0.14f, 0.10f);
L22 = glm::vec3( 0.37f, 0.31f, 0.20f);
}
break;
}
}
};
class Light {
public:
enum Type {
SUN = 0,
POINT,
SPOT,
NUM_TYPES,
};
typedef Vec3 Color;
enum FlagBit {
COLOR_BIT = 0,
INTENSITY_BIT,
RANGE_BIT,
SPOT_BIT,
TRANSFORM_BIT,
NUM_FLAGS,
};
typedef std::bitset<NUM_FLAGS> Flags;
Light();
Light(const Light& light);
Light& operator= (const Light& light);
virtual ~Light();
void setType(Type type) { editSchema()._control.x = float(type); }
Type getType() const { return Type((int) getSchema()._control.x); }
void setPosition(const Vec3& position);
const Vec3& getPosition() const { return _transform.getTranslation(); }
void setDirection(const Vec3& direction);
const Vec3& getDirection() const;
void setOrientation(const Quat& orientation);
const glm::quat& getOrientation() const { return _transform.getRotation(); }
const Color& getColor() const { return getSchema()._color; }
void setColor(const Color& color);
float getIntensity() const { return getSchema()._intensity; }
void setIntensity(float intensity);
bool isRanged() const { return (getType() == POINT) || (getType() == SPOT ); }
void setMaximumRadius(float radius);
float getMaximumRadius() const { return getSchema()._attenuation.w; }
// Spot properties
bool isSpot() const { return getType() == SPOT; }
void setSpotAngle(float angle);
float getSpotAngle() const { return getSchema()._spot.z; }
void setSpotExponent(float exponent);
float getSpotExponent() const { return getSchema()._spot.w; }
// For editing purpose, show the light volume contour.
// Set to non 0 to show it, the value is used as the intensity of the contour color
void setShowContour(float show);
float getShowContour() const { return getSchema()._control.w; }
// Spherical Harmonics storing the Ambien lighting approximation used for the Sun typed light
void setAmbientSphere(const SphericalHarmonics& sphere) { _ambientSphere = sphere; }
const SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; }
void setAmbientSpherePreset(SphericalHarmonics::Preset preset) { _ambientSphere.assignPreset(preset); }
// Schema to access the attribute values of the light
class Schema {
public:
Vec4 _position;
Vec3 _direction;
float _spare0;
Color _color;
float _intensity;
Vec4 _attenuation;
Vec4 _spot;
Vec4 _shadow;
Vec4 _control;
Schema() :
_position(0.0f, 0.0f, 0.0f, 1.0f),
_direction(0.0f, 0.0f, -1.0f),
_spare0(0.f),
_color(1.0f),
_intensity(1.0f),
_attenuation(1.0f, 1.0f, 1.0f, 1.0f),
_spot(0.0f, 0.0f, 0.0f, 3.0f),
_control(0.0f)
{}
};
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
protected:
Flags _flags;
UniformBufferView _schemaBuffer;
Transform _transform;
SphericalHarmonics _ambientSphere;
const Schema& getSchema() const { return _schemaBuffer.get<Schema>(); }
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }
};
typedef QSharedPointer< Light > LightPointer;
};
#endif

View file

@ -100,7 +100,6 @@ public:
void setTextureView(MapChannel channel, const TextureView& texture);
const TextureMap& getTextureMap() const { return _textureMap; }
const Schema* getSchema() const { return &_schemaBuffer.get<Schema>(); }
protected:
Flags _flags;

View file

@ -0,0 +1,117 @@
<!
// DeferredGlobalLight.slh
// libraries/render-utils/src
//
// Created by Sam Gateau on 2/5/15.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not DEFERRED_GLOBAL_LIGHT_SLH@>
<@def DEFERRED_GLOBAL_LIGHT_SLH@>
<@include DeferredLighting.slh@>
struct SphericalHarmonics {
vec4 L00;
vec4 L1m1;
vec4 L10;
vec4 L11;
vec4 L2m2;
vec4 L2m1;
vec4 L20;
vec4 L21;
vec4 L22;
};
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
const float C1 = 0.429043;
const float C2 = 0.511664;
const float C3 = 0.743125;
const float C4 = 0.886227;
const float C5 = 0.247708;
vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) +
C3 * sh.L20 * direction.z * direction.z +
C4 * sh.L00 - C5 * sh.L20 +
2.0 * C1 * ( sh.L2m2 * direction.x * direction.y +
sh.L21 * direction.x * direction.z +
sh.L2m1 * direction.y * direction.z ) +
2.0 * C2 * ( sh.L11 * direction.x +
sh.L1m1 * direction.y +
sh.L10 * direction.z ) ;
return value;
}
// Need one SH
uniform SphericalHarmonics ambientSphere;
// Everything about light
<@include Light.slh@>
// The view Matrix
uniform mat4 invViewMat;
vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 color = diffuse.rgb * getLightColor(light) * 0.5;
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return color;
}
vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
// TODO: The world space normal doesn;t seem to work properly with the current SH definitions
// FoOr now, we use the normal in view space
vec3 ambientNormal = normal;
vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz;
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return color;
}
vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) {
Light light = getLight();
float diffuseDot = dot(normal, getLightDirection(light));
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold
// it should be just 0, but we have innacurracy so we need to overshoot
const float PERPENDICULAR_THRESHOLD = -0.005;
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
// evaluate the shadow test but only relevant for light facing fragments
float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation;
// diffuse light is the lightmap dimmed by shadow
vec3 diffuseLight = lightAttenuation * lightmap;
// ambient is a tiny percentage of the lightmap and only when in the shadow
vec3 ambientLight = (1 - lightAttenuation) * 0.5 * lightmap;
return diffuse * (ambientLight + diffuseLight);
}
<@endif@>

View file

@ -11,86 +11,51 @@
<@if not DEFERRED_LIGHTING_SLH@>
<@def DEFERRED_LIGHTING_SLH@>
struct SphericalHarmonics {
vec4 L00;
vec4 L1m1;
vec4 L10;
vec4 L11;
vec4 L2m2;
vec4 L2m1;
vec4 L20;
vec4 L21;
vec4 L22;
};
vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) {
const float C1 = 0.429043;
const float C2 = 0.511664;
const float C3 = 0.743125;
const float C4 = 0.886227;
const float C5 = 0.247708;
vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) +
C3 * sh.L20 * direction.z * direction.z +
C4 * sh.L00 - C5 * sh.L20 +
2.0 * C1 * ( sh.L2m2 * direction.x * direction.y +
sh.L21 * direction.x * direction.z +
sh.L2m1 * direction.y * direction.z ) +
2.0 * C2 * ( sh.L11 * direction.x +
sh.L1m1 * direction.y +
sh.L10 * direction.z ) ;
return value;
}
uniform SphericalHarmonics ambientSphere;
vec3 evalAmbientColor(vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
return diffuse.rgb * gl_FrontLightProduct[0].ambient.rgb;
}
vec3 evalAmbientSphereColor(vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
vec3 ambientLight = 0.5 * evalSphericalLight(ambientSphere, normal).xyz;
return diffuse.rgb * ambientLight;
}
vec3 evalDirectionalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
// Diffuse Lighting
float diffuseDot = dot(normal, gl_LightSource[0].position.xyz);
float facingLight = step(0.0, diffuseDot) * shadowAttenuation;
vec3 diffuseColor = diffuse * (gl_FrontLightProduct[0].diffuse.rgb * (diffuseDot * facingLight));
// compute the specular multiplier (sans exponent)
float specularPower = facingLight * max(0.0,
dot(normalize(gl_LightSource[0].position.xyz - normalize(position)), normal));
vec3 specularColor = pow(specularPower, gloss * 128.0) * specular;
float diffuseDot = dot(fragNormal, fragLightDir);
float facingLight = step(0.0, diffuseDot);
float diffuse = diffuseDot * facingLight;
// Specular Lighting depends on the half vector and the gloss
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
// add specular contribution
return vec3(diffuseColor + specularColor);
// float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
float specularPower = pow(max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
specularPower *= (gloss * 128.0 * 0.125 + 0.25);
float shlickPower = (1.0 - dot(fragLightDir,halfDir));
float shlickPower2 = shlickPower * shlickPower;
float shlickPower5 = shlickPower2 * shlickPower2 * shlickPower;
vec3 schlick = specular * (1.0 - shlickPower5) + vec3(shlickPower5);
vec3 reflect = specularPower * schlick;
return vec4(reflect, diffuse);
}
vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
// Diffuse Lighting
float diffuseDot = dot(fragNormal, fragLightDir);
float facingLight = step(0.0, diffuseDot);
float diffuse = diffuseDot * facingLight;
// Specular Lighting depends on the half vector and the gloss
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) {
float diffuseDot = dot(normal, gl_LightSource[0].position.xyz);
// need to catch normals perpendicular to the projection plane hence the magic number for the threshold
// it should be just 0, but we have innacurracy so we need to overshoot
const float PERPENDICULAR_THRESHOLD = -0.005;
float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot);
// evaluate the shadow test but only relevant for light facing fragments
float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation;
// diffuse light is the lightmap dimmed by shadow
vec3 diffuseLight = lightAttenuation * lightmap;
float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0);
vec3 reflect = specularPower * specular;
// ambient is a tiny percentage of the lightmap and only when in the shadow
vec3 ambientLight = (1 - lightAttenuation) * 0.5 * lightmap;
return diffuse * (ambientLight + diffuseLight);
return vec4(reflect, diffuse);
}
vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) {
/*if (gl_FragCoord.x > 1000) {
return evalBlinnShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss);
} else {*/
return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss);
//}
}
<@endif@>

View file

@ -25,6 +25,9 @@
#include "RenderUtil.h"
#include "TextureCache.h"
#include "gpu/Batch.h"
#include "gpu/GLBackend.h"
#include "simple_vert.h"
#include "simple_frag.h"
@ -42,146 +45,6 @@
#include "point_light_frag.h"
#include "spot_light_frag.h"
class SphericalHarmonics {
public:
glm::vec3 L00 ; float spare0;
glm::vec3 L1m1 ; float spare1;
glm::vec3 L10 ; float spare2;
glm::vec3 L11 ; float spare3;
glm::vec3 L2m2 ; float spare4;
glm::vec3 L2m1 ; float spare5;
glm::vec3 L20 ; float spare6;
glm::vec3 L21 ; float spare7;
glm::vec3 L22 ; float spare8;
static const int NUM_COEFFICIENTS = 9;
void assignPreset(int p) {
switch (p) {
case DeferredLightingEffect::OLD_TOWN_SQUARE: {
L00 = glm::vec3( 0.871297f, 0.875222f, 0.864470f);
L1m1 = glm::vec3( 0.175058f, 0.245335f, 0.312891f);
L10 = glm::vec3( 0.034675f, 0.036107f, 0.037362f);
L11 = glm::vec3(-0.004629f,-0.029448f,-0.048028f);
L2m2 = glm::vec3(-0.120535f,-0.121160f,-0.117507f);
L2m1 = glm::vec3( 0.003242f, 0.003624f, 0.007511f);
L20 = glm::vec3(-0.028667f,-0.024926f,-0.020998f);
L21 = glm::vec3(-0.077539f,-0.086325f,-0.091591f);
L22 = glm::vec3(-0.161784f,-0.191783f,-0.219152f);
}
break;
case DeferredLightingEffect::GRACE_CATHEDRAL: {
L00 = glm::vec3( 0.79f, 0.44f, 0.54f);
L1m1 = glm::vec3( 0.39f, 0.35f, 0.60f);
L10 = glm::vec3(-0.34f, -0.18f, -0.27f);
L11 = glm::vec3(-0.29f, -0.06f, 0.01f);
L2m2 = glm::vec3(-0.11f, -0.05f, -0.12f);
L2m1 = glm::vec3(-0.26f, -0.22f, -0.47f);
L20 = glm::vec3(-0.16f, -0.09f, -0.15f);
L21 = glm::vec3( 0.56f, 0.21f, 0.14f);
L22 = glm::vec3( 0.21f, -0.05f, -0.30f);
}
break;
case DeferredLightingEffect::EUCALYPTUS_GROVE: {
L00 = glm::vec3( 0.38f, 0.43f, 0.45f);
L1m1 = glm::vec3( 0.29f, 0.36f, 0.41f);
L10 = glm::vec3( 0.04f, 0.03f, 0.01f);
L11 = glm::vec3(-0.10f, -0.10f, -0.09f);
L2m2 = glm::vec3(-0.06f, -0.06f, -0.04f);
L2m1 = glm::vec3( 0.01f, -0.01f, -0.05f);
L20 = glm::vec3(-0.09f, -0.13f, -0.15f);
L21 = glm::vec3(-0.06f, -0.05f, -0.04f);
L22 = glm::vec3( 0.02f, 0.00f, -0.05f);
}
break;
case DeferredLightingEffect::ST_PETERS_BASILICA: {
L00 = glm::vec3( 0.36f, 0.26f, 0.23f);
L1m1 = glm::vec3( 0.18f, 0.14f, 0.13f);
L10 = glm::vec3(-0.02f, -0.01f, 0.00f);
L11 = glm::vec3( 0.03f, 0.02f, -0.00f);
L2m2 = glm::vec3( 0.02f, 0.01f, -0.00f);
L2m1 = glm::vec3(-0.05f, -0.03f, -0.01f);
L20 = glm::vec3(-0.09f, -0.08f, -0.07f);
L21 = glm::vec3( 0.01f, 0.00f, 0.00f);
L22 = glm::vec3(-0.08f, -0.03f, -0.00f);
}
break;
case DeferredLightingEffect::UFFIZI_GALLERY: {
L00 = glm::vec3( 0.32f, 0.31f, 0.35f);
L1m1 = glm::vec3( 0.37f, 0.37f, 0.43f);
L10 = glm::vec3( 0.00f, 0.00f, 0.00f);
L11 = glm::vec3(-0.01f, -0.01f, -0.01f);
L2m2 = glm::vec3(-0.02f, -0.02f, -0.03f);
L2m1 = glm::vec3(-0.01f, -0.01f, -0.01f);
L20 = glm::vec3(-0.28f, -0.28f, -0.32f);
L21 = glm::vec3( 0.00f, 0.00f, 0.00f);
L22 = glm::vec3(-0.24f, -0.24f, -0.28f);
}
break;
case DeferredLightingEffect::GALILEOS_TOMB: {
L00 = glm::vec3( 1.04f, 0.76f, 0.71f);
L1m1 = glm::vec3( 0.44f, 0.34f, 0.34f);
L10 = glm::vec3(-0.22f, -0.18f, -0.17f);
L11 = glm::vec3( 0.71f, 0.54f, 0.56f);
L2m2 = glm::vec3( 0.64f, 0.50f, 0.52f);
L2m1 = glm::vec3(-0.12f, -0.09f, -0.08f);
L20 = glm::vec3(-0.37f, -0.28f, -0.32f);
L21 = glm::vec3(-0.17f, -0.13f, -0.13f);
L22 = glm::vec3( 0.55f, 0.42f, 0.42f);
}
break;
case DeferredLightingEffect::VINE_STREET_KITCHEN: {
L00 = glm::vec3( 0.64f, 0.67f, 0.73f);
L1m1 = glm::vec3( 0.28f, 0.32f, 0.33f);
L10 = glm::vec3( 0.42f, 0.60f, 0.77f);
L11 = glm::vec3(-0.05f, -0.04f, -0.02f);
L2m2 = glm::vec3(-0.10f, -0.08f, -0.05f);
L2m1 = glm::vec3( 0.25f, 0.39f, 0.53f);
L20 = glm::vec3( 0.38f, 0.54f, 0.71f);
L21 = glm::vec3( 0.06f, 0.01f, -0.02f);
L22 = glm::vec3(-0.03f, -0.02f, -0.03f);
}
break;
case DeferredLightingEffect::BREEZEWAY: {
L00 = glm::vec3( 0.32f, 0.36f, 0.38f);
L1m1 = glm::vec3( 0.37f, 0.41f, 0.45f);
L10 = glm::vec3(-0.01f, -0.01f, -0.01f);
L11 = glm::vec3(-0.10f, -0.12f, -0.12f);
L2m2 = glm::vec3(-0.13f, -0.15f, -0.17f);
L2m1 = glm::vec3(-0.01f, -0.02f, 0.02f);
L20 = glm::vec3(-0.07f, -0.08f, -0.09f);
L21 = glm::vec3( 0.02f, 0.03f, 0.03f);
L22 = glm::vec3(-0.29f, -0.32f, -0.36f);
}
break;
case DeferredLightingEffect::CAMPUS_SUNSET: {
L00 = glm::vec3( 0.79f, 0.94f, 0.98f);
L1m1 = glm::vec3( 0.44f, 0.56f, 0.70f);
L10 = glm::vec3(-0.10f, -0.18f, -0.27f);
L11 = glm::vec3( 0.45f, 0.38f, 0.20f);
L2m2 = glm::vec3( 0.18f, 0.14f, 0.05f);
L2m1 = glm::vec3(-0.14f, -0.22f, -0.31f);
L20 = glm::vec3(-0.39f, -0.40f, -0.36f);
L21 = glm::vec3( 0.09f, 0.07f, 0.04f);
L22 = glm::vec3( 0.67f, 0.67f, 0.52f);
}
break;
case DeferredLightingEffect::FUNSTON_BEACH_SUNSET: {
L00 = glm::vec3( 0.68f, 0.69f, 0.70f);
L1m1 = glm::vec3( 0.32f, 0.37f, 0.44f);
L10 = glm::vec3(-0.17f, -0.17f, -0.17f);
L11 = glm::vec3(-0.45f, -0.42f, -0.34f);
L2m2 = glm::vec3(-0.17f, -0.17f, -0.15f);
L2m1 = glm::vec3(-0.08f, -0.09f, -0.10f);
L20 = glm::vec3(-0.03f, -0.02f, -0.01f);
L21 = glm::vec3( 0.16f, 0.14f, 0.10f);
L22 = glm::vec3( 0.37f, 0.31f, 0.20f);
}
break;
}
}
};
void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
_viewState = viewState;
_simpleProgram.addShaderFromSourceCode(QGLShader::Vertex, simple_vert);
@ -206,6 +69,18 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
loadLightProgram(point_light_frag, true, _pointLight, _pointLightLocations);
loadLightProgram(spot_light_frag, true, _spotLight, _spotLightLocations);
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
_globalLights.push_back(0);
_allocatedLights.push_back(model::LightPointer(new model::Light()));
model::LightPointer lp = _allocatedLights[0];
lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f));
lp->setColor(glm::vec3(1.0f));
lp->setIntensity(1.0f);
lp->setType(model::Light::SUN);
lp->setAmbientSpherePreset(model::SphericalHarmonics::Preset(_ambientLightMode % model::SphericalHarmonics::NUM_PRESET));
}
void DeferredLightingEffect::bindSimpleProgram() {
@ -260,30 +135,29 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation,
float quadraticAttenuation, const glm::vec3& direction, float exponent, float cutoff) {
int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
if (lightID >= _allocatedLights.size()) {
_allocatedLights.push_back(model::LightPointer(new model::Light()));
}
model::LightPointer lp = _allocatedLights[lightID];
lp->setPosition(position);
lp->setMaximumRadius(radius);
lp->setColor(diffuse);
lp->setIntensity(1.0f);
//lp->setShowContour(quadraticAttenuation);
if (exponent == 0.0f && cutoff == PI) {
PointLight light;
light.position = glm::vec4(position, 1.0f);
light.radius = radius;
light.ambient = glm::vec4(ambient, 1.0f);
light.diffuse = glm::vec4(diffuse, 1.0f);
light.specular = glm::vec4(specular, 1.0f);
light.constantAttenuation = constantAttenuation;
light.linearAttenuation = linearAttenuation;
_pointLights.append(light);
lp->setType(model::Light::POINT);
_pointLights.push_back(lightID);
} else {
SpotLight light;
light.position = glm::vec4(position, 1.0f);
light.radius = radius;
light.ambient = glm::vec4(ambient, 1.0f);
light.diffuse = glm::vec4(diffuse, 1.0f);
light.specular = glm::vec4(specular, 1.0f);
light.constantAttenuation = constantAttenuation;
light.linearAttenuation = linearAttenuation;
light.direction = direction;
light.exponent = exponent;
light.cutoff = cutoff;
_spotLights.append(light);
lp->setDirection(direction);
lp->setSpotAngle(cutoff);
lp->setSpotExponent(exponent);
lp->setType(model::Light::SPOT);
_spotLights.push_back(lightID);
}
}
@ -317,7 +191,7 @@ void DeferredLightingEffect::render() {
QOpenGLFramebufferObject* freeFBO = DependencyManager::get<GlowEffect>()->getFreeFramebufferObject();
freeFBO->bind();
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_FRAMEBUFFER_SRGB);
// glEnable(GL_FRAMEBUFFER_SRGB);
glBindTexture(GL_TEXTURE_2D, primaryFBO->texture());
@ -342,6 +216,10 @@ void DeferredLightingEffect::render() {
float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height();
float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height();
// Fetch the ViewMatrix;
glm::mat4 invViewMat;
_viewState->getViewTransform().getMatrix(invViewMat);
ProgramObject* program = &_directionalLight;
const LightLocations* locations = &_directionalLightLocations;
bool shadowsEnabled = _viewState->getShadowsEnabled();
@ -379,19 +257,24 @@ void DeferredLightingEffect::render() {
program->bind();
}
if (locations->ambientSphere >= 0) {
SphericalHarmonics sh;
if (_ambientLightMode < NUM_PRESET) {
sh.assignPreset(_ambientLightMode);
} else {
sh.assignPreset(0);
}
for (int i =0; i <SphericalHarmonics::NUM_COEFFICIENTS; i++) {
program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i));
}
}
{
auto globalLight = _allocatedLights[_globalLights.front()];
if (locations->ambientSphere >= 0) {
auto sh = globalLight->getAmbientSphere();
for (int i =0; i <model::SphericalHarmonics::NUM_COEFFICIENTS; i++) {
program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i));
}
}
if (locations->lightBufferUnit >= 0) {
gpu::Batch batch;
batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());
gpu::GLBackend::renderBatch(batch);
}
glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
}
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
_viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
@ -434,27 +317,27 @@ void DeferredLightingEffect::render() {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (!_pointLights.isEmpty()) {
if (!_pointLights.empty()) {
_pointLight.bind();
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
_pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale);
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
_pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
foreach (const PointLight& light, _pointLights) {
_pointLight.setUniformValue(_pointLightLocations.radius, light.radius);
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
for (auto lightID : _pointLights) {
auto light = _allocatedLights[lightID];
if (_pointLightLocations.lightBufferUnit >= 0) {
gpu::Batch batch;
batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer());
gpu::GLBackend::renderBatch(batch);
}
glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
glPushMatrix();
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius + nearRadius) {
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < expandedRadius + nearRadius) {
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -1.0f);
@ -468,7 +351,7 @@ void DeferredLightingEffect::render() {
glMatrixMode(GL_MODELVIEW);
} else {
glTranslatef(light.position.x, light.position.y, light.position.z);
glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z);
geometryCache->renderSphere(expandedRadius, 32, 32, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
}
@ -479,31 +362,28 @@ void DeferredLightingEffect::render() {
_pointLight.release();
}
if (!_spotLights.isEmpty()) {
if (!_spotLights.empty()) {
_spotLight.bind();
_spotLight.setUniformValue(_spotLightLocations.nearLocation, nearVal);
_spotLight.setUniformValue(_spotLightLocations.depthScale, depthScale);
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT);
_spotLight.setUniformValue(_spotLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT);
foreach (const SpotLight& light, _spotLights) {
_spotLight.setUniformValue(_spotLightLocations.radius, light.radius);
glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient);
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction);
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
for (auto lightID : _spotLights) {
auto light = _allocatedLights[lightID];
if (_spotLightLocations.lightBufferUnit >= 0) {
gpu::Batch batch;
batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer());
gpu::GLBackend::renderBatch(batch);
}
glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat));
glPushMatrix();
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
float edgeRadius = expandedRadius / glm::cos(light.cutoff);
if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius + nearRadius) {
float expandedRadius = light->getMaximumRadius() * (1.0f + SCALE_EXPANSION);
float edgeRadius = expandedRadius / glm::cos(light->getSpotAngle());
if (glm::distance(eyePoint, glm::vec3(light->getPosition())) < edgeRadius + nearRadius) {
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -1.0f);
@ -517,12 +397,12 @@ void DeferredLightingEffect::render() {
glMatrixMode(GL_MODELVIEW);
} else {
glTranslatef(light.position.x, light.position.y, light.position.z);
glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction);
glTranslatef(light->getPosition().x, light->getPosition().y, light->getPosition().z);
glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light->getDirection());
glm::vec3 axis = glm::axis(spotRotation);
glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z);
glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f));
geometryCache->renderCone(expandedRadius * glm::tan(light.cutoff),
glTranslatef(0.0f, 0.0f, -light->getMaximumRadius() * (1.0f + SCALE_EXPANSION * 0.5f));
geometryCache->renderCone(expandedRadius * glm::tan(light->getSpotAngle()),
expandedRadius, 32, 1);
}
@ -545,7 +425,7 @@ void DeferredLightingEffect::render() {
glBindTexture(GL_TEXTURE_2D, 0);
freeFBO->release();
glDisable(GL_FRAMEBUFFER_SRGB);
// glDisable(GL_FRAMEBUFFER_SRGB);
glDisable(GL_CULL_FACE);
@ -607,11 +487,46 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit
locations.depthTexCoordScale = program.uniformLocation("depthTexCoordScale");
locations.radius = program.uniformLocation("radius");
locations.ambientSphere = program.uniformLocation("ambientSphere.L00");
locations.invViewMat = program.uniformLocation("invViewMat");
GLint loc = -1;
#if defined(Q_OS_MAC)
loc = program.uniformLocation("lightBuffer");
if (loc >= 0) {
locations.lightBufferUnit = loc;
} else {
locations.lightBufferUnit = -1;
}
#elif defined(Q_OS_WIN)
loc = glGetUniformBlockIndex(program.programId(), "lightBuffer");
if (loc >= 0) {
glUniformBlockBinding(program.programId(), loc, 0);
locations.lightBufferUnit = 0;
} else {
locations.lightBufferUnit = -1;
}
#else
loc = program.uniformLocation("lightBuffer");
if (loc >= 0) {
locations.lightBufferUnit = loc;
} else {
locations.lightBufferUnit = -1;
}
#endif
program.release();
}
void DeferredLightingEffect::setAmbientLightMode(int preset) {
if ((preset >= -1) && (preset < NUM_PRESET)) {
if ((preset >= -1) && (preset < model::SphericalHarmonics::NUM_PRESET)) {
_ambientLightMode = preset;
auto light = _allocatedLights.front();
light->setAmbientSpherePreset(model::SphericalHarmonics::Preset(preset % model::SphericalHarmonics::NUM_PRESET));
}
}
void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity) {
auto light = _allocatedLights.front();
light->setDirection(direction);
light->setColor(diffuse);
light->setIntensity(intensity);
}

View file

@ -19,6 +19,8 @@
#include "ProgramObject.h"
#include "model/Light.h"
class AbstractViewStateInterface;
class PostLightingRenderable;
@ -71,25 +73,12 @@ public:
void prepare();
void render();
enum AmbientLightPreset {
OLD_TOWN_SQUARE = 0,
GRACE_CATHEDRAL,
EUCALYPTUS_GROVE,
ST_PETERS_BASILICA,
UFFIZI_GALLERY,
GALILEOS_TOMB,
VINE_STREET_KITCHEN,
BREEZEWAY,
CAMPUS_SUNSET,
FUNSTON_BEACH_SUNSET,
NUM_PRESET,
};
// update global lighting
void setAmbientLightMode(int preset);
void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity);
private:
DeferredLightingEffect() { }
DeferredLightingEffect() {}
virtual ~DeferredLightingEffect() { }
class LightLocations {
@ -102,6 +91,8 @@ private:
int depthTexCoordScale;
int radius;
int ambientSphere;
int lightBufferUnit;
int invViewMat;
};
static void loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations);
@ -146,9 +137,13 @@ private:
float exponent;
float cutoff;
};
QVector<PointLight> _pointLights;
QVector<SpotLight> _spotLights;
typedef std::vector< model::LightPointer > Lights;
Lights _allocatedLights;
std::vector<int> _globalLights;
std::vector<int> _pointLights;
std::vector<int> _spotLights;
QVector<PostLightingRenderable*> _postLightingRenderables;
AbstractViewStateInterface* _viewState;

View file

@ -1152,7 +1152,7 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
gpu::Batch batch;
glEnable(GL_TEXTURE_2D);
// glEnable(GL_TEXTURE_2D);
//glBindTexture(GL_TEXTURE_2D, _currentTextureID); // this is quad specific...
batch.setInputFormat(details.streamFormat);
@ -1166,8 +1166,8 @@ void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxC
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
// glBindTexture(GL_TEXTURE_2D, 0);
// glDisable(GL_TEXTURE_2D);
}
void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {

View file

@ -0,0 +1,107 @@
<!
// Light.slh
// fragment shader
//
// Created by Sam Gateau on 1/25/14.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not LIGHT_SLH@>
<@def LIGHT_SLH@>
struct Light {
vec4 _position;
vec4 _direction;
vec4 _color;
vec4 _attenuation;
vec4 _spot;
vec4 _shadow;
vec4 _control;
};
vec3 getLightPosition(Light l) { return l._position.xyz; }
vec3 getLightDirection(Light l) { return l._direction.xyz; } // direction is -Z axis
vec3 getLightColor(Light l) { return l._color.rgb; }
float getLightIntensity(Light l) { return l._color.w; }
float evalLightAttenuation(Light l, float r) {
float d = max(r - l._attenuation.x, 0.0);
float denom = d * l._attenuation.y + 1.0;
float attenuation = 1.0 / (denom * denom);
return max((attenuation - l._attenuation.z)/(1.0 - l._attenuation.z), 0.0);
// return clamp(1.0/(l._attenuation.x + l._attenuation.y * r + l._attenuation.z * r * r), 0.0, 1.0);
}
float getLightSpotAngleCos(Light l) {
return l._spot.x;
}
vec2 getLightSpotOutsideNormal2(Light l) {
return vec2(-l._spot.y, l._spot.x);
}
float evalLightSpotAttenuation(Light l, float cosA) {
return pow(cosA, l._spot.w);
}
float getLightSquareRadius(Light l) {
return l._attenuation.w * l._attenuation.w;
}
float getLightRadius(Light l) {
return l._attenuation.w;
}
float getLightAttenuationCutoff(Light l) {
return l._attenuation.z;
}
float getLightShowContour(Light l) {
return l._control.w;
}
<@if GLPROFILE == PC_GL@>
uniform lightBuffer {
Light light;
};
Light getLight() {
return light;
}
<@elif GLPROFILE == MAC_GL@>
uniform vec4 lightBuffer[9];
Light getLight() {
Light light;
light._position = lightBuffer[0];
light._direction = lightBuffer[1];
light._color = lightBuffer[2];
light._attenuation = lightBuffer[3];
light._spot = lightBuffer[4];
light._shadow = lightBuffer[5];
light._control = lightBuffer[6];
return light;
}
<@else@>
uniform vec4 lightBuffer[9];
Light getLight() {
Light light;
light._position = lightBuffer[0];
light._direction = lightBuffer[1];
light._color = lightBuffer[2];
light._attenuation = lightBuffer[3];
light._spot = lightBuffer[4];
light._shadow = lightBuffer[5];
light._control = lightBuffer[6];
return light;
}
<@endif@>
<@endif@>

View file

@ -2437,11 +2437,9 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
}
static bool showDiffuse = true;
if (showDiffuse && diffuseMap) {
// GLBATCH(glBindTexture)(GL_TEXTURE_2D, diffuseMap->getID());
batch.setUniformTexture(0, diffuseMap->getGPUTexture());
} else {
// GLBATCH(glBindTexture)(GL_TEXTURE_2D, textureCache->getWhiteTextureID());
batch.setUniformTexture(0, textureCache->getWhiteTexture());
}

View file

@ -15,22 +15,23 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
void main(void) {
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
// Light mapped or not ?
if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) {
gl_FragColor = vec4( evalLightmappedColor(
vec3 color = evalLightmappedColor(
1.0,
frag.normal,
frag.diffuse,
frag.specularVal.xyz),
1.0);
frag.specularVal.xyz);
gl_FragColor = vec4(color, 1.0);
} else {
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(1.0,
vec3 color = evalAmbienSphereGlobalColor(1.0,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -15,7 +15,7 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
// Everything about shadow
<@include Shadow.slh@>
@ -36,8 +36,7 @@ void main(void) {
frag.specularVal.xyz),
1.0);
} else {
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(shadowAttenuation,
vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -15,7 +15,7 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
// Everything about shadow
<@include Shadow.slh@>
@ -37,8 +37,7 @@ void main(void) {
frag.specularVal.xyz),
1.0);
} else {
vec3 color = evalAmbientSphereColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(shadowAttenuation,
vec3 color = evalAmbienSphereGlobalColor(shadowAttenuation,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -15,7 +15,7 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
void main(void) {
DeferredFragment frag = unpackDeferredFragment(gl_TexCoord[0].st);
@ -29,8 +29,7 @@ void main(void) {
frag.specularVal.xyz),
1.0);
} else {
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(1.0,
vec3 color = evalAmbienGlobalColor(1.0,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -15,7 +15,7 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
// Everything about shadow
<@include Shadow.slh@>
@ -36,8 +36,7 @@ void main(void) {
frag.specularVal.xyz),
1.0);
} else {
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(shadowAttenuation,
vec3 color = evalAmbienGlobalColor(shadowAttenuation,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -15,7 +15,7 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
<@include DeferredLighting.slh@>
<@include DeferredGlobalLight.slh@>
// Everything about shadow
<@include Shadow.slh@>
@ -37,8 +37,7 @@ void main(void) {
frag.specularVal.xyz),
1.0);
} else {
vec3 color = evalAmbientColor(frag.normal, frag.diffuse, frag.specular, frag.gloss)
+ evalDirectionalColor(shadowAttenuation,
vec3 color = evalAmbienGlobalColor(shadowAttenuation,
frag.position.xyz,
frag.normal,
frag.diffuse,

View file

@ -33,8 +33,9 @@ void main(void) {
// and the texture coordinates
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
// interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0)).xy;
interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy;
// use standard pipeline transform
gl_Position = ftransform();
}

View file

@ -15,41 +15,61 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
// the radius (hard cutoff) of the light effect
uniform float radius;
//Everything about deferred lighting
<@include DeferredLighting.slh@>
// Everything about light
<@include Light.slh@>
// The view Matrix
uniform mat4 invViewMat;
void main(void) {
// get the depth and exit early if it doesn't pass the test
// Grab the fragment data from the uv
vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q;
float depth = texture2D(depthMap, texCoord).r;
DeferredFragment frag = unpackDeferredFragment(texCoord);
// Kill if in front of the light volume
float depth = frag.depthVal;
if (depth < gl_FragCoord.z) {
discard;
}
// compute the view space position using the depth
float z = near / (depth * depthScale - 1.0);
vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0);
// get the normal from the map
vec4 normal = texture2D(normalMap, texCoord);
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
// compute the base color based on OpenGL lighting model
vec4 lightVector = gl_LightSource[1].position - position;
float lightDistance = length(lightVector);
lightVector = lightVector / lightDistance;
float diffuse = dot(normalizedNormal, lightVector);
float facingLight = step(0.0, diffuse);
vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient +
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
// compute attenuation based on distance, etc.
float attenuation = step(lightDistance, radius) / dot(vec3(gl_LightSource[1].constantAttenuation,
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
vec3(1.0, lightDistance, lightDistance * lightDistance));
// add base to specular, modulate by attenuation
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
normalizedNormal));
vec4 specularColor = texture2D(specularMap, texCoord);
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
// Need the light now
Light light = getLight();
// Make the Light vector going from fragment to light center in world space
vec4 fragPos = invViewMat * frag.position;
vec3 fragLightVec = getLightPosition(light) - fragPos.xyz;
// Kill if too far from the light center
if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) {
discard;
}
// Allright we re valid in the volume
float fragLightDistance = length(fragLightVec);
vec3 fragLightDir = fragLightVec / fragLightDistance;
// Eval shading
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
// Eval attenuation
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
// Final Lighting color
vec3 fragColor = shading.w * (frag.diffuse + shading.xyz);
gl_FragColor = vec4(fragColor * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0);
if (getLightShowContour(light) > 0.0) {
// Show edge
float edge = abs(2.0 * ((getLightRadius(light) - fragLightDistance) / (0.1)) - 1.0);
if (edge < 1) {
float edgeCoord = exp2(-8.0*edge*edge);
gl_FragColor = vec4(edgeCoord * edgeCoord * getLightShowContour(light) * getLightColor(light), 0.0);
}
}
}

View file

@ -15,43 +15,73 @@
// Everything about deferred buffer
<@include DeferredBuffer.slh@>
// the radius (hard cutoff) of the light effect
uniform float radius;
//Everything about deferred lighting
<@include DeferredLighting.slh@>
// Everything about light
<@include Light.slh@>
// The view Matrix
uniform mat4 invViewMat;
void main(void) {
// get the depth and exit early if it doesn't pass the test
// Grab the fragment data from the uv
vec2 texCoord = gl_TexCoord[0].st / gl_TexCoord[0].q;
float depth = texture2D(depthMap, texCoord).r;
DeferredFragment frag = unpackDeferredFragment(texCoord);
// Kill if in front of the light volume
float depth = frag.depthVal;
if (depth < gl_FragCoord.z) {
discard;
}
// compute the view space position using the depth
float z = near / (depth * depthScale - 1.0);
vec4 position = vec4((depthTexCoordOffset + texCoord * depthTexCoordScale) * z, z, 1.0);
// get the normal from the map
vec4 normal = texture2D(normalMap, texCoord);
vec4 normalizedNormal = normalize(normal * 2.0 - vec4(1.0, 1.0, 1.0, 2.0));
// compute the base color based on OpenGL lighting model
vec4 lightVector = gl_LightSource[1].position - position;
float lightDistance = length(lightVector);
lightVector = lightVector / lightDistance;
float diffuse = dot(normalizedNormal, lightVector);
float facingLight = step(0.0, diffuse);
vec4 baseColor = texture2D(diffuseMap, texCoord) * (gl_FrontLightProduct[1].ambient +
gl_FrontLightProduct[1].diffuse * (diffuse * facingLight));
// compute attenuation based on spot angle, distance, etc.
float cosSpotAngle = max(-dot(lightVector.xyz, gl_LightSource[1].spotDirection), 0.0);
float attenuation = step(lightDistance, radius) * step(gl_LightSource[1].spotCosCutoff, cosSpotAngle) *
pow(cosSpotAngle, gl_LightSource[1].spotExponent) / dot(vec3(gl_LightSource[1].constantAttenuation,
gl_LightSource[1].linearAttenuation, gl_LightSource[1].quadraticAttenuation),
vec3(1.0, lightDistance, lightDistance * lightDistance));
// add base to specular, modulate by attenuation
float specular = facingLight * max(0.0, dot(normalize(lightVector - normalize(vec4(position.xyz, 0.0))),
normalizedNormal));
vec4 specularColor = texture2D(specularMap, texCoord);
gl_FragColor = vec4((baseColor.rgb + pow(specular, specularColor.a * 128.0) * specularColor.rgb) * attenuation, 0.0);
// Need the light now
Light light = getLight();
// Make the Light vector going from fragment to light center in world space
vec4 fragPos = invViewMat * frag.position;
vec3 fragLightVec = getLightPosition(light) - fragPos.xyz;
// Kill if too far from the light center
if (dot(fragLightVec, fragLightVec) > getLightSquareRadius(light)) {
discard;
}
// Allright we re valid in the volume
float fragLightDistance = length(fragLightVec);
vec3 fragLightDir = fragLightVec / fragLightDistance;
// Kill if not in the spot light (ah ah !)
vec3 lightSpotDir = getLightDirection(light);
float cosSpotAngle = max(-dot(fragLightDir, lightSpotDir), 0.0);
if (cosSpotAngle < getLightSpotAngleCos(light)) {
discard;
}
// Eval shading
vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0));
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss);
// Eval attenuation
float radialAttenuation = evalLightAttenuation(light, fragLightDistance);
float angularAttenuation = evalLightSpotAttenuation(light, cosSpotAngle);
// Final Lighting color
vec3 fragColor = shading.w * (frag.diffuse + shading.xyz);
gl_FragColor = vec4(fragColor * angularAttenuation * radialAttenuation * getLightColor(light) * getLightIntensity(light), 0.0);
if (getLightShowContour(light) > 0.0) {
// Show edges
float edgeDistR = (getLightRadius(light) - fragLightDistance);
float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -getLightSpotOutsideNormal2(light));
float edgeDist = min(edgeDistR, edgeDistS);
float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0);
if (edge < 1) {
float edgeCoord = exp2(-8.0*edge*edge);
gl_FragColor = vec4(edgeCoord * edgeCoord * getLightColor(light), 0.0);
}
}
}

View file

@ -100,6 +100,8 @@ public:
// Left will be inversed before the multiplication
static Transform& inverseMult(Transform& result, const Transform& left, const Transform& right);
Vec4 transform(const Vec4& pos) const;
protected:
enum Flag {
@ -414,6 +416,13 @@ inline Transform& Transform::inverseMult( Transform& result, const Transform& le
return result;
}
inline Transform::Vec4 Transform::transform(const Vec4& pos) const {
Mat4 m;
getMatrix(m);
return m * pos;
}
inline Transform::Mat4& Transform::getCachedMatrix(Transform::Mat4& result) const {
updateCache();
result = (*_matrix);