Merge pull request #6678 from samcake/hdr

Graphics: Tone mapping Tone curve is now configurable and Material colors are sRGB by default
This commit is contained in:
Clément Brisset 2015-12-17 09:43:02 -08:00
commit aac59ad442
11 changed files with 134 additions and 36 deletions

View file

@ -3703,6 +3703,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
renderContext._fxaaStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing);
renderContext._toneMappingExposure = sceneInterface->getEngineToneMappingExposure();
renderContext._toneMappingToneCurve = sceneInterface->getEngineToneMappingToneCurveValue();
renderArgs->_shouldRender = LODManager::shouldRender;

View file

@ -44,9 +44,9 @@ Material& Material::operator= (const Material& material) {
Material::~Material() {
}
void Material::setDiffuse(const Color& diffuse) {
void Material::setDiffuse(const Color& diffuse, bool isSRGB) {
_key.setDiffuse(glm::any(glm::greaterThan(diffuse, Color(0.0f))));
_schemaBuffer.edit<Schema>()._diffuse = diffuse;
_schemaBuffer.edit<Schema>()._diffuse = (isSRGB ? ColorUtils::toLinearVec3(diffuse) : diffuse);
}
void Material::setMetallic(float metallic) {
@ -54,9 +54,9 @@ void Material::setMetallic(float metallic) {
_schemaBuffer.edit<Schema>()._metallic = glm::vec3(metallic);
}
void Material::setEmissive(const Color& emissive) {
void Material::setEmissive(const Color& emissive, bool isSRGB) {
_key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f))));
_schemaBuffer.edit<Schema>()._emissive = emissive;
_schemaBuffer.edit<Schema>()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive);
}
void Material::setGloss(float gloss) {

View file

@ -14,7 +14,7 @@
#include <bitset>
#include <map>
#include <glm/glm.hpp>
#include <ColorUtils.h>
#include <gpu/Resource.h>
@ -219,28 +219,31 @@ public:
virtual ~Material();
const MaterialKey& getKey() const { return _key; }
const Color& getEmissive() const { return _schemaBuffer.get<Schema>()._emissive; }
const Color& getDiffuse() const { return _schemaBuffer.get<Schema>()._diffuse; }
float getMetallic() const { return _schemaBuffer.get<Schema>()._metallic.x; }
float getGloss() const { return _schemaBuffer.get<Schema>()._gloss; }
float getOpacity() const { return _schemaBuffer.get<Schema>()._opacity; }
void setEmissive(const Color& emissive);
void setDiffuse(const Color& diffuse);
void setEmissive(const Color& emissive, bool isSRGB = true);
const Color& getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._emissive) : _schemaBuffer.get<Schema>()._emissive); }
void setDiffuse(const Color& diffuse, bool isSRGB = true);
const Color& getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._diffuse) : _schemaBuffer.get<Schema>()._diffuse); }
void setMetallic(float metallic);
float getMetallic() const { return _schemaBuffer.get<Schema>()._metallic.x; }
void setGloss(float gloss);
float getGloss() const { return _schemaBuffer.get<Schema>()._gloss; }
void setOpacity(float opacity);
float getOpacity() const { return _schemaBuffer.get<Schema>()._opacity; }
// Schema to access the attribute values of the material
class Schema {
public:
Color _diffuse{0.5f};
glm::vec3 _diffuse{ 0.5f };
float _opacity{1.f};
Color _metallic{0.03f};
glm::vec3 _metallic{ 0.03f };
float _gloss{0.1f};
Color _emissive{0.0f};
glm::vec3 _emissive{ 0.0f };
float _spare0{0.0f};
glm::vec4 _spareVec4{0.0f}; // for alignment beauty, Material size == Mat4x4

View file

@ -166,6 +166,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
setAntialiasingStatus(renderContext->_fxaaStatus);
setToneMappingExposure(renderContext->_toneMappingExposure);
setToneMappingToneCurve(renderContext->_toneMappingToneCurve);
renderContext->args->_context->syncCache();
@ -403,8 +404,23 @@ void RenderDeferredTask::setToneMappingExposure(float exposure) {
float RenderDeferredTask::getToneMappingExposure() const {
if (_toneMappingJobIndex >= 0) {
_jobs[_toneMappingJobIndex].get<ToneMappingDeferred>()._toneMappingEffect.getExposure();
return _jobs[_toneMappingJobIndex].get<ToneMappingDeferred>()._toneMappingEffect.getExposure();
} else {
return 0.0f;
}
}
void RenderDeferredTask::setToneMappingToneCurve(int toneCurve) {
if (_toneMappingJobIndex >= 0) {
_jobs[_toneMappingJobIndex].edit<ToneMappingDeferred>()._toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)toneCurve);
}
}
int RenderDeferredTask::getToneMappingToneCurve() const {
if (_toneMappingJobIndex >= 0) {
return _jobs[_toneMappingJobIndex].get<ToneMappingDeferred>()._toneMappingEffect.getToneCurve();
} else {
return 0.0f;
}
}

View file

@ -134,6 +134,9 @@ public:
void setToneMappingExposure(float exposure);
float getToneMappingExposure() const;
void setToneMappingToneCurve(int toneCurve);
int getToneMappingToneCurve() const;
virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);

View file

@ -36,18 +36,28 @@ void ToneMappingEffect::init() {
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
struct ToneMappingParams {
vec4 _exp_2powExp_s0_s1;
ivec4 _toneCurve_s0_s1_s2;
};
const float INV_GAMMA_22 = 1.0 / 2.2;
const int ToneCurveNone = 0;
const int ToneCurveGamma22 = 1;
const int ToneCurveReinhard = 2;
const int ToneCurveFilmic = 3;
uniform toneMappingParamsBuffer {
ToneMappingParams params;
};
float getTwoPowExposure() {
return params._exp_2powExp_s0_s1.y;
}
int getToneCurve() {
return params._toneCurve_s0_s1_s2.x;
}
uniform sampler2D colorMap;
in vec2 varTexCoord0;
@ -56,25 +66,26 @@ void ToneMappingEffect::init() {
void main(void) {
vec4 fragColorRaw = textureLod(colorMap, varTexCoord0, 0);
vec3 fragColor = fragColorRaw.xyz;
/* vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10);
/*
vec4 fragColorAverage = textureLod(colorMap, varTexCoord0, 10);
float averageIntensity = length(fragColorAverage.xyz);
vec3 fragColor = fragColorRaw.xyz / averageIntensity;
fragColor /= averageIntensity;
*/
fragColor *= getTwoPowExposure();
vec3 srcColor = fragColor * getTwoPowExposure();
int toneCurve = getToneCurve();
vec3 tonedColor = srcColor;
if (toneCurve == ToneCurveFilmic) {
vec3 x = max(vec3(0.0), srcColor-0.004);
tonedColor = (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);
} else if (toneCurve == ToneCurveReinhard) {
tonedColor = srcColor/(1.0 + srcColor);
tonedColor = pow(tonedColor, vec3(INV_GAMMA_22));
} else if (toneCurve == ToneCurveGamma22) {
tonedColor = pow(srcColor, vec3(INV_GAMMA_22));
} // else None toned = src
// Manually gamma correct from Ligthing BUffer to color buffer
// outFragColor.xyz = pow( fragColor.xyz , vec3(1.0 / 2.2) );
vec3 x = max(vec3(0.0),fragColor.xyz-0.004);
vec3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
// fragColor = fragColor/(1.0+fragColor);
// vec3 retColor = pow(fragColor.xyz,vec3(1/2.2));
outFragColor = vec4(retColor, 1.0);
outFragColor = vec4(tonedColor, 1.0);
}
)SCRIBE";
@ -96,6 +107,9 @@ void ToneMappingEffect::setExposure(float exposure) {
_parametersBuffer.edit<Parameters>()._twoPowExposure = pow(2.0, exposure);
}
void ToneMappingEffect::setToneCurve(ToneCurve curve) {
_parametersBuffer.edit<Parameters>()._toneCurve = curve;
}
void ToneMappingEffect::render(RenderArgs* args) {
if (!_blitLightBuffer) {

View file

@ -30,6 +30,16 @@ public:
void setExposure(float exposure);
float getExposure() const { return _parametersBuffer.get<Parameters>()._exposure; }
// Different tone curve available
enum ToneCurve {
None = 0,
Gamma22,
Reinhard,
Filmic,
};
void setToneCurve(ToneCurve curve);
ToneCurve getToneCurve() const { return (ToneCurve)_parametersBuffer.get<Parameters>()._toneCurve; }
private:
gpu::PipelinePointer _blitLightBuffer;
@ -39,7 +49,9 @@ private:
public:
float _exposure = 0.0f;
float _twoPowExposure = 1.0f;
glm::vec2 spare;
glm::vec2 spareA;
int _toneCurve = Filmic;
glm::vec3 spareB;
Parameters() {}
};

View file

@ -62,6 +62,7 @@ public:
bool _fxaaStatus = false;
float _toneMappingExposure = 0.0;
int _toneMappingToneCurve = 3;
RenderContext() {}
};

View file

@ -167,3 +167,30 @@ void SceneScriptingInterface::clearEngineCounters() {
_numFeedOverlay3DItems = 0;
_numDrawnOverlay3DItems = 0;
}
void SceneScriptingInterface::setEngineToneMappingToneCurve(const QString& toneCurve) {
if (toneCurve == QString("None")) {
_engineToneMappingToneCurve = 0;
} else if (toneCurve == QString("Gamma22")) {
_engineToneMappingToneCurve = 1;
} else if (toneCurve == QString("Reinhard")) {
_engineToneMappingToneCurve = 2;
} else if (toneCurve == QString("Filmic")) {
_engineToneMappingToneCurve = 3;
}
}
QString SceneScriptingInterface::getEngineToneMappingToneCurve() const {
switch (_engineToneMappingToneCurve) {
case 0:
return QString("None");
case 1:
return QString("Gamma22");
case 2:
return QString("Reinhard");
case 3:
return QString("Filmic");
default:
return QString("Filmic");
};
}

View file

@ -119,7 +119,11 @@ public:
Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; }
Q_INVOKABLE void setEngineToneMappingExposure(float exposure) { _engineToneMappingExposure = exposure; }
Q_INVOKABLE float getEngineToneMappingExposure() { return _engineToneMappingExposure; }
Q_INVOKABLE float getEngineToneMappingExposure() const { return _engineToneMappingExposure; }
Q_INVOKABLE void setEngineToneMappingToneCurve(const QString& curve);
Q_INVOKABLE QString getEngineToneMappingToneCurve() const;
int getEngineToneMappingToneCurveValue() const { return _engineToneMappingToneCurve; }
signals:
void shouldRenderAvatarsChanged(bool shouldRenderAvatars);
@ -158,6 +162,7 @@ protected:
bool _drawHitEffect = false;
float _engineToneMappingExposure = 0.0f;
int _engineToneMappingToneCurve = 3;
};
#endif // hifi_SceneScriptingInterface_h

View file

@ -20,6 +20,10 @@
class ColorUtils {
public:
inline static glm::vec3 toVec3(const xColor& color);
// Convert from gamma 2.2 space to linear
inline static glm::vec3 toLinearVec3(const glm::vec3& srgb);
inline static glm::vec3 toGamma22Vec3(const glm::vec3& linear);
};
inline glm::vec3 ColorUtils::toVec3(const xColor& color) {
@ -27,4 +31,16 @@ inline glm::vec3 ColorUtils::toVec3(const xColor& color) {
return glm::vec3(color.red * ONE_OVER_255, color.green * ONE_OVER_255, color.blue * ONE_OVER_255);
}
inline glm::vec3 ColorUtils::toLinearVec3(const glm::vec3& srgb) {
const float GAMMA_22 = 2.2f;
// Couldn't find glm::pow(vec3, vec3) ? so did it myself...
return glm::vec3(glm::pow(srgb.x, GAMMA_22), glm::pow(srgb.y, GAMMA_22), glm::pow(srgb.z, GAMMA_22));
}
inline glm::vec3 ColorUtils::toGamma22Vec3(const glm::vec3& linear) {
const float INV_GAMMA_22 = 1.0f / 2.2f;
// Couldn't find glm::pow(vec3, vec3) ? so did it myself...
return glm::vec3(glm::pow(linear.x, INV_GAMMA_22), glm::pow(linear.y, INV_GAMMA_22), glm::pow(linear.z, INV_GAMMA_22));
}
#endif // hifi_ColorUtils_h