Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KHR_materials_emissive_strength support #1441

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
1 change: 1 addition & 0 deletions indra/llprimitive/llgltfloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class gltf_render_material
double normalScale; // scale applies only to X,Y components of normal
double occlusionScale; // strength multiplier for occlusion
LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
double emissiveStrength; // multiplier for emissiveColor
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is confusing to me that it is double here but handled as F32 everywhere else, but seems like that is what we do for all the other fields so ok i guess

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was a bit weirded out by that. I'm keeping with the established convention more or less.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the GLTF spec, it does seem there are cases where single precision floating point is enforced. From the section on "Accessors Bounds":

For floating-point components, JSON-stored minimum and maximum values represent single precision floats and SHOULD be rounded to single precision before usage to avoid any potential boundary mismatches.

Not relevant to this PR, but might be worth keeping in mind for the future. cc: @RunitaiLinden

std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
double alphaMask; // alpha cut-off

Expand Down
79 changes: 79 additions & 0 deletions indra/llprimitive/llgltfmaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset";
const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation";


const char *const LLGLTFMaterial::GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH = "KHR_materials_emissive_strength";
const char *const LLGLTFMaterial::GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH_EMISSIVE_STRENGTH = "emissiveStrength";

// special UUID that indicates a null UUID in override data
const LLUUID LLGLTFMaterial::GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff");

Expand Down Expand Up @@ -111,6 +115,7 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)

mBaseColor = rhs.mBaseColor;
mEmissiveColor = rhs.mEmissiveColor;
mEmissiveStrength = rhs.mEmissiveStrength;

mMetallicFactor = rhs.mMetallicFactor;
mRoughnessFactor = rhs.mRoughnessFactor;
Expand Down Expand Up @@ -162,6 +167,7 @@ bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const
mBaseColor == rhs.mBaseColor &&
mEmissiveColor == rhs.mEmissiveColor &&

mEmissiveStrength == rhs.mEmissiveStrength &&
mMetallicFactor == rhs.mMetallicFactor &&
mRoughnessFactor == rhs.mRoughnessFactor &&
mAlphaCutoff == rhs.mAlphaCutoff &&
Expand Down Expand Up @@ -208,6 +214,27 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const
return str.str();
}

// static
void LLGLTFMaterial::setEmissiveStrengthFromModel(const tinygltf::Material& model, F32& emissive_strength)
{
LL_PROFILE_ZONE_SCOPED;

const tinygltf::Value::Object &extensions_object = model.extensions;
const auto emissive_it = extensions_object.find(GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH);

LL_INFOS() << "Material extensions: " << model.extensions_json_string << LL_ENDL;
Geenz marked this conversation as resolved.
Show resolved Hide resolved
Geenz marked this conversation as resolved.
Show resolved Hide resolved

if (emissive_it != extensions_object.end())
{
const tinygltf::Value &emissive_strength_json = std::get<1>(*emissive_it);
if (emissive_strength_json.IsObject())
{
const tinygltf::Value::Object &emissive_object = emissive_strength_json.Get<tinygltf::Value::Object>();
emissive_strength = floatFromJson(emissive_object, GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH_EMISSIVE_STRENGTH, getDefaultEmissiveStrength());
}
}
}

void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
{
LL_PROFILE_ZONE_SCOPED;
Expand All @@ -227,6 +254,9 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)
// Apply emissive texture
setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE);

// KHR_materials_emissive_strength
setEmissiveStrengthFromModel(material_in, mEmissiveStrength);

setAlphaMode(material_in.alphaMode);
mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f);

Expand Down Expand Up @@ -297,6 +327,14 @@ F32 LLGLTFMaterial::floatFromJson(const tinygltf::Value::Object& object, const c
return (F32)real_json.GetNumberAsDouble();
}

// static
void LLGLTFMaterial::writeEmissiveStrength(tinygltf::Material &material, F32 emissive_strength)
{
tinygltf::Value::Object emissive_strength_object;
emissive_strength_object[LLGLTFMaterial::GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH_EMISSIVE_STRENGTH] = tinygltf::Value(emissive_strength);
material.extensions[LLGLTFMaterial::GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH_EMISSIVE_STRENGTH] = tinygltf::Value(emissive_strength_object);
Geenz marked this conversation as resolved.
Show resolved Hide resolved
}

void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
{
LL_PROFILE_ZONE_SCOPED;
Expand Down Expand Up @@ -332,6 +370,8 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const
mEmissiveColor.write(material_out.emissiveFactor);
}

writeEmissiveStrength(material_out, mEmissiveStrength);

material_out.pbrMetallicRoughness.metallicFactor = mMetallicFactor;
material_out.pbrMetallicRoughness.roughnessFactor = mRoughnessFactor;

Expand Down Expand Up @@ -465,6 +505,19 @@ void LLGLTFMaterial::setEmissiveColorFactor(const LLColor3& emissiveColor, bool
}
}

void LLGLTFMaterial::setEmissiveStrength(F32 emissiveStrength, bool for_override)
{
// KHR_materials_emissive_strength only allows positive values. There is no maximum value.
mEmissiveStrength = llmax(emissiveStrength, 0.f);
if (for_override)
{
if (mEmissiveStrength == getDefaultEmissiveStrength())
{
mEmissiveStrength -= FLT_EPSILON;
}
}
}

void LLGLTFMaterial::setMetallicFactor(F32 metallic, bool for_override)
{
mMetallicFactor = llclamp(metallic, 0.f, for_override ? 1.f - FLT_EPSILON : 1.f);
Expand Down Expand Up @@ -564,6 +617,11 @@ LLColor3 LLGLTFMaterial::getDefaultEmissiveColor()
return sDefault.mEmissiveColor;
}

F32 LLGLTFMaterial::getDefaultEmissiveStrength()
{
return sDefault.mEmissiveStrength;
}

bool LLGLTFMaterial::getDefaultDoubleSided()
{
return sDefault.mDoubleSided;
Expand Down Expand Up @@ -621,6 +679,11 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)
mEmissiveColor = override_mat.mEmissiveColor;
}

if (override_mat.mEmissiveStrength != getDefaultEmissiveStrength())
{
mEmissiveStrength = override_mat.mEmissiveStrength;
}

if (override_mat.mMetallicFactor != getDefaultMetallicFactor())
{
mMetallicFactor = override_mat.mMetallicFactor;
Expand Down Expand Up @@ -698,6 +761,11 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d
{
data["ec"] = override_mat.mEmissiveColor.getValue();
}

if (override_mat.mEmissiveStrength != getDefaultEmissiveStrength())
{
data["es"] = override_mat.mEmissiveStrength;
}

if (override_mat.mMetallicFactor != getDefaultMetallicFactor())
{
Expand Down Expand Up @@ -777,6 +845,17 @@ void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data)
mEmissiveColor.mV[0] += FLT_EPSILON;
}
}

const LLSD &es = data["es"];
if (es.isDefined())
{
mEmissiveStrength = es.asReal();
if (mEmissiveStrength == getDefaultEmissiveStrength())
{
// HACK -- nudge by epsilon if we receive a default value (indicates override to default)
mEmissiveStrength -= FLT_EPSILON;
}
}

const LLSD& mf = data["mf"];
if (mf.isReal())
Expand Down
23 changes: 17 additions & 6 deletions indra/llprimitive/llgltfmaterial.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace tinygltf
class Model;
struct TextureInfo;
class Value;
struct Material;
}

class LLTextureEntry;
Expand Down Expand Up @@ -100,6 +101,11 @@ class LLGLTFMaterial : public LLRefCount
// -Cosmic,2023-01-26
GLTF_TEXTURE_INFO_OCCLUSION = GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
GLTF_TEXTURE_INFO_EMISSIVE,
GLTF_TEXTURE_INFO_TRANSMISSION_TEXTURE,
// Geenz: The GLTF spec for KHR_materials_transmission states that the red channel of the transmission texture defines the
// transmission factor, but the spec does not define what the green and blue channels are for. We are using the green channel to
// define the thickness of the object, as the spec defines the green channel of the volume extension as thickness in KHR_materials_volume.
GLTF_TEXTURE_INFO_THICKNESS_TEXTURE = GLTF_TEXTURE_INFO_TRANSMISSION_TEXTURE,

GLTF_TEXTURE_INFO_COUNT
};
Expand All @@ -110,6 +116,10 @@ class LLGLTFMaterial : public LLRefCount
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION;
static const LLUUID GLTF_OVERRIDE_NULL_UUID;


static const char *const GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH;
static const char *const GLTF_FILE_EXTENSION_EMISSIVE_STRENGTH_EMISSIVE_STRENGTH;

// *TODO: If/when we implement additional GLTF extensions, they may not be
// compatible with our GLTF terrain implementation. We may want to disallow
// materials with some features from being set on terrain, if their
Expand All @@ -120,12 +130,6 @@ class LLGLTFMaterial : public LLRefCount
// heightmaps cannot currently be described as finite enclosed
// volumes.
// See also LLPanelRegionTerrainInfo::validateMaterials
bool mDoubleSided = false;


// These fields are local to viewer and are a part of local bitmap support
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndrewMeadows changed the order of the fields to save some bits. That's relevant to resolving this merge conflict. You may be interested in choosing a location for mEmissiveStrength to optimize the packing (although the savings may only be relevant server-side)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - I wasn't sure what the specific ordering was supposed to be here. I'll look at the git-blame and reorder as needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I restored the packing from the previous merge - I'm generally assuming there's a very good reason for it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grokking this further, it appears there's a comment/warning further down that LLGLTFMaterial::getHash uses mLocalTexDataDigest to determine the hash offset of the material object. (see "IMPORTANT: do not move this member down") Any fields prior to mLocalTexDataDigest will not get included in the hash. I didn't consider this before, but this probably takes precedence over @AndrewMeadows ' size optimizations.

This also would explain why the merge broke. There was a fix to GLTF hashing (and therefore render batching) in a maintenance branch.


public:

Expand All @@ -145,6 +149,7 @@ class LLGLTFMaterial : public LLRefCount
void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false);
void setAlphaCutoff(F32 cutoff, bool for_override = false);
void setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override = false);
void setEmissiveStrength(F32 emissiveStrength, bool for_override = false);
void setMetallicFactor(F32 metallic, bool for_override = false);
void setRoughnessFactor(F32 roughness, bool for_override = false);
void setAlphaMode(S32 mode, bool for_override = false);
Expand All @@ -163,6 +168,7 @@ class LLGLTFMaterial : public LLRefCount
static F32 getDefaultRoughnessFactor();
static LLColor4 getDefaultBaseColor();
static LLColor3 getDefaultEmissiveColor();
static F32 getDefaultEmissiveStrength();
static bool getDefaultDoubleSided();
static LLVector2 getDefaultTextureOffset();
static LLVector2 getDefaultTextureScale();
Expand Down Expand Up @@ -228,6 +234,10 @@ class LLGLTFMaterial : public LLRefCount
bool hasLocalTextures() { return !mTrackingIdToLocalTexture.empty(); }
virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id);
virtual void updateTextureTracking();

static void writeEmissiveStrength(tinygltf::Material &material, F32 emissive_strength);
static void setEmissiveStrengthFromModel(const tinygltf::Material &model, F32 &emissiveStrength);

protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
Expand Down Expand Up @@ -269,6 +279,7 @@ class LLGLTFMaterial : public LLRefCount
// NOTE: these values should be in linear color space
LLColor4 mBaseColor;
LLColor3 mEmissiveColor;
F32 mEmissiveStrength = 1.0f;

F32 mMetallicFactor;
F32 mRoughnessFactor;
Expand Down
11 changes: 11 additions & 0 deletions indra/newview/app_settings/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9153,6 +9153,17 @@
<real>0.00</real>
</array>
</map>
<key>RenderTransmissionDetail</key>
Geenz marked this conversation as resolved.
Show resolved Hide resolved
<map>
<key>Comment</key>
<string>Controls the quality level of transmissive materials 0 is thin-film non-refractive transmission. 1 is basic refraction. 2 is "glossy" refraction.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>RenderMirrors</key>
<map>
<key>Comment</key>
Expand Down
2 changes: 1 addition & 1 deletion indra/newview/lldrawpoolterrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials)
base_color_factors[i] = material->mBaseColor;
metallic_factors[i] = material->mMetallicFactor;
roughness_factors[i] = material->mRoughnessFactor;
emissive_colors[i] = material->mEmissiveColor;
emissive_colors[i] = material->mEmissiveColor * material->mEmissiveStrength;
// glTF 2.0 Specification 3.9.4. Alpha Coverage
// mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK
// Use 0 here due to GLTF terrain blending (LLGLTFMaterial::bind uses
Expand Down
2 changes: 1 addition & 1 deletion indra/newview/llfetchedgltfmaterial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex)

shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor);
shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor);
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV);
shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, (mEmissiveColor * mEmissiveStrength).mV);

F32 normal_packed[8];
mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
Expand Down
36 changes: 36 additions & 0 deletions indra/newview/llmaterialeditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ static const U32 MATERIAL_DOUBLE_SIDED_DIRTY = 0x1 << 8;
static const U32 MATERIAL_ALPHA_MODE_DIRTY = 0x1 << 9;
static const U32 MATERIAL_ALPHA_CUTOFF_DIRTY = 0x1 << 10;

static const U32 MATERIAL_EMISSSIVE_STRENGTH_DIRTY = 0x1 << 11;

LLUUID LLMaterialEditor::mOverrideObjectId;
S32 LLMaterialEditor::mOverrideObjectTE = -1;
bool LLMaterialEditor::mOverrideInProgress = false;
Expand Down Expand Up @@ -763,6 +765,16 @@ void LLMaterialEditor::setEmissiveColor(const LLColor4& color)
mEmissiveColorCtrl->setValue(srgbColor4(color).getValue());
}

F32 LLMaterialEditor::getEmissiveStrength()
{
return childGetValue("emissive strength").asReal();
}

void LLMaterialEditor::setEmissiveStrength(F32 strength)
{
childSetValue("emissive strength", strength);
}

LLUUID LLMaterialEditor::getNormalId()
{
return mNormalTextureCtrl->getValue().asUUID();
Expand Down Expand Up @@ -1174,6 +1186,13 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_
nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveColorFactor(LLColor3(mCtrl->getValue()), true);
break;
}

case MATERIAL_EMISSSIVE_STRENGTH_DIRTY:
{
nodep->mSavedGLTFOverrideMaterials[te]->setEmissiveStrength(mCtrl->getValue().asReal(), true);
break;
}

default:
break;
}
Expand Down Expand Up @@ -2315,6 +2334,7 @@ void LLMaterialEditor::saveObjectsMaterialAs(const LLGLTFMaterial* render_materi
me->setMetalnessFactor(render_material->mMetallicFactor);
me->setRoughnessFactor(render_material->mRoughnessFactor);
me->setEmissiveColor(render_material->mEmissiveColor);
me->setEmissiveStrength(render_material->mEmissiveStrength);
me->setDoubleSided(render_material->mDoubleSided);
me->setAlphaMode(render_material->getAlphaMode());
me->setAlphaCutoff(render_material->mAlphaCutoff);
Expand Down Expand Up @@ -2604,6 +2624,11 @@ bool LLMaterialEditor::setFromGltfModel(const tinygltf::Model& model, S32 index,

setBaseColor(LLTinyGLTFHelper::getColor(material_in.pbrMetallicRoughness.baseColorFactor));
setEmissiveColor(LLTinyGLTFHelper::getColor(material_in.emissiveFactor));
F32 emissive_strength = 1.0f;

LLGLTFMaterial::setEmissiveStrengthFromModel(material_in, emissive_strength);

setEmissiveStrength(emissive_strength);

setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor);
setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor);
Expand Down Expand Up @@ -3040,6 +3065,15 @@ class LLRenderMaterialOverrideFunctor : public LLSelectedNodeFunctor
material->setEmissiveColorFactor(revert_mat->mEmissiveColor, false);
}

if (changed_flags & MATERIAL_EMISSSIVE_STRENGTH_DIRTY)
{
material->setEmissiveStrength(mEditor->getEmissiveStrength(), true);
}
else if ((reverted_flags & MATERIAL_EMISSSIVE_STRENGTH_DIRTY) && revert_mat.notNull())
{
material->setEmissiveStrength(revert_mat->mEmissiveStrength, false);
}

if (changed_flags & MATERIAL_EMISIVE_TEX_DIRTY)
{
material->setEmissiveId(mEditor->getEmissiveId(), true);
Expand Down Expand Up @@ -3186,6 +3220,7 @@ void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)

mat->mEmissiveColor = getEmissiveColor();
mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = getEmissiveId();
mat->mEmissiveStrength = getEmissiveStrength();

mat->mDoubleSided = getDoubleSided();
mat->setAlphaMode(getAlphaMode());
Expand All @@ -3204,6 +3239,7 @@ void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)

setEmissiveColor(mat->mEmissiveColor);
setEmissiveId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);
setEmissiveStrength(mat->mEmissiveStrength);

setDoubleSided(mat->mDoubleSided);
setAlphaMode(mat->getAlphaMode());
Expand Down
3 changes: 3 additions & 0 deletions indra/newview/llmaterialeditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
LLColor4 getEmissiveColor();
void setEmissiveColor(const LLColor4& color);

F32 getEmissiveStrength();
void setEmissiveStrength(F32 strength);

LLUUID getNormalId();
void setNormalId(const LLUUID& id);
void setNormalUploadId(const LLUUID& id);
Expand Down
2 changes: 1 addition & 1 deletion indra/newview/llvlcomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
base_color_factor = LLColor3(mDetailMaterials[i]->mBaseColor);
// *HACK: Treat alpha as black
base_color_factor *= (mDetailMaterials[i]->mBaseColor.mV[VW]);
emissive_factor = mDetailMaterials[i]->mEmissiveColor;
emissive_factor = mDetailMaterials[i]->mEmissiveColor * mDetailMaterials[i]->mEmissiveStrength;
has_base_color_factor = (base_color_factor.mV[VX] != 1.f ||
base_color_factor.mV[VY] != 1.f ||
base_color_factor.mV[VZ] != 1.f);
Expand Down
Loading
Loading