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
566 changes: 566 additions & 0 deletions indra/llprimitive/llgltfmaterial.cpp

Large diffs are not rendered by default.

77 changes: 70 additions & 7 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 @@ -105,6 +106,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 @@ -114,6 +120,25 @@ class LLGLTFMaterial : public LLRefCount
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET;
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;

static const char *const GLTF_FILE_EXTENSION_TRANSMISSION;
static const char *const GLTF_FILE_EXTENSION_TRANSMISSION_TRANSMISSION_FACTOR;
static const char *const GLTF_FILE_EXTENSION_TRANSMISSION_TEXTURE;

static const char *const GLTF_FILE_EXTENSION_IOR;
static const char *const GLTF_FILE_EXTENSION_IOR_IOR;

static const char *const GLTF_FILE_EXTENSION_VOLUME;
static const char *const GLTF_FILE_EXTENSION_VOLUME_THICKNESS_FACTOR;
static const char *const GLTF_FILE_EXTENSION_VOLUME_THICKNESS_TEXTURE;
static const char *const GLTF_FILE_EXTENSION_VOLUME_ATTENUATION_DISTANCE;
static const char *const GLTF_FILE_EXTENSION_VOLUME_ATTENUATION_COLOR;

static const char *const GLTF_FILE_EXTENSION_DISPERSION;
static const char *const GLTF_FILE_EXTENSION_DISPERSION_DISPERSION;

// *TODO: If/when we implement additional GLTF extensions, they may not be
// compatible with our GLTF terrain implementation. We may want to disallow
Expand All @@ -125,26 +150,39 @@ class LLGLTFMaterial : public LLRefCount
// heightmaps cannot currently be described as finite enclosed
// volumes.
// See also LLPanelRegionTerrainInfo::validateMaterials

bool mDoubleSided = false;
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;

public:

// get a UUID based on a hash of this LLGLTFMaterial
LLUUID getHash() const;

//setters for various members (will clamp to acceptable ranges)
// for_override - set to true if this value is being set as part of an override (important for handling override to default value)
// for_override - set to true if this value is being set as part of an override (important for handling override to default value)x1

void setTextureId(TextureInfo texture_info, const LLUUID& id, bool for_override = false);

void setBaseColorId(const LLUUID& id, bool for_override = false);
void setNormalId(const LLUUID& id, bool for_override = false);
void setOcclusionRoughnessMetallicId(const LLUUID& id, bool for_override = false);
void setEmissiveId(const LLUUID& id, bool for_override = false);
void setEmissiveId(const LLUUID &id, bool for_override = false);
void setTransmissionId(const LLUUID &id, bool for_override = false);

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 setTransmissionFactor(F32 transmission, bool for_override = false);
void setIOR(F32 ior, bool for_override = false);
void setThicknessFactor(F32 thickness, bool for_override = false);
void setAttenuationDistance(F32 attenuationDistance, bool for_override = false);
void setAttenuationColor(const LLColor3& attenuationColor, bool for_override = false);
void setDispersion(F32 dispersion, bool for_override = false);
void setAlphaMode(S32 mode, bool for_override = false);
void setDoubleSided(bool double_sided, bool for_override = false);

Expand All @@ -159,8 +197,15 @@ class LLGLTFMaterial : public LLRefCount
static S32 getDefaultAlphaMode();
static F32 getDefaultMetallicFactor();
static F32 getDefaultRoughnessFactor();
static F32 getDefaultTransmissionFactor();
static F32 getDefaultIOR();
static F32 getDefaultThicknessFactor();
static F32 getDefaultAttenuationDistance();
static LLColor3 getDefaultAttenuationColor();
static F32 getDefaultDispersion();
static LLColor4 getDefaultBaseColor();
static LLColor3 getDefaultEmissiveColor();
static F32 getDefaultEmissiveStrength();
static bool getDefaultDoubleSided();
static LLVector2 getDefaultTextureOffset();
static LLVector2 getDefaultTextureScale();
Expand Down Expand Up @@ -226,8 +271,22 @@ 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 writeFloatToMaterialWithExtension(tinygltf::Material &material, const char *extension, const char *key, F32 value);
static void setFloatFromModelWithExtension(const tinygltf::Material &model, const char *extension, const char *key, F32 &value, F32 defaultValue);

static void writeColor3ToMaterialWithExtension(tinygltf::Material &material, const char *extension, const char *key, const LLColor3 &color);
static void setColor3FromMaterialWithExtension(const tinygltf::Material &model, const char *extension, const char *key, LLColor3 &color,
LLColor3 defaultColor);

static void writeTextureToMaterialWithExtension(tinygltf::Material &material, const char *extension, const char *key,
const tinygltf::TextureInfo &texture_info);
static void setTextureFromMaterialWithExtension(const tinygltf::Material &model, const char *extension, const char *key,
tinygltf::TextureInfo &texture_info);

protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static LLColor3 color3FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLColor3& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);

template<typename T>
Expand All @@ -236,7 +295,7 @@ class LLGLTFMaterial : public LLRefCount
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id);
template<typename T>
static void setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform);
static void setFromTexture(const tinygltf::Model &model, const T &texture_info, LLUUID &texture_id, TextureTransform &transform);

template<typename T>
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
Expand All @@ -253,8 +312,6 @@ class LLGLTFMaterial : public LLRefCount
// IMPORTANT: do not move this member down (and do not move
// mLocalTexDataDigest either): the getHash() method does rely on the
// current ordering. HB
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;

// Used to store a digest of mTrackingIdToLocalTexture when the latter is
// not empty, or zero otherwise. HB
Expand All @@ -267,14 +324,20 @@ 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;
F32 mAlphaCutoff;

F32 mTransmissionFactor = 0.0f;
F32 mIOR = 1.5f;
F32 mThicknessFactor = 0.0f;
F32 mAttenuationDistance = INFINITY;
LLColor3 mAttenuationColor = LLColor3::white;
F32 mDispersion = 0.0f;

AlphaMode mAlphaMode;

bool mDoubleSided = false;

// Override specific flags for state that can't use off-by-epsilon or UUID
// hack
Expand Down
12 changes: 10 additions & 2 deletions indra/llprimitive/tests/llgltfmaterial_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ namespace tut
material.setNormalId(LLUUID::generateNewID());
material.setOcclusionRoughnessMetallicId(LLUUID::generateNewID());
material.setEmissiveId(LLUUID::generateNewID());
material.setTransmissionId(LLUUID::generateNewID());
}

void apply_test_material_texture_transforms(LLGLTFMaterial& material)
Expand All @@ -96,6 +97,13 @@ namespace tut
material.setEmissiveColorFactor(LLColor3(test_fraction_big, test_fraction_big, test_fraction_big));
material.setMetallicFactor(test_fraction);
material.setRoughnessFactor(test_fraction);
material.setEmissiveStrength(test_fraction);
material.setTransmissionFactor(test_fraction);
material.setAttenuationColor(LLColor3(test_fraction_big, test_fraction_big, test_fraction_big));
material.setAttenuationDistance(test_fraction);
material.setDispersion(test_fraction);
material.setThicknessFactor(test_fraction);
material.setIOR(test_fraction);
}

LLGLTFMaterial create_test_material()
Expand Down Expand Up @@ -145,10 +153,10 @@ namespace tut
#if LL_WINDOWS
// If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial)
// This test result will vary between compilers, so only test a single platform
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 232);
ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 312);
#endif
#endif
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4);
ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 5);
}

// Test that occlusion and metallicRoughness are the same (They are different for asset validation. See lluploadmaterial.cpp)
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 @@ -502,7 +502,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 @@ -128,7 +128,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 @@ -721,7 +721,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
base_color_factor = LLColor3(mat->mBaseColor);
// *HACK: Treat alpha as black
base_color_factor *= (mat->mBaseColor.mV[VW]);
emissive_factor = mat->mEmissiveColor;
emissive_factor = mat->mEmissiveColor * mat->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
1 change: 1 addition & 0 deletions indra/newview/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,7 @@ class LLPipeline
static bool RenderMirrors;
static S32 RenderHeroProbeUpdateRate;
static S32 RenderHeroProbeConservativeUpdateMultiplier;
static S32 RenderTransmissionDetail;
};

void render_bbox(const LLVector3 &min, const LLVector3 &max);
Expand Down
25 changes: 25 additions & 0 deletions indra/newview/skins/default/xui/en/panel_gltf_material.xml
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,31 @@
top_pad="5"
name="emissive color"
width="40" />
<text
type="string"
length="1"
follows="left|top"
height="10"
layout="topleft"
left_delta="0"
top_pad="5"
width="96"
name="emissive_strength_lbl">
Emissive Strength
</text>
<spinner
decimal_digits="3"
Geenz marked this conversation as resolved.
Show resolved Hide resolved
follows="left|top"
height="19"
increment="0.01"
initial_value="0"
layout="topleft"
left_delta="0"
top_pad="5"
min_val="0"
max_val="9999"
name="emissive strength"
width="64"/>
</panel>
<panel
border="true"
Expand Down
Loading