mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 16:26:17 +02:00
Merge pull request #7752 from Geenz/master
Correction To sRGB Conversions
This commit is contained in:
commit
eb209c7483
9 changed files with 91 additions and 34 deletions
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
glm::vec3 getColorRGB() const { return ColorUtils::toLinearVec3(toGlm(getXColor())); }
|
||||
glm::vec3 getColorRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(getXColor())); }
|
||||
|
||||
static const xColor DEFAULT_COLOR;
|
||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
||||
|
@ -62,17 +62,17 @@ public:
|
|||
bool _isColorStartInitialized = false;
|
||||
void setColorStart(const xColor& colorStart) { _colorStart = colorStart; _isColorStartInitialized = true; }
|
||||
xColor getColorStart() const { return _isColorStartInitialized ? _colorStart : getXColor(); }
|
||||
glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorStart)) : getColorRGB(); }
|
||||
glm::vec3 getColorStartRGB() const { return _isColorStartInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_colorStart)) : getColorRGB(); }
|
||||
|
||||
bool _isColorFinishInitialized = false;
|
||||
void setColorFinish(const xColor& colorFinish) { _colorFinish = colorFinish; _isColorFinishInitialized = true; }
|
||||
xColor getColorFinish() const { return _isColorFinishInitialized ? _colorFinish : getXColor(); }
|
||||
glm::vec3 getColorFinishRGB() const { return _isColorStartInitialized ? ColorUtils::toLinearVec3(toGlm(_colorFinish)) : getColorRGB(); }
|
||||
glm::vec3 getColorFinishRGB() const { return _isColorStartInitialized ? ColorUtils::sRGBToLinearVec3(toGlm(_colorFinish)) : getColorRGB(); }
|
||||
|
||||
static const xColor DEFAULT_COLOR_SPREAD;
|
||||
void setColorSpread(const xColor& colorSpread) { _colorSpread = colorSpread; }
|
||||
xColor getColorSpread() const { return _colorSpread; }
|
||||
glm::vec3 getColorSpreadRGB() const { return ColorUtils::toLinearVec3(toGlm(_colorSpread)); }
|
||||
glm::vec3 getColorSpreadRGB() const { return ColorUtils::sRGBToLinearVec3(toGlm(_colorSpread)); }
|
||||
|
||||
static const float MAXIMUM_ALPHA;
|
||||
static const float MINIMUM_ALPHA;
|
||||
|
|
|
@ -11,9 +11,14 @@
|
|||
<@if not GPU_COLOR_SLH@>
|
||||
<@def GPU_COLOR_SLH@>
|
||||
|
||||
float sRGBFloatToLinear(float value) {
|
||||
const float SRGB_ELBOW = 0.04045;
|
||||
|
||||
return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 colorToLinearRGB(vec3 srgb) {
|
||||
const float GAMMA_22 = 2.2;
|
||||
return pow(srgb, vec3(GAMMA_22));
|
||||
return vec3(sRGBFloatToLinear(srgb.r), sRGBFloatToLinear(srgb.g), sRGBFloatToLinear(srgb.b));
|
||||
}
|
||||
|
||||
vec4 colorToLinearRGBA(vec4 srgba) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
using namespace gpu;
|
||||
|
||||
const Element Element::COLOR_RGBA_32{ VEC4, NUINT8, RGBA };
|
||||
const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA };
|
||||
const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA };
|
||||
const Element Element::VEC2F_UV{ VEC2, FLOAT, UV };
|
||||
const Element Element::VEC2F_XY{ VEC2, FLOAT, XY };
|
||||
|
|
|
@ -245,6 +245,7 @@ public:
|
|||
}
|
||||
|
||||
static const Element COLOR_RGBA_32;
|
||||
static const Element COLOR_SRGBA_32;
|
||||
static const Element VEC4F_COLOR_RGBA;
|
||||
static const Element VEC2F_UV;
|
||||
static const Element VEC2F_XY;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "GPULogging.h"
|
||||
#include "Context.h"
|
||||
|
||||
#include "ColorUtils.h"
|
||||
|
||||
using namespace gpu;
|
||||
|
||||
static int TexturePointerMetaTypeId = qRegisterMetaType<TexturePointer>();
|
||||
|
@ -637,18 +639,6 @@ void SphericalHarmonics::assignPreset(int p) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 sRGBToLinear(glm::vec3& color) {
|
||||
const float GAMMA_CORRECTION = 2.2f;
|
||||
return glm::pow(color, glm::vec3(GAMMA_CORRECTION));
|
||||
}
|
||||
|
||||
glm::vec3 linearTosRGB(glm::vec3& color) {
|
||||
const float GAMMA_CORRECTION_INV = 1.0f / 2.2f;
|
||||
return glm::pow(color, glm::vec3(GAMMA_CORRECTION_INV));
|
||||
}
|
||||
|
||||
// Originial code for the Spherical Harmonics taken from "Sun and Black Cat- Igor Dykhta (igor dykhta email) <20> 2007-2014 "
|
||||
void sphericalHarmonicsAdd(float * result, int order, const float * inputA, const float * inputB) {
|
||||
const int numCoeff = order * order;
|
||||
|
@ -803,7 +793,7 @@ bool sphericalHarmonicsFromTexture(const gpu::Texture& cubeTexture, std::vector<
|
|||
float(data[pixOffsetIndex+2]) * UCHAR_TO_FLOAT);
|
||||
|
||||
// Gamma correct
|
||||
clr = sRGBToLinear(clr);
|
||||
clr = ColorUtils::sRGBToLinearVec3(clr);
|
||||
|
||||
// scale color and add to previously accumulated coefficients
|
||||
sphericalHarmonicsScale(shBuffB.data(), order,
|
||||
|
|
|
@ -65,7 +65,7 @@ Material::~Material() {
|
|||
void Material::setEmissive(const Color& emissive, bool isSRGB) {
|
||||
_key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f))));
|
||||
_schemaBuffer.edit<Schema>()._key = (uint32) _key._flags.to_ulong();
|
||||
_schemaBuffer.edit<Schema>()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive);
|
||||
_schemaBuffer.edit<Schema>()._emissive = (isSRGB ? ColorUtils::sRGBToLinearVec3(emissive) : emissive);
|
||||
}
|
||||
|
||||
void Material::setOpacity(float opacity) {
|
||||
|
@ -77,7 +77,7 @@ void Material::setOpacity(float opacity) {
|
|||
void Material::setAlbedo(const Color& albedo, bool isSRGB) {
|
||||
_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f))));
|
||||
_schemaBuffer.edit<Schema>()._key = (uint32)_key._flags.to_ulong();
|
||||
_schemaBuffer.edit<Schema>()._albedo = (isSRGB ? ColorUtils::toLinearVec3(albedo) : albedo);
|
||||
_schemaBuffer.edit<Schema>()._albedo = (isSRGB ? ColorUtils::sRGBToLinearVec3(albedo) : albedo);
|
||||
}
|
||||
|
||||
void Material::setRoughness(float roughness) {
|
||||
|
@ -89,7 +89,7 @@ void Material::setRoughness(float roughness) {
|
|||
|
||||
void Material::setFresnel(const Color& fresnel, bool isSRGB) {
|
||||
//_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f))));
|
||||
_schemaBuffer.edit<Schema>()._fresnel = (isSRGB ? ColorUtils::toLinearVec3(fresnel) : fresnel);
|
||||
_schemaBuffer.edit<Schema>()._fresnel = (isSRGB ? ColorUtils::sRGBToLinearVec3(fresnel) : fresnel);
|
||||
}
|
||||
|
||||
void Material::setMetallic(float metallic) {
|
||||
|
|
|
@ -245,16 +245,16 @@ public:
|
|||
const MaterialKey& getKey() const { return _key; }
|
||||
|
||||
void setEmissive(const Color& emissive, bool isSRGB = true);
|
||||
Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._emissive) : _schemaBuffer.get<Schema>()._emissive); }
|
||||
Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get<Schema>()._emissive) : _schemaBuffer.get<Schema>()._emissive); }
|
||||
|
||||
void setOpacity(float opacity);
|
||||
float getOpacity() const { return _schemaBuffer.get<Schema>()._opacity; }
|
||||
|
||||
void setAlbedo(const Color& albedo, bool isSRGB = true);
|
||||
Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._albedo) : _schemaBuffer.get<Schema>()._albedo); }
|
||||
Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get<Schema>()._albedo) : _schemaBuffer.get<Schema>()._albedo); }
|
||||
|
||||
void setFresnel(const Color& fresnel, bool isSRGB = true);
|
||||
Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get<Schema>()._fresnel) : _schemaBuffer.get<Schema>()._fresnel); }
|
||||
Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get<Schema>()._fresnel) : _schemaBuffer.get<Schema>()._fresnel); }
|
||||
|
||||
void setMetallic(float metallic);
|
||||
float getMetallic() const { return _schemaBuffer.get<Schema>()._metallic; }
|
||||
|
|
|
@ -363,7 +363,7 @@ void Font::drawString(gpu::Batch& batch, float x, float y, const QString& str, c
|
|||
batch._glUniform1i(_outlineLoc, (effectType == OUTLINE_EFFECT));
|
||||
|
||||
// need the gamma corrected color here
|
||||
glm::vec4 lrgba = glm::vec4(ColorUtils::toLinearVec3(glm::vec3(*color)), color->a);
|
||||
glm::vec4 lrgba = ColorUtils::sRGBToLinearVec4(*color);
|
||||
batch._glUniform4fv(_colorLoc, 1, (const float*)&lrgba);
|
||||
|
||||
batch.setInputFormat(_format);
|
||||
|
|
|
@ -21,9 +21,19 @@ 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);
|
||||
// Convert to gamma 2.2 space from linear
|
||||
inline static glm::vec3 toGamma22Vec3(const glm::vec3& linear);
|
||||
|
||||
// Convert from sRGB gamma space to linear.
|
||||
// This is pretty different from converting from 2.2.
|
||||
inline static glm::vec3 sRGBToLinearVec3(const glm::vec3& srgb);
|
||||
inline static glm::vec3 tosRGBVec3(const glm::vec3& srgb);
|
||||
|
||||
inline static glm::vec4 sRGBToLinearVec4(const glm::vec4& srgb);
|
||||
inline static glm::vec4 tosRGBVec4(const glm::vec4& srgb);
|
||||
|
||||
inline static float sRGBToLinearFloat(const float& srgb);
|
||||
inline static float tosRGBFloat(const float& linear);
|
||||
};
|
||||
|
||||
inline glm::vec3 ColorUtils::toVec3(const xColor& color) {
|
||||
|
@ -31,16 +41,66 @@ 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));
|
||||
}
|
||||
|
||||
// Convert from sRGB color space to linear color space.
|
||||
inline glm::vec3 ColorUtils::sRGBToLinearVec3(const glm::vec3& srgb) {
|
||||
return glm::vec3(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z));
|
||||
}
|
||||
|
||||
// Convert from linear color space to sRGB color space.
|
||||
inline glm::vec3 ColorUtils::tosRGBVec3(const glm::vec3& linear) {
|
||||
return glm::vec3(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z));
|
||||
}
|
||||
|
||||
// Convert from sRGB color space with alpha to linear color space with alpha.
|
||||
inline glm::vec4 ColorUtils::sRGBToLinearVec4(const glm::vec4& srgb) {
|
||||
return glm::vec4(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z), srgb.w);
|
||||
}
|
||||
|
||||
// Convert from linear color space with alpha to sRGB color space with alpha.
|
||||
inline glm::vec4 ColorUtils::tosRGBVec4(const glm::vec4& linear) {
|
||||
return glm::vec4(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z), linear.w);
|
||||
}
|
||||
|
||||
// This is based upon the conversions found in section 8.24 of the OpenGL 4.4 4.4 specification.
|
||||
// glm::pow(color, 2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers.
|
||||
inline float ColorUtils::sRGBToLinearFloat(const float &srgb) {
|
||||
const float SRGB_ELBOW = 0.04045f;
|
||||
float linearValue = 0.0f;
|
||||
|
||||
// This should mirror the conversion table found in section 8.24: sRGB Texture Color Conversion
|
||||
if (srgb <= SRGB_ELBOW) {
|
||||
linearValue = srgb / 12.92f;
|
||||
} else {
|
||||
linearValue = powf(((srgb + 0.055f) / 1.055f), 2.4f);
|
||||
}
|
||||
|
||||
return linearValue;
|
||||
}
|
||||
|
||||
// This is based upon the conversions found in section 17.3.9 of the OpenGL 4.4 specification.
|
||||
// glm::pow(color, 1.0f/2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers.
|
||||
inline float ColorUtils::tosRGBFloat(const float &linear) {
|
||||
const float SRGB_ELBOW_INV = 0.0031308f;
|
||||
float sRGBValue = 0.0f;
|
||||
|
||||
// This should mirror the conversion table found in section 17.3.9: sRGB Conversion
|
||||
if (linear <= 0.0f) {
|
||||
sRGBValue = 0.0f;
|
||||
} else if (0 < linear && linear < SRGB_ELBOW_INV) {
|
||||
sRGBValue = 12.92f * linear;
|
||||
} else if (SRGB_ELBOW_INV <= linear && linear < 1) {
|
||||
sRGBValue = 1.055f * powf(linear, 0.41666f - 0.055f);
|
||||
} else {
|
||||
sRGBValue = 1.0f;
|
||||
}
|
||||
|
||||
return sRGBValue;
|
||||
}
|
||||
|
||||
#endif // hifi_ColorUtils_h
|
Loading…
Reference in a new issue