Merge pull request #7114 from samcake/hdr

Adding Ambient lighting to transparent surfaces
This commit is contained in:
Brad Hefta-Gaub 2016-02-17 09:08:38 -08:00
commit d5c349abec
8 changed files with 85 additions and 98 deletions

View file

@ -116,5 +116,10 @@ void Light::setShowContour(float show) {
editSchema()._control.w = show;
}
void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) {
editSchema()._ambientSphere = sphere;
}
void Light::setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) {
editSchema()._ambientSphere.assignPreset(preset);
}

View file

@ -94,10 +94,10 @@ public:
void setAmbientIntensity(float intensity);
float getAmbientIntensity() const { return getSchema()._ambientIntensity; }
// Spherical Harmonics storing the Ambien lighting approximation used for the Sun typed light
void setAmbientSphere(const gpu::SphericalHarmonics& sphere) { _ambientSphere = sphere; }
const gpu::SphericalHarmonics& getAmbientSphere() const { return _ambientSphere; }
void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) { _ambientSphere.assignPreset(preset); }
// Spherical Harmonics storing the Ambient lighting approximation used for the Sun typed light
void setAmbientSphere(const gpu::SphericalHarmonics& sphere);
const gpu::SphericalHarmonics& getAmbientSphere() const { return getSchema()._ambientSphere; }
void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset);
// Schema to access the attribute values of the light
class Schema {
@ -112,6 +112,8 @@ public:
Vec4 _shadow{0.0f};
Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f};
gpu::SphericalHarmonics _ambientSphere;
};
const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; }
@ -121,7 +123,6 @@ protected:
Flags _flags;
UniformBufferView _schemaBuffer;
Transform _transform;
gpu::SphericalHarmonics _ambientSphere;
const Schema& getSchema() const { return _schemaBuffer.get<Schema>(); }
Schema& editSchema() { return _schemaBuffer.edit<Schema>(); }

View file

@ -11,6 +11,41 @@
<@if not MODEL_LIGHT_SLH@>
<@def MODEL_LIGHT_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 ) {
vec3 dir = direction.xyz;
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 * (dir.x * dir.x - dir.y * dir.y) +
C3 * sh.L20 * dir.z * dir.z +
C4 * sh.L00 - C5 * sh.L20 +
2.0 * C1 * ( sh.L2m2 * dir.x * dir.y +
sh.L21 * dir.x * dir.z +
sh.L2m1 * dir.y * dir.z ) +
2.0 * C2 * ( sh.L11 * dir.x +
sh.L1m1 * dir.y +
sh.L10 * dir.z ) ;
return value;
}
struct Light {
vec4 _position;
vec4 _direction;
@ -20,6 +55,8 @@ struct Light {
vec4 _shadow;
vec4 _control;
SphericalHarmonics _ambientSphere;
};
vec3 getLightPosition(Light l) { return l._position.xyz; }
@ -65,6 +102,10 @@ float getLightShowContour(Light l) {
return l._control.w;
}
SphericalHarmonics getLightAmbientSphere(Light l) {
return l._ambientSphere;
}
<@if GPU_FEATURE_PROFILE == GPU_CORE @>
uniform lightBuffer {
Light light;

View file

@ -26,46 +26,6 @@ vec4 evalSkyboxLight(vec3 direction, float lod) {
<@endfunc@>
<@func declareSphericalHarmonics()@>
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 ) {
vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis?
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 * (dir.x * dir.x - dir.y * dir.y) +
C3 * sh.L20 * dir.z * dir.z +
C4 * sh.L00 - C5 * sh.L20 +
2.0 * C1 * ( sh.L2m2 * dir.x * dir.y +
sh.L21 * dir.x * dir.z +
sh.L2m1 * dir.y * dir.z ) +
2.0 * C2 * ( sh.L11 * dir.x +
sh.L1m1 * dir.y +
sh.L10 * dir.z ) ;
return value;
}
// Need one SH
uniform SphericalHarmonics ambientSphere;
<@endfunc@>
// Everything about light
<@include model/Light.slh@>
@ -91,8 +51,6 @@ vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obsc
<@func declareEvalAmbientSphereGlobalColor()@>
<$declareSphericalHarmonics()$>
vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
Light light = getLight();
@ -102,7 +60,7 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 ambientNormal = fragNormal.xyz;
vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, ambientNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), ambientNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
@ -115,7 +73,6 @@ vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, floa
<@func declareEvalSkyboxGlobalColor()@>
<$declareSkyboxMap()$>
<$declareSphericalHarmonics()$>
vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) {
// Need the light now
@ -125,7 +82,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
vec4 fragEyeVector = invViewMat * vec4(-position, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
vec3 color = diffuse.rgb * evalSphericalLight(ambientSphere, fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);

View file

@ -344,26 +344,7 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
}
{ // Setup the global lighting
auto globalLight = _allocatedLights[_globalLights.front()];
if (locations->ambientSphere >= 0) {
gpu::SphericalHarmonics sh = globalLight->getAmbientSphere();
if (useSkyboxCubemap && _skybox->getCubemap()->getIrradiance()) {
sh = (*_skybox->getCubemap()->getIrradiance());
}
for (int i =0; i <gpu::SphericalHarmonics::NUM_COEFFICIENTS; i++) {
batch._glUniform4fv(locations->ambientSphere + i, 1, (const float*) (&sh) + i * 4);
}
}
if (useSkyboxCubemap) {
batch.setResourceTexture(SKYBOX_MAP_UNIT, _skybox->getCubemap());
}
if (locations->lightBufferUnit >= 0) {
batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer());
}
setupKeyLightBatch(batch, locations->lightBufferUnit, SKYBOX_MAP_UNIT);
}
{
@ -512,10 +493,18 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
}
}
void DeferredLightingEffect::setupBatch(gpu::Batch& batch, int lightBufferUnit) {
void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit) {
PerformanceTimer perfTimer("DLE->setupBatch()");
auto globalLight = _allocatedLights[_globalLights.front()];
batch.setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
if (lightBufferUnit >= 0) {
batch.setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer());
}
bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap());
if (useSkyboxCubemap && (skyboxCubemapUnit >= 0)) {
batch.setResourceTexture(skyboxCubemapUnit, _skybox->getCubemap());
}
}
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& pipeline, LightLocationsPtr& locations) {
@ -594,6 +583,11 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl
void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) {
_skybox = skybox;
auto light = _allocatedLights.front();
if (_skybox && _skybox->getCubemap() && _skybox->getCubemap()->isDefined() && _skybox->getCubemap()->getIrradiance()) {
light->setAmbientSphere( (*_skybox->getCubemap()->getIrradiance()) );
}
}
model::MeshPointer DeferredLightingEffect::getSpotLightMesh() {

View file

@ -46,7 +46,7 @@ public:
void prepare(RenderArgs* args);
void render(const render::RenderContextPointer& renderContext);
void setupBatch(gpu::Batch& batch, int lightBufferUnit);
void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit);
// update global lighting
void setAmbientLightMode(int preset);

View file

@ -96,7 +96,9 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) {
batchSetter(pipeline, batch);
// Set the light
if (pipeline.locations->lightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupBatch(batch, pipeline.locations->lightBufferUnit);
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(batch,
pipeline.locations->lightBufferUnit,
-1);
}
}

View file

@ -5,7 +5,7 @@
// model_translucent.frag
// fragment shader
//
// Created by Andrzej Kapolka on 9/19/14.
// Created by Sam Gateau on 2/15/2016.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
@ -14,31 +14,13 @@
<@include model/Material.slh@>
<@include DeferredLighting.slh@>
<@include model/Light.slh@>
<@include DeferredGlobalLight.slh@>
<$declareEvalAmbientSphereGlobalColor()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) {
// Need the light now
Light light = getLight();
TransformCamera cam = getTransformCamera();
vec3 fragNormal;
<$transformEyeToWorldDir(cam, normal, fragNormal)$>
vec3 fragEyeVectorView = normalize(-position);
vec3 fragEyeDir;
<$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$>
vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light);
vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss);
color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light);
return vec4(color, opacity);
}
uniform sampler2D diffuseMap;
@ -61,11 +43,16 @@ void main(void) {
float fragGloss = getMaterialShininess(mat) / 128;
float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha;
_fragColor = evalGlobalColor(1.0,
TransformCamera cam = getTransformCamera();
_fragColor = vec4(evalAmbientSphereGlobalColor(
cam._viewInverse,
1.0,
1.0,
fragPosition,
fragNormal,
fragDiffuse,
fragSpecular,
fragGloss,
fragGloss),
fragOpacity);
}