Merge branch 'release/materials_featurette' of https://github.com/secondlife/viewer
# Conflicts: # indra/newview/app_settings/settings.xml # indra/newview/llpanelface.h # indra/newview/pipeline.cpp # indra/newview/skins/default/xui/en/floater_tools.xmlmaster
commit
62ffcf193d
|
|
@ -601,7 +601,7 @@ void LLPluginProcessParent::idle(void)
|
|||
params.args.add("-e");
|
||||
params.args.add("tell application \"Terminal\"");
|
||||
params.args.add("-e");
|
||||
params.args.add(STRINGIZE("set win to do script \"gdb -pid "
|
||||
params.args.add(STRINGIZE("set win to do script \"lldb -pid "
|
||||
<< mProcess->getProcessID() << "\""));
|
||||
params.args.add("-e");
|
||||
params.args.add("do script \"continue\" in win");
|
||||
|
|
|
|||
|
|
@ -1839,6 +1839,40 @@ bool LLLightParams::fromLLSD(LLSD& sd)
|
|||
|
||||
//============================================================================
|
||||
|
||||
LLMirrorParams::LLMirrorParams()
|
||||
{
|
||||
mType = PARAMS_MIRROR;
|
||||
}
|
||||
|
||||
BOOL LLMirrorParams::pack(LLDataPacker &dp) const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLMirrorParams::unpack(LLDataPacker &dp)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool LLMirrorParams::operator==(const LLNetworkData& data) const
|
||||
{
|
||||
if (data.mType != PARAMS_REFLECTION_PROBE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLMirrorParams::copy(const LLNetworkData& data)
|
||||
{
|
||||
const LLMirrorParams *param = (LLMirrorParams*)&data;
|
||||
mType = param->mType;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLReflectionProbeParams::LLReflectionProbeParams()
|
||||
{
|
||||
mType = PARAMS_REFLECTION_PROBE;
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ public:
|
|||
PARAMS_EXTENDED_MESH = 0x70,
|
||||
PARAMS_RENDER_MATERIAL = 0x80,
|
||||
PARAMS_REFLECTION_PROBE = 0x90,
|
||||
PARAMS_MIRROR = 0x100,
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -180,6 +181,16 @@ public:
|
|||
F32 getCutoff() const { return mCutoff; }
|
||||
};
|
||||
|
||||
class LLMirrorParams : public LLNetworkData
|
||||
{
|
||||
public:
|
||||
LLMirrorParams();
|
||||
/*virtual*/ BOOL pack(LLDataPacker &dp) const;
|
||||
/*virtual*/ BOOL unpack(LLDataPacker &dp);
|
||||
/*virtual*/ bool operator==(const LLNetworkData& data) const;
|
||||
/*virtual*/ void copy(const LLNetworkData& data);
|
||||
};
|
||||
|
||||
extern const F32 REFLECTION_PROBE_MIN_AMBIANCE;
|
||||
extern const F32 REFLECTION_PROBE_MAX_AMBIANCE;
|
||||
extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE;
|
||||
|
|
|
|||
|
|
@ -685,6 +685,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
|
|||
mMaterialUpdatePending = true;
|
||||
}
|
||||
mMaterial = pMaterialParams;
|
||||
|
||||
return TEM_CHANGE_TEXTURE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public:
|
|||
S32 setGlow(F32 glow);
|
||||
S32 setMaterialID(const LLMaterialID& pMaterialID);
|
||||
S32 setMaterialParams(const LLMaterialPtr pMaterialParams);
|
||||
|
||||
|
||||
virtual const LLUUID &getID() const { return mID; }
|
||||
const LLColor4 &getColor() const { return mColor; }
|
||||
const F32 getAlpha() const { return mColor.mV[VALPHA]; }
|
||||
|
|
|
|||
|
|
@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const
|
|||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
S32 index = mTexture[uniform];
|
||||
if (index != -1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ public:
|
|||
bool hasAlphaMask = false;
|
||||
bool hasReflectionProbes = false;
|
||||
bool attachNothing = false;
|
||||
bool isPBRTerrain = false; // include: shaders\class1\deferred\pbrterrainUtilF.glsl
|
||||
bool hasHeroProbes = false;
|
||||
bool isPBRTerrain = false;
|
||||
};
|
||||
|
||||
// ============= Structure for caching shader uniforms ===============
|
||||
|
|
|
|||
|
|
@ -224,6 +224,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (features->hasHeroProbes)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl"))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (features->hasShadows)
|
||||
{
|
||||
|
|
@ -601,6 +609,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2
|
||||
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
|
||||
|
||||
if (defines)
|
||||
|
|
@ -1206,6 +1215,9 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("emissiveColor");
|
||||
mReservedUniforms.push_back("metallicFactor");
|
||||
mReservedUniforms.push_back("roughnessFactor");
|
||||
mReservedUniforms.push_back("mirror_flag");
|
||||
mReservedUniforms.push_back("clipPlane");
|
||||
mReservedUniforms.push_back("clipSign");
|
||||
|
||||
mReservedUniforms.push_back("diffuseMap");
|
||||
mReservedUniforms.push_back("altDiffuseMap");
|
||||
|
|
@ -1218,6 +1230,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("sceneDepth");
|
||||
mReservedUniforms.push_back("reflectionProbes");
|
||||
mReservedUniforms.push_back("irradianceProbes");
|
||||
mReservedUniforms.push_back("heroProbes");
|
||||
mReservedUniforms.push_back("cloud_noise_texture");
|
||||
mReservedUniforms.push_back("cloud_noise_texture_next");
|
||||
mReservedUniforms.push_back("fullbright");
|
||||
|
|
@ -1447,6 +1460,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("cloud_variance");
|
||||
mReservedUniforms.push_back("reflection_probe_ambiance");
|
||||
mReservedUniforms.push_back("max_probe_lod");
|
||||
mReservedUniforms.push_back("probe_strength");
|
||||
|
||||
mReservedUniforms.push_back("sh_input_r");
|
||||
mReservedUniforms.push_back("sh_input_g");
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ public:
|
|||
EMISSIVE_COLOR, // "emissiveColor"
|
||||
METALLIC_FACTOR, // "metallicFactor"
|
||||
ROUGHNESS_FACTOR, // "roughnessFactor"
|
||||
MIRROR_FLAG, // "mirror_flag"
|
||||
CLIP_PLANE, // "clipPlane"
|
||||
CLIP_SIGN, // "clipSign"
|
||||
DIFFUSE_MAP, // "diffuseMap"
|
||||
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
|
||||
SPECULAR_MAP, // "specularMap"
|
||||
|
|
@ -96,6 +99,7 @@ public:
|
|||
SCENE_DEPTH, // "sceneDepth"
|
||||
REFLECTION_PROBES, // "reflectionProbes"
|
||||
IRRADIANCE_PROBES, // "irradianceProbes"
|
||||
HERO_PROBE, // "heroProbes"
|
||||
CLOUD_NOISE_MAP, // "cloud_noise_texture"
|
||||
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
|
||||
FULLBRIGHT, // "fullbright"
|
||||
|
|
@ -316,6 +320,7 @@ public:
|
|||
|
||||
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
|
||||
REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
|
||||
REFLECTION_PROBE_STRENGTH, // "probe_strength"
|
||||
SH_INPUT_L1R, // "sh_input_r"
|
||||
SH_INPUT_L1G, // "sh_input_g"
|
||||
SH_INPUT_L1B, // "sh_input_b"
|
||||
|
|
|
|||
|
|
@ -633,6 +633,7 @@ set(viewer_SOURCE_FILES
|
|||
llrecentpeople.cpp
|
||||
llreflectionmap.cpp
|
||||
llreflectionmapmanager.cpp
|
||||
llheroprobemanager.cpp
|
||||
llregioninfomodel.cpp
|
||||
llregionposition.cpp
|
||||
llremoteparcelrequest.cpp
|
||||
|
|
@ -1413,6 +1414,7 @@ set(viewer_HEADER_FILES
|
|||
llrecentpeople.h
|
||||
llreflectionmap.h
|
||||
llreflectionmapmanager.h
|
||||
llheroprobemanager.h
|
||||
llregioninfomodel.h
|
||||
llregionposition.h
|
||||
llremoteparcelrequest.h
|
||||
|
|
|
|||
|
|
@ -12150,6 +12150,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderMirrors</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Renders realtime mirrors.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderScreenSpaceReflections</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -13495,6 +13506,39 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderHeroProbeResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Resolution to render hero probes used for mirrors, water, etc.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>1024</integer>
|
||||
</map>
|
||||
<key>RenderHeroProbeDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Distance in meters for hero probes to render out to.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>16</real>
|
||||
</map>
|
||||
<key>RenderHeroProbeNearClipOffset</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Distance offset in meters for hero probes to near clip.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>2.1</real>
|
||||
</map>
|
||||
<key>RenderReflectionProbeVolumes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -13950,6 +13994,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<real>12.0</real>
|
||||
</map>
|
||||
<key>RenderTerrainPBREnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>EXPERIMENTAL: Enable PBR Terrain features. Requires restart.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderTerrainPBRDetail</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -28,25 +28,18 @@
|
|||
#define DIFFUSE_ALPHA_MODE_MASK 2
|
||||
#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
uniform mat4 modelview_matrix;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
#ifdef HAS_SKIN
|
||||
mat4 getObjectSkinnedTransform();
|
||||
#else
|
||||
uniform mat3 normal_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
#endif
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
|
||||
#if !defined(HAS_SKIN)
|
||||
uniform mat4 modelview_matrix;
|
||||
#endif
|
||||
|
||||
out vec3 vary_position;
|
||||
|
||||
#endif
|
||||
|
||||
uniform mat4 texture_matrix0;
|
||||
|
||||
in vec3 position;
|
||||
|
|
@ -133,10 +126,8 @@ void main()
|
|||
|
||||
vertex_color = diffuse_color;
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
#if !defined(HAS_SKIN)
|
||||
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
#endif
|
||||
vary_position = (projection_matrix*vec4(position.xyz, 1.0)).xyz;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,37 @@ vec2 encode_normal(vec3 n);
|
|||
vec3 linear_to_srgb(vec3 c);
|
||||
vec3 srgb_to_linear(vec3 c);
|
||||
|
||||
uniform vec4 clipPlane;
|
||||
uniform float clipSign;
|
||||
uniform float mirror_flag;
|
||||
void applyClip(vec3 pos)
|
||||
{
|
||||
if (mirror_flag > 0)
|
||||
{
|
||||
// TODO: make this less branchy
|
||||
if (clipSign > 0)
|
||||
{
|
||||
if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
applyClip(vary_position);
|
||||
|
||||
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
|
||||
if (basecolor.a < minimum_alpha)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ in vec3 vary_dir;
|
|||
uniform float mipLevel;
|
||||
uniform int u_width;
|
||||
uniform float max_probe_lod;
|
||||
uniform float probe_strength;
|
||||
|
||||
|
||||
// =============================================================================================================
|
||||
|
|
@ -163,5 +164,6 @@ void main()
|
|||
{
|
||||
vec3 N = normalize(vary_dir);
|
||||
frag_color = max(prefilterEnvMap(N), vec4(0));
|
||||
frag_color.a *= probe_strength;
|
||||
}
|
||||
// =============================================================================================================
|
||||
|
|
|
|||
|
|
@ -45,6 +45,23 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
|
|||
vec3 srgb_to_linear(vec3 cs);
|
||||
vec3 linear_to_srgb(vec3 cs);
|
||||
|
||||
uniform vec4 clipPlane;
|
||||
uniform float clipSign;
|
||||
uniform float mirror_flag;
|
||||
void applyClip(vec3 pos)
|
||||
{
|
||||
float funnyClip = 0;
|
||||
if (mirror_flag > 0)
|
||||
{
|
||||
if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in vec3 vary_position;
|
||||
|
||||
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
|
||||
|
||||
out vec4 frag_color;
|
||||
|
|
@ -66,12 +83,12 @@ uniform vec4 morphFactor;
|
|||
uniform vec3 camPosLocal;
|
||||
uniform mat3 env_mat;
|
||||
|
||||
uniform float is_mirror;
|
||||
|
||||
uniform vec3 sun_dir;
|
||||
uniform vec3 moon_dir;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
in vec3 vary_position;
|
||||
|
||||
uniform mat4 proj_mat;
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
|
@ -285,6 +302,7 @@ float getShadow(vec3 pos, vec3 norm)
|
|||
|
||||
void main()
|
||||
{
|
||||
applyClip(vary_position);
|
||||
waterClip();
|
||||
|
||||
// diffcol == diffuse map combined with vertex color
|
||||
|
|
@ -407,9 +425,15 @@ void main()
|
|||
|
||||
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
|
||||
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
|
||||
|
||||
float flag = GBUFFER_FLAG_HAS_ATMOS;
|
||||
|
||||
if (mirror_flag > 0)
|
||||
flag = 1;
|
||||
|
||||
frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials
|
||||
frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent.
|
||||
frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
|
||||
frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
|
||||
frag_data[3] = vec4(0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n,
|
|||
|
||||
uniform samplerCubeArray reflectionProbes;
|
||||
uniform samplerCubeArray irradianceProbes;
|
||||
|
||||
uniform sampler2D sceneMap;
|
||||
uniform int cube_snapshot;
|
||||
uniform float max_probe_lod;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,16 @@ uniform sampler2D specularRect;
|
|||
uniform sampler2D normalMap;
|
||||
uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
|
||||
|
||||
uniform samplerCubeArray heroProbes;
|
||||
|
||||
#if defined(HERO_PROBES)
|
||||
layout (std140) uniform HeroProbeData
|
||||
{
|
||||
vec4 heroPosition[1];
|
||||
int heroProbeCount;
|
||||
};
|
||||
#endif
|
||||
|
||||
const float M_PI = 3.14159265;
|
||||
|
||||
#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
|
||||
|
|
@ -187,6 +197,13 @@ void main()
|
|||
|
||||
vec3 v = -normalize(pos.xyz);
|
||||
color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
|
||||
|
||||
#ifdef HERO_PROBES
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
|
||||
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR))
|
||||
color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor;
|
||||
#endif
|
||||
}
|
||||
else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
|
||||
{
|
||||
|
|
@ -244,6 +261,11 @@ void main()
|
|||
|
||||
// add radiance map
|
||||
applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
|
||||
|
||||
#ifdef HERO_PROBES
|
||||
color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a);
|
||||
|
|
|
|||
|
|
@ -1766,6 +1766,7 @@ bool LLAppViewer::doFrame()
|
|||
LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");
|
||||
pingMainloopTimeout("Main:Snapshot");
|
||||
gPipeline.mReflectionMapManager.update();
|
||||
gPipeline.mHeroProbeManager.update();
|
||||
LLFloaterSnapshot::update(); // take snapshots
|
||||
LLFloaterSimpleSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ public:
|
|||
ANIMATED_CHILD = 0x01000000,
|
||||
ACTIVE_CHILD = 0x02000000,
|
||||
FOR_UNLOAD = 0x04000000, //should be unload from memory
|
||||
MIRROR = 0x08000000, // Used as a mirror, needs a hero probe position to be calculated.
|
||||
} EDrawableFlags;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -183,6 +183,19 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
|
|||
glUniform4fv(specular, 1, lastSpecular.mV);
|
||||
}
|
||||
|
||||
if (gPipeline.mHeroProbeManager.isMirrorPass())
|
||||
{
|
||||
glUniform1f(LLShaderMgr::MIRROR_FLAG, 1);
|
||||
}
|
||||
|
||||
LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0],
|
||||
gPipeline.mHeroProbeManager.currentMirrorClip()[1],
|
||||
gPipeline.mHeroProbeManager.currentMirrorClip()[2],
|
||||
gPipeline.mHeroProbeManager.currentMirrorClip()[3]);
|
||||
|
||||
mShader->uniform4fv(LLShaderMgr::CLIP_PLANE,
|
||||
1, clipPlane.mV);
|
||||
|
||||
LLVOAvatar* lastAvatar = nullptr;
|
||||
|
||||
for (LLCullResult::drawinfo_iterator i = begin; i != end; )
|
||||
|
|
|
|||
|
|
@ -1991,7 +1991,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
F32* normals = (F32*) norm.get();
|
||||
LLVector4a* src = vf.mNormals;
|
||||
LLVector4a* end = src+num_vertices;
|
||||
|
||||
|
||||
while (src < end)
|
||||
{
|
||||
LLVector4a normal;
|
||||
|
|
|
|||
|
|
@ -128,6 +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->uniform1f(LLShaderMgr::MIRROR_FLAG, 0);
|
||||
|
||||
F32 normal_packed[8];
|
||||
mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed);
|
||||
|
|
|
|||
|
|
@ -1627,32 +1627,45 @@ BOOL LLPanelRegionTerrainInfo::postBuild()
|
|||
mAskedTextureHeights = false;
|
||||
mConfirmedTextureHeights = false;
|
||||
|
||||
refresh();
|
||||
|
||||
return LLPanelRegionInfo::postBuild();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelRegionTerrainInfo::refresh()
|
||||
{
|
||||
std::string buffer;
|
||||
// For simplicity, require restart
|
||||
static BOOL feature_pbr_terrain_enabled = gSavedSettings.getBOOL("RenderTerrainPBREnabled");
|
||||
|
||||
bool has_material_assets = false;
|
||||
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
|
||||
{
|
||||
buffer = llformat("material_detail_%d", i);
|
||||
LLTextureCtrl* material_ctrl = getChild<LLTextureCtrl>(buffer);
|
||||
if (material_ctrl && material_ctrl->getImageAssetID().notNull())
|
||||
{
|
||||
has_material_assets = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LLTextBox* texture_text = getChild<LLTextBox>("detail_texture_text");
|
||||
if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); }
|
||||
|
||||
LLComboBox* material_type_ctrl = getChild<LLComboBox>("terrain_material_type");
|
||||
if (material_type_ctrl)
|
||||
{
|
||||
const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
|
||||
material_type_ctrl->setVisible(feature_pbr_terrain_enabled);
|
||||
|
||||
bool has_material_assets = false;
|
||||
|
||||
std::string buffer;
|
||||
for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i)
|
||||
{
|
||||
buffer = llformat("material_detail_%d", i);
|
||||
LLTextureCtrl* material_ctrl = getChild<LLTextureCtrl>(buffer);
|
||||
if (material_ctrl && material_ctrl->getImageAssetID().notNull())
|
||||
{
|
||||
has_material_assets = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex());
|
||||
|
||||
if (!feature_pbr_terrain_enabled) { material_type = TerrainMaterialType::TEXTURE; }
|
||||
|
||||
const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL;
|
||||
material_type_ctrl->setEnabled(!(is_material_selected && has_material_assets));
|
||||
material_type_ctrl->setEnabled(feature_pbr_terrain_enabled && !(is_material_selected && has_material_assets));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,584 @@
|
|||
/**
|
||||
* @file LLHeroProbeManager.cpp
|
||||
* @brief LLHeroProbeManager class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llheroprobemanager.h"
|
||||
#include "llreflectionmapmanager.h"
|
||||
#include "llviewercamera.h"
|
||||
#include "llspatialpartition.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "pipeline.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llenvironment.h"
|
||||
#include "llstartup.h"
|
||||
#include "llagent.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llviewerjoystick.h"
|
||||
#include "llviewermediafocus.h"
|
||||
|
||||
extern BOOL gCubeSnapshot;
|
||||
extern BOOL gTeleportDisplay;
|
||||
|
||||
// get the next highest power of two of v (or v if v is already a power of two)
|
||||
//defined in llvertexbuffer.cpp
|
||||
extern U32 nhpo2(U32 v);
|
||||
|
||||
static void touch_default_probe(LLReflectionMap* probe)
|
||||
{
|
||||
if (LLViewerCamera::getInstance())
|
||||
{
|
||||
LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
|
||||
origin.mV[2] += 64.f;
|
||||
|
||||
probe->mOrigin.load3(origin.mV);
|
||||
}
|
||||
}
|
||||
|
||||
LLHeroProbeManager::LLHeroProbeManager()
|
||||
{
|
||||
}
|
||||
|
||||
// helper class to seed octree with probes
|
||||
void LLHeroProbeManager::update()
|
||||
{
|
||||
if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
llassert(!gCubeSnapshot); // assert a snapshot is not in progress
|
||||
if (LLAppViewer::instance()->logoutRequestSent())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
initReflectionMaps();
|
||||
|
||||
if (!mRenderTarget.isComplete())
|
||||
{
|
||||
U32 color_fmt = GL_RGBA16F;
|
||||
U32 targetRes = mProbeResolution; // super sample
|
||||
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
|
||||
}
|
||||
|
||||
if (mMipChain.empty())
|
||||
{
|
||||
U32 res = mProbeResolution;
|
||||
U32 count = log2((F32)res) + 0.5f;
|
||||
|
||||
mMipChain.resize(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
mMipChain[i].allocate(res, res, GL_RGBA16F);
|
||||
res /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
llassert(mProbes[0] == mDefaultProbe);
|
||||
|
||||
LLVector4a probe_pos;
|
||||
LLVector3 camera_pos = LLViewerCamera::instance().mOrigin;
|
||||
F32 near_clip = 0.1f;
|
||||
if (mHeroVOList.size() > 0)
|
||||
{
|
||||
// Find our nearest hero candidate.
|
||||
|
||||
float last_distance = 99999.f;
|
||||
|
||||
for (auto vo : mHeroVOList)
|
||||
{
|
||||
if (vo)
|
||||
{
|
||||
if (vo->mDrawable.notNull())
|
||||
{
|
||||
if (vo->mDrawable->mDistanceWRTCamera < last_distance)
|
||||
{
|
||||
mNearestHero = vo;
|
||||
last_distance = vo->mDrawable->mDistanceWRTCamera;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Valid drawables only please. Unregister this one.
|
||||
unregisterHeroDrawable(vo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unregisterHeroDrawable(vo);
|
||||
}
|
||||
}
|
||||
|
||||
if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull())
|
||||
{
|
||||
U8 mode = mNearestHero->mirrorFace();
|
||||
mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode);
|
||||
|
||||
mCurrentFace = mNearestHero->mDrawable->getFace(mode);
|
||||
LLVector3 hero_pos = mCurrentFace->getPositionAgent();
|
||||
|
||||
|
||||
// Calculate the average normal.
|
||||
LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions;
|
||||
U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices;
|
||||
// get first three vertices (first triangle)
|
||||
LLVector4a v0 = posp[indp[0]];
|
||||
LLVector4a v1 = posp[indp[1]];
|
||||
LLVector4a v2 = posp[indp[2]];
|
||||
|
||||
v1.sub(v0);
|
||||
v2.sub(v0);
|
||||
LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]);
|
||||
|
||||
face_normal.normalize();
|
||||
face_normal *= mCurrentFace->getXform()->getWorldRotation();
|
||||
|
||||
LLVector3 offset = camera_pos - hero_pos;
|
||||
LLVector3 project = face_normal * (offset * face_normal);
|
||||
LLVector3 reject = offset - project;
|
||||
LLVector3 point = (reject - project) + hero_pos;
|
||||
|
||||
glh::matrix4f mat = copy_matrix(gGLModelView);
|
||||
glh::vec4f tc(face_normal.mV);
|
||||
mat.mult_matrix_vec(tc);
|
||||
|
||||
LLVector3 mirror_normal;
|
||||
mirror_normal.set(tc.v);
|
||||
|
||||
LLVector3 hero_pos_render;
|
||||
tc = glh::vec4f(hero_pos.mV);
|
||||
|
||||
mat.mult_matrix_vec(tc);
|
||||
hero_pos_render.set(tc.v);
|
||||
|
||||
mCurrentClipPlane.setVec(hero_pos_render, mirror_normal);
|
||||
|
||||
probe_pos.load3(point.mV);
|
||||
}
|
||||
|
||||
mHeroProbeStrength = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
probe_pos.load3(camera_pos.mV);
|
||||
}
|
||||
|
||||
|
||||
static LLCachedControl<S32> sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1);
|
||||
static LLCachedControl<S32> sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3);
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime");
|
||||
// Probe 0 is always our mirror probe.
|
||||
mProbes[0]->mOrigin = probe_pos;
|
||||
|
||||
bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass();
|
||||
|
||||
gPipeline.mReflectionMapManager.mRadiancePass = true;
|
||||
mRenderingMirror = true;
|
||||
for (U32 j = 0; j < mProbes.size(); j++)
|
||||
{
|
||||
for (U32 i = 0; i < 6; ++i)
|
||||
{
|
||||
updateProbeFace(mProbes[j], i, near_clip);
|
||||
}
|
||||
}
|
||||
mRenderingMirror = false;
|
||||
|
||||
gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the reflection map update render passes.
|
||||
// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// a simple mip chain (not convolution filter).
|
||||
// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe
|
||||
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
|
||||
// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.
|
||||
// In effect this simulates single-bounce lighting.
|
||||
void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip)
|
||||
{
|
||||
// hacky hot-swap of camera specific render targets
|
||||
gPipeline.mRT = &gPipeline.mAuxillaryRT;
|
||||
|
||||
probe->update(mRenderTarget.getWidth(), face, true, near_clip);
|
||||
|
||||
gPipeline.mRT = &gPipeline.mMainRT;
|
||||
|
||||
S32 sourceIdx = mReflectionProbeCount;
|
||||
|
||||
|
||||
// Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes.
|
||||
sourceIdx += 1;
|
||||
|
||||
gGL.setColorMask(true, true);
|
||||
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
|
||||
// downsample to placeholder map
|
||||
{
|
||||
gGL.matrixMode(gGL.MM_MODELVIEW);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
gGL.matrixMode(gGL.MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadIdentity();
|
||||
|
||||
gGL.flush();
|
||||
U32 res = mProbeResolution * 2;
|
||||
|
||||
static LLStaticHashedString resScale("resScale");
|
||||
static LLStaticHashedString direction("direction");
|
||||
static LLStaticHashedString znear("znear");
|
||||
static LLStaticHashedString zfar("zfar");
|
||||
|
||||
LLRenderTarget *screen_rt = &gPipeline.mAuxillaryRT.screen;
|
||||
LLRenderTarget *depth_rt = &gPipeline.mAuxillaryRT.deferredScreen;
|
||||
|
||||
// perform a gaussian blur on the super sampled render before downsampling
|
||||
{
|
||||
gGaussianProgram.bind();
|
||||
gGaussianProgram.uniform1f(resScale, 1.f / mProbeResolution);
|
||||
S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
|
||||
|
||||
// horizontal
|
||||
gGaussianProgram.uniform2f(direction, 1.f, 0.f);
|
||||
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
|
||||
mRenderTarget.bindTarget();
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
mRenderTarget.flush();
|
||||
|
||||
// vertical
|
||||
gGaussianProgram.uniform2f(direction, 0.f, 1.f);
|
||||
gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
|
||||
screen_rt->bindTarget();
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
screen_rt->flush();
|
||||
}
|
||||
|
||||
|
||||
S32 mips = log2((F32)mProbeResolution) + 0.5f;
|
||||
|
||||
gReflectionMipProgram.bind();
|
||||
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
|
||||
S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE);
|
||||
|
||||
for (int i = 0; i < mMipChain.size(); ++i)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe mip");
|
||||
mMipChain[i].bindTarget();
|
||||
if (i == 0)
|
||||
{
|
||||
gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1]));
|
||||
}
|
||||
|
||||
gGL.getTexUnit(depthChannel)->bind(depth_rt, true);
|
||||
|
||||
gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));
|
||||
gReflectionMipProgram.uniform1f(znear, probe->getNearClip());
|
||||
gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP);
|
||||
|
||||
gPipeline.mScreenTriangleVB->setBuffer();
|
||||
gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
|
||||
res /= 2;
|
||||
|
||||
S32 mip = i - (mMipChain.size() - mips);
|
||||
|
||||
if (mip >= 0)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe mip copy");
|
||||
mTexture->bind(0);
|
||||
|
||||
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res);
|
||||
|
||||
mTexture->unbind();
|
||||
}
|
||||
mMipChain[i].flush();
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(gGL.MM_MODELVIEW);
|
||||
gGL.popMatrix();
|
||||
|
||||
gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gReflectionMipProgram.unbind();
|
||||
}
|
||||
|
||||
if (face == 5)
|
||||
{
|
||||
mMipChain[0].bindTarget();
|
||||
static LLStaticHashedString sSourceIdx("sourceIdx");
|
||||
|
||||
{
|
||||
//generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
|
||||
gRadianceGenProgram.bind();
|
||||
mVertexBuffer->setBuffer();
|
||||
|
||||
S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
|
||||
mTexture->bind(channel);
|
||||
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength);
|
||||
|
||||
U32 res = mMipChain[0].getWidth();
|
||||
|
||||
for (int i = 0; i < mMipChain.size(); ++i)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("probe radiance gen");
|
||||
static LLStaticHashedString sMipLevel("mipLevel");
|
||||
static LLStaticHashedString sRoughness("roughness");
|
||||
static LLStaticHashedString sWidth("u_width");
|
||||
static LLStaticHashedString sStrength("probe_strength");
|
||||
|
||||
gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
|
||||
gRadianceGenProgram.uniform1f(sMipLevel, i);
|
||||
gRadianceGenProgram.uniform1i(sWidth, mProbeResolution);
|
||||
gRadianceGenProgram.uniform1f(sStrength, 1);
|
||||
|
||||
for (int cf = 0; cf < 6; ++cf)
|
||||
{ // for each cube face
|
||||
LLCoordFrame frame;
|
||||
frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
|
||||
|
||||
F32 mat[16];
|
||||
frame.getOpenGLRotation(mat);
|
||||
gGL.loadMatrix(mat);
|
||||
|
||||
mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
|
||||
}
|
||||
|
||||
if (i != mMipChain.size() - 1)
|
||||
{
|
||||
res /= 2;
|
||||
glViewport(0, 0, res, res);
|
||||
}
|
||||
}
|
||||
|
||||
gRadianceGenProgram.unbind();
|
||||
}
|
||||
|
||||
mMipChain[0].flush();
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::updateUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
|
||||
struct HeroProbeData
|
||||
{
|
||||
LLVector4 heroPosition[1];
|
||||
GLint heroProbeCount = 1;
|
||||
};
|
||||
|
||||
HeroProbeData hpd;
|
||||
|
||||
LLMatrix4a modelview;
|
||||
modelview.loadu(gGLModelView);
|
||||
LLVector4a oa; // scratch space for transformed origin
|
||||
oa.set(0, 0, 0, 0);
|
||||
hpd.heroProbeCount = 1;
|
||||
modelview.affineTransform(mProbes[0]->mOrigin, oa);
|
||||
hpd.heroPosition[0].set(oa.getF32ptr());
|
||||
|
||||
//copy rpd into uniform buffer object
|
||||
if (mUBO == 0)
|
||||
{
|
||||
glGenBuffers(1, &mUBO);
|
||||
}
|
||||
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, mUBO);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::setUniforms()
|
||||
{
|
||||
if (!LLPipeline::sReflectionProbesEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUBO == 0)
|
||||
{
|
||||
updateUniforms();
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::renderDebug()
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
renderReflectionProbe(probe);
|
||||
}
|
||||
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::initReflectionMaps()
|
||||
{
|
||||
U32 count = LL_MAX_HERO_PROBE_COUNT;
|
||||
|
||||
if (mTexture.isNull() || mReflectionProbeCount != count || mReset)
|
||||
{
|
||||
mReset = false;
|
||||
mReflectionProbeCount = count;
|
||||
mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution");
|
||||
mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1
|
||||
|
||||
mTexture = new LLCubeMapArray();
|
||||
|
||||
// store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source)
|
||||
mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2);
|
||||
|
||||
if (mDefaultProbe.isNull())
|
||||
{
|
||||
llassert(mProbes.empty()); // default probe MUST be the first probe created
|
||||
mDefaultProbe = new LLReflectionMap();
|
||||
mProbes.push_back(mDefaultProbe);
|
||||
}
|
||||
|
||||
llassert(mProbes[0] == mDefaultProbe);
|
||||
|
||||
// For hero probes, we treat this as the main mirror probe.
|
||||
|
||||
mDefaultProbe->mCubeIndex = 0;
|
||||
mDefaultProbe->mCubeArray = mTexture;
|
||||
mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance");
|
||||
mDefaultProbe->mRadius = 4096.f;
|
||||
mDefaultProbe->mProbeIndex = 0;
|
||||
touch_default_probe(mDefaultProbe);
|
||||
|
||||
mProbes.push_back(mDefaultProbe);
|
||||
}
|
||||
|
||||
if (mVertexBuffer.isNull())
|
||||
{
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX;
|
||||
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask);
|
||||
buff->allocateBuffer(4, 0);
|
||||
|
||||
LLStrider<LLVector3> v;
|
||||
|
||||
buff->getVertexStrider(v);
|
||||
|
||||
v[0] = LLVector3(-1, -1, -1);
|
||||
v[1] = LLVector3(1, -1, -1);
|
||||
v[2] = LLVector3(-1, 1, -1);
|
||||
v[3] = LLVector3(1, 1, -1);
|
||||
|
||||
buff->unmapBuffer();
|
||||
|
||||
mVertexBuffer = buff;
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::cleanup()
|
||||
{
|
||||
mVertexBuffer = nullptr;
|
||||
mRenderTarget.release();
|
||||
mHeroRenderTarget.release();
|
||||
|
||||
mMipChain.clear();
|
||||
|
||||
mTexture = nullptr;
|
||||
|
||||
mProbes.clear();
|
||||
|
||||
mReflectionMaps.clear();
|
||||
|
||||
mDefaultProbe = nullptr;
|
||||
mUpdatingProbe = nullptr;
|
||||
|
||||
glDeleteBuffers(1, &mUBO);
|
||||
mUBO = 0;
|
||||
|
||||
mHeroVOList.clear();
|
||||
mNearestHero = nullptr;
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::doOcclusion()
|
||||
{
|
||||
LLVector4a eye;
|
||||
eye.load3(LLViewerCamera::instance().getOrigin().mV);
|
||||
|
||||
for (auto& probe : mProbes)
|
||||
{
|
||||
if (probe != nullptr && probe != mDefaultProbe)
|
||||
{
|
||||
probe->doOcclusion(eye);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep)
|
||||
{
|
||||
if (mHeroVOList.find(drawablep) == mHeroVOList.end())
|
||||
{
|
||||
mHeroVOList.insert(drawablep);
|
||||
LL_INFOS() << "Mirror drawable registered." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep)
|
||||
{
|
||||
if (mHeroVOList.find(drawablep) != mHeroVOList.end())
|
||||
{
|
||||
mHeroVOList.erase(drawablep);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLHeroProbeManager::isViableMirror(LLFace* face) const
|
||||
{
|
||||
return face == mCurrentFace;
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* @file llheroprobemanager.h
|
||||
* @brief LLHeroProbeManager class declaration
|
||||
*
|
||||
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2022, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "llreflectionmap.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "llcubemaparray.h"
|
||||
#include "llcubemap.h"
|
||||
#include "lldrawable.h"
|
||||
|
||||
class LLSpatialGroup;
|
||||
class LLViewerObject;
|
||||
|
||||
// number of reflection probes to keep in vram
|
||||
#define LL_MAX_HERO_PROBE_COUNT 2
|
||||
|
||||
class alignas(16) LLHeroProbeManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
enum class DetailLevel
|
||||
{
|
||||
STATIC_ONLY = 0,
|
||||
STATIC_AND_DYNAMIC,
|
||||
REALTIME = 2
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
LLHeroProbeManager();
|
||||
|
||||
// release any GL state
|
||||
void cleanup();
|
||||
|
||||
// maintain reflection probes
|
||||
void update();
|
||||
|
||||
// debug display, called from llspatialpartition if reflection
|
||||
// probe debug display is active
|
||||
void renderDebug();
|
||||
|
||||
// call once at startup to allocate cubemap arrays
|
||||
void initReflectionMaps();
|
||||
|
||||
// perform occlusion culling on all active reflection probes
|
||||
void doOcclusion();
|
||||
|
||||
void registerHeroDrawable(LLVOVolume* drawablep);
|
||||
void unregisterHeroDrawable(LLVOVolume* drawablep);
|
||||
|
||||
bool isViableMirror(LLFace* face) const;
|
||||
|
||||
bool isMirrorPass() const { return mRenderingMirror; }
|
||||
|
||||
LLPlane currentMirrorClip() const { return mCurrentClipPlane; }
|
||||
|
||||
private:
|
||||
friend class LLPipeline;
|
||||
|
||||
// update UBO used for rendering (call only once per render pipe flush)
|
||||
void updateUniforms();
|
||||
|
||||
// bind UBO used for rendering
|
||||
void setUniforms();
|
||||
|
||||
// render target for cube snapshots
|
||||
// used to generate mipmaps without doing a copy-to-texture
|
||||
LLRenderTarget mRenderTarget;
|
||||
|
||||
LLRenderTarget mHeroRenderTarget;
|
||||
|
||||
std::vector<LLRenderTarget> mMipChain;
|
||||
|
||||
// storage for reflection probe radiance maps (plus two scratch space cubemaps)
|
||||
LLPointer<LLCubeMapArray> mTexture;
|
||||
|
||||
// vertex buffer for pushing verts to filter shaders
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
LLPlane mCurrentClipPlane;
|
||||
|
||||
// update the specified face of the specified probe
|
||||
void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip);
|
||||
|
||||
// list of active reflection maps
|
||||
std::vector<LLPointer<LLReflectionMap> > mProbes;
|
||||
|
||||
// handle to UBO
|
||||
U32 mUBO = 0;
|
||||
|
||||
// list of maps being used for rendering
|
||||
std::vector<LLReflectionMap*> mReflectionMaps;
|
||||
|
||||
LLReflectionMap* mUpdatingProbe = nullptr;
|
||||
|
||||
LLPointer<LLReflectionMap> mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0)
|
||||
|
||||
// number of reflection probes to use for rendering
|
||||
U32 mReflectionProbeCount;
|
||||
|
||||
// resolution of reflection probes
|
||||
U32 mProbeResolution = 1024;
|
||||
|
||||
// maximum LoD of reflection probes (mip levels - 1)
|
||||
F32 mMaxProbeLOD = 6.f;
|
||||
|
||||
F32 mHeroProbeStrength = 1.f;
|
||||
bool mIsInTransition = false;
|
||||
|
||||
// if true, reset all probe render state on the next update (for teleports and sky changes)
|
||||
bool mReset = false;
|
||||
|
||||
bool mRenderingMirror = false;
|
||||
|
||||
std::set<LLVOVolume*> mHeroVOList;
|
||||
LLVOVolume* mNearestHero;
|
||||
LLFace* mCurrentFace;
|
||||
};
|
||||
|
||||
|
|
@ -1932,6 +1932,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
|
|||
mCtrlShinyOffsetV->setValue(offset_y);
|
||||
getChild<LLUICtrl>("glossiness")->setValue(material->getSpecularLightExponent());
|
||||
getChild<LLUICtrl>("environment")->setValue(material->getEnvironmentIntensity());
|
||||
getChild<LLUICtrl>("mirror")->setValue(material->getEnvironmentIntensity());
|
||||
|
||||
updateShinyControls(!material->getSpecularID().isNull(), true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ protected:
|
|||
void sendTexGen(); // applies and sends bump map
|
||||
void sendShiny(U32 shininess); // applies and sends shininess
|
||||
void sendFullbright(); // applies and sends full bright
|
||||
|
||||
void sendGlow();
|
||||
void alignTestureLayer();
|
||||
|
||||
|
|
@ -235,7 +236,7 @@ protected:
|
|||
static void onCommitShiny( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitFullbright( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
|
||||
static void onCommitGlow( LLUICtrl* ctrl, void *userdata);
|
||||
static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo);
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ BOOL LLPanelVolume::postBuild()
|
|||
getChild<LLUICtrl>("FlexForceZ")->setValidateBeforeCommit(precommitValidate);
|
||||
}
|
||||
|
||||
// Mirror Parameters
|
||||
{
|
||||
childSetCommitCallback("Mirror Checkbox Ctrl", onCommitIsMirror, this);
|
||||
}
|
||||
|
||||
// LIGHT Parameters
|
||||
{
|
||||
childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this);
|
||||
|
|
@ -309,6 +314,10 @@ void LLPanelVolume::getState( )
|
|||
getChildView("select_single")->setEnabled(true);
|
||||
}
|
||||
|
||||
BOOL is_mirror = volobjp && volobjp->isMirror();
|
||||
getChild<LLUICtrl>("Mirror Checkbox Ctrl")->setValue(is_mirror);
|
||||
getChildView("Mirror Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp);
|
||||
|
||||
// Light properties
|
||||
BOOL is_light = volobjp && volobjp->getIsLight();
|
||||
getChild<LLUICtrl>("Light Checkbox Ctrl")->setValue(is_light);
|
||||
|
|
@ -764,6 +773,20 @@ void LLPanelVolume::sendIsLight()
|
|||
LL_INFOS() << "update light sent" << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLPanelVolume::sendIsMirror()
|
||||
{
|
||||
LLViewerObject* objectp = mObject;
|
||||
if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||
|
||||
BOOL value = getChild<LLUICtrl>("Mirror Checkbox Ctrl")->getValue();
|
||||
volobjp->setIsMirror(value);
|
||||
LL_INFOS() << "update mirror sent" << LL_ENDL;
|
||||
}
|
||||
|
||||
void notify_cant_select_reflection_probe()
|
||||
{
|
||||
if (!gSavedSettings.getBOOL("SelectReflectionProbes"))
|
||||
|
|
@ -1506,6 +1529,12 @@ void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
|
|||
self->sendIsLight();
|
||||
}
|
||||
|
||||
void LLPanelVolume::onCommitIsMirror( LLUICtrl* ctrl, void* userdata )
|
||||
{
|
||||
LLPanelVolume* self = (LLPanelVolume*) userdata;
|
||||
self->sendIsMirror();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public:
|
|||
|
||||
void sendIsLight();
|
||||
|
||||
void sendIsMirror();
|
||||
// when an object is becoming a refleciton probe, present a dialog asking for confirmation
|
||||
// otherwise, send the reflection probe update immediately
|
||||
void sendIsReflectionProbe();
|
||||
|
|
@ -71,6 +72,7 @@ public:
|
|||
|
||||
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitIsMirror( LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata);
|
||||
static void onCommitProbe(LLUICtrl* ctrl, void* userdata);
|
||||
void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap()
|
|||
}
|
||||
}
|
||||
|
||||
void LLReflectionMap::update(U32 resolution, U32 face)
|
||||
void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
mLastUpdateTime = gFrameTimeSeconds;
|
||||
|
|
@ -63,7 +63,10 @@ void LLReflectionMap::update(U32 resolution, U32 face)
|
|||
{
|
||||
resolution /= 2;
|
||||
}
|
||||
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
|
||||
|
||||
F32 clip = (near_clip > 0) ? near_clip : getNearClip();
|
||||
|
||||
gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane);
|
||||
}
|
||||
|
||||
void LLReflectionMap::autoAdjustOrigin()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ class alignas(16) LLReflectionMap : public LLRefCount
|
|||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
|
||||
enum class ProbeType
|
||||
{
|
||||
ALL = 0,
|
||||
RADIANCE,
|
||||
IRRADIANCE,
|
||||
REFLECTION
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMap();
|
||||
|
||||
|
|
@ -43,7 +52,7 @@ public:
|
|||
|
||||
// update this environment map
|
||||
// resolution - size of cube map to generate
|
||||
void update(U32 resolution, U32 face);
|
||||
void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f, bool useClipPlane = false, LLPlane clipPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1)));
|
||||
|
||||
// for volume partition probes, try to place this probe in the best spot
|
||||
void autoAdjustOrigin();
|
||||
|
|
@ -127,5 +136,7 @@ public:
|
|||
GLuint mOcclusionQuery = 0;
|
||||
bool mOccluded = false;
|
||||
U32 mOcclusionPendingFrames = 0;
|
||||
|
||||
ProbeType mType;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -309,8 +309,8 @@ void LLReflectionMapManager::update()
|
|||
}
|
||||
}
|
||||
|
||||
if (realtime &&
|
||||
closestDynamic == nullptr &&
|
||||
if (realtime &&
|
||||
closestDynamic == nullptr &&
|
||||
probe->mCubeIndex != -1 &&
|
||||
probe->getIsDynamic())
|
||||
{
|
||||
|
|
@ -325,7 +325,7 @@ void LLReflectionMapManager::update()
|
|||
// should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames
|
||||
closestDynamic->autoAdjustOrigin();
|
||||
|
||||
// store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set
|
||||
// store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set
|
||||
// lighting values etc
|
||||
bool radiance_pass = isRadiancePass();
|
||||
mRadiancePass = mRealtimeRadiancePass;
|
||||
|
|
@ -576,7 +576,7 @@ void LLReflectionMapManager::doProbeUpdate()
|
|||
|
||||
// Do the reflection map update render passes.
|
||||
// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
|
||||
// a simple mip chain (not convolution filter).
|
||||
// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe
|
||||
// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
|
||||
|
|
@ -737,6 +737,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
|
|||
mTexture->bind(channel);
|
||||
gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
|
||||
gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f);
|
||||
|
||||
U32 res = mMipChain[0].getWidth();
|
||||
|
||||
|
|
@ -901,14 +902,14 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// see class3/deferred/reflectionProbeF.glsl
|
||||
struct ReflectionProbeData
|
||||
{
|
||||
// for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
|
||||
// for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of
|
||||
// the box probe
|
||||
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
// for sphere probes, origin (xyz) and radius (w) of refmaps in clip space
|
||||
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];
|
||||
|
||||
// extra parameters
|
||||
// extra parameters
|
||||
// x - irradiance scale
|
||||
// y - radiance scale
|
||||
// z - fade in
|
||||
|
|
@ -920,14 +921,14 @@ void LLReflectionMapManager::updateUniforms()
|
|||
// [i][1] - index into "refNeighbor" for probes that intersect this probe
|
||||
// [i][2] - number of probes that intersect this probe, or -1 for no neighbors
|
||||
// [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes)
|
||||
GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
|
||||
GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4];
|
||||
|
||||
// list of neighbor indices
|
||||
GLint refNeighbor[4096];
|
||||
GLint refNeighbor[4096];
|
||||
|
||||
GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth
|
||||
// numbrer of active refmaps
|
||||
GLint refmapCount;
|
||||
GLint refmapCount;
|
||||
};
|
||||
|
||||
mReflectionMaps.resize(mReflectionProbeCount);
|
||||
|
|
@ -1155,7 +1156,7 @@ void LLReflectionMapManager::setUniforms()
|
|||
}
|
||||
|
||||
if (mUBO == 0)
|
||||
{
|
||||
{
|
||||
updateUniforms();
|
||||
}
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
|
||||
|
|
@ -1346,8 +1347,8 @@ void LLReflectionMapManager::initReflectionMaps()
|
|||
}
|
||||
}
|
||||
|
||||
void LLReflectionMapManager::cleanup()
|
||||
{
|
||||
void LLReflectionMapManager::cleanup()
|
||||
{
|
||||
mVertexBuffer = nullptr;
|
||||
mRenderTarget.release();
|
||||
|
||||
|
|
|
|||
|
|
@ -43,21 +43,23 @@ class LLViewerObject;
|
|||
// reflection probe mininum scale
|
||||
#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f;
|
||||
|
||||
void renderReflectionProbe(LLReflectionMap* probe);
|
||||
|
||||
class alignas(16) LLReflectionMapManager
|
||||
{
|
||||
LL_ALIGN_NEW
|
||||
public:
|
||||
enum class DetailLevel
|
||||
enum class DetailLevel
|
||||
{
|
||||
STATIC_ONLY = 0,
|
||||
STATIC_AND_DYNAMIC,
|
||||
REALTIME = 2
|
||||
};
|
||||
|
||||
// allocate an environment map of the given resolution
|
||||
// allocate an environment map of the given resolution
|
||||
LLReflectionMapManager();
|
||||
|
||||
// release any GL state
|
||||
// release any GL state
|
||||
void cleanup();
|
||||
|
||||
// maintain reflection probes
|
||||
|
|
@ -113,6 +115,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class LLPipeline;
|
||||
friend class LLHeroProbeManager;
|
||||
|
||||
// initialize mCubeFree array to default values
|
||||
void initCubeFree();
|
||||
|
|
@ -124,7 +127,7 @@ private:
|
|||
// returns -1 if allocation failed
|
||||
S32 allocateCubeIndex();
|
||||
|
||||
// update the neighbors of the given probe
|
||||
// update the neighbors of the given probe
|
||||
void updateNeighbors(LLReflectionMap* probe);
|
||||
|
||||
// update UBO used for rendering (call only once per render pipe flush)
|
||||
|
|
|
|||
|
|
@ -1191,7 +1191,7 @@ void display_cube_face()
|
|||
LLSpatialGroup::sNoDelete = TRUE;
|
||||
|
||||
S32 occlusion = LLPipeline::sUseOcclusion;
|
||||
LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
|
||||
LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
|
||||
//gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
|
||||
|
||||
static LLCullResult result;
|
||||
|
|
|
|||
|
|
@ -332,7 +332,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
|
|||
mLastUpdateCached(FALSE),
|
||||
mCachedMuteListUpdateTime(0),
|
||||
mCachedOwnerInMuteList(false),
|
||||
mRiggedAttachedWarned(false)
|
||||
mRiggedAttachedWarned(false),
|
||||
mIsMirror(false),
|
||||
mMirrorFace(3)
|
||||
{
|
||||
if (!is_global)
|
||||
{
|
||||
|
|
@ -1201,6 +1203,39 @@ U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector
|
|||
return parent_id;
|
||||
}
|
||||
|
||||
void detectMirror(const std::string &str, bool &mirror, U8 &mode)
|
||||
{
|
||||
|
||||
std::stringstream ss(str);
|
||||
std::string word;
|
||||
while (ss >> word)
|
||||
{
|
||||
if (word == "IsMirror")
|
||||
{
|
||||
mirror = true;
|
||||
}
|
||||
|
||||
if (mirror)
|
||||
{
|
||||
bool num = false;
|
||||
std::string::const_iterator it = word.begin();
|
||||
while (it != word.end())
|
||||
{
|
||||
num = std::isdigit(*it);
|
||||
++it;
|
||||
|
||||
if (!num)
|
||||
break;
|
||||
}
|
||||
|
||||
if (num)
|
||||
{
|
||||
mode = atoi(word.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
|
||||
void **user_data,
|
||||
U32 block_num,
|
||||
|
|
@ -1580,11 +1615,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
|
|||
std::string temp_string;
|
||||
mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num );
|
||||
|
||||
detectMirror(temp_string, mIsMirror, mMirrorFace);
|
||||
|
||||
LLColor4U coloru;
|
||||
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num);
|
||||
|
||||
|
||||
// alpha was flipped so that it zero encoded better
|
||||
coloru.mV[3] = 255 - coloru.mV[3];
|
||||
|
||||
mText->setColor(LLColor4(coloru));
|
||||
mText->setString(temp_string);
|
||||
// [RLVa:KB] - Checked: 2010-03-27 (RLVa-1.4.0a) | Added: RLVa-1.0.0f
|
||||
|
|
@ -1970,6 +2008,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
|
|||
{
|
||||
std::string temp_string;
|
||||
dp->unpackString(temp_string, "Text");
|
||||
|
||||
detectMirror(temp_string, mIsMirror, mMirrorFace);
|
||||
|
||||
LLColor4U coloru;
|
||||
dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
|
||||
coloru.mV[3] = 255 - coloru.mV[3];
|
||||
|
|
@ -5528,7 +5569,6 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
|
||||
{
|
||||
// this might need work for media type
|
||||
|
|
@ -6474,6 +6514,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
|
|||
{
|
||||
new_block = new LLReflectionProbeParams();
|
||||
break;
|
||||
}
|
||||
case LLNetworkData::PARAMS_MIRROR:
|
||||
{
|
||||
new_block = new LLMirrorParams();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ public:
|
|||
virtual BOOL isRiggedMesh() const { return FALSE; }
|
||||
virtual BOOL hasLightTexture() const { return FALSE; }
|
||||
virtual BOOL isReflectionProbe() const { return FALSE; }
|
||||
virtual BOOL isMirror() const { return FALSE; }
|
||||
virtual U8 mirrorFace() const { return 0; }
|
||||
|
||||
// This method returns true if the object is over land owned by
|
||||
// the agent, one of its groups, or it encroaches and
|
||||
|
|
@ -898,6 +900,9 @@ protected:
|
|||
F32 mPhysicsCost;
|
||||
F32 mLinksetPhysicsCost;
|
||||
|
||||
bool mIsMirror;
|
||||
U8 mMirrorFace;
|
||||
|
||||
// If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap"
|
||||
bool mShouldShrinkWrap = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1825,6 +1825,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
|
|||
gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1");
|
||||
}
|
||||
|
||||
if (LLPipeline::RenderMirrors)
|
||||
{
|
||||
gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1");
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
|
||||
{ //if using SSAO, take screen space light map into account as if shadows are enabled
|
||||
gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2);
|
||||
|
|
|
|||
|
|
@ -6515,7 +6515,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
|
|||
|
||||
void display_cube_face();
|
||||
|
||||
BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render)
|
||||
BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render, bool useCustomClipPlane, LLPlane clipPlane)
|
||||
{
|
||||
// NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
|
||||
|
|
@ -6546,6 +6546,14 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
|
|||
camera->setOrigin(origin);
|
||||
camera->setNear(near_clip);
|
||||
|
||||
LLPlane previousClipPlane;
|
||||
|
||||
if (useCustomClipPlane)
|
||||
{
|
||||
previousClipPlane = camera->getUserClipPlane();
|
||||
camera->setUserClipPlane(clipPlane);
|
||||
}
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
U32 dynamic_render_types[] = {
|
||||
|
|
@ -6652,6 +6660,11 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea
|
|||
|
||||
gPipeline.resetDrawOrders();
|
||||
mWorldViewRectRaw = window_rect;
|
||||
|
||||
if (useCustomClipPlane)
|
||||
{
|
||||
camera->setUserClipPlane(previousClipPlane);
|
||||
}
|
||||
|
||||
// restore original view/camera/avatar settings settings
|
||||
*camera = saved_camera;
|
||||
|
|
|
|||
|
|
@ -375,7 +375,8 @@ public:
|
|||
// index - cube index in the array to use (cube index, not face-layer)
|
||||
// face - which cube face to update
|
||||
// near_clip - near clip setting to use
|
||||
BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars);
|
||||
BOOL cubeSnapshot(const LLVector3 &origin, LLCubeMapArray *cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars,
|
||||
bool customCullingPlane = false, LLPlane cullingPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1)));
|
||||
|
||||
|
||||
// special implementation of simpleSnapshot for reflection maps
|
||||
|
|
|
|||
|
|
@ -267,6 +267,9 @@ LLVOVolume::~LLVOVolume()
|
|||
mTextureAnimp = NULL;
|
||||
delete mVolumeImpl;
|
||||
mVolumeImpl = NULL;
|
||||
|
||||
if (mIsMirror)
|
||||
gPipeline.mHeroProbeManager.unregisterHeroDrawable(this);
|
||||
|
||||
gMeshRepo.unregisterMesh(this);
|
||||
|
||||
|
|
@ -1150,7 +1153,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
|
|||
{
|
||||
updateReflectionProbePtr();
|
||||
}
|
||||
|
||||
|
||||
if (isMirror())
|
||||
{
|
||||
gPipeline.mHeroProbeManager.registerHeroDrawable(this);
|
||||
}
|
||||
|
||||
updateRadius();
|
||||
bool force_update = true; // avoid non-alpha mDistance update being optimized away
|
||||
mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
|
||||
|
|
@ -3515,6 +3523,48 @@ F32 LLVOVolume::getLightCutoff() const
|
|||
}
|
||||
}
|
||||
|
||||
bool LLVOVolume::setIsMirror(BOOL is_mirror)
|
||||
{
|
||||
BOOL was_mirror = isMirror();
|
||||
if (is_mirror != was_mirror)
|
||||
{
|
||||
if (is_mirror)
|
||||
{
|
||||
setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, TRUE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, FALSE, true);
|
||||
}
|
||||
}
|
||||
|
||||
updateMirrorDrawable();
|
||||
|
||||
return was_mirror != is_mirror;
|
||||
}
|
||||
|
||||
void LLVOVolume::updateMirrorDrawable()
|
||||
{
|
||||
if (isMirror())
|
||||
{
|
||||
gPipeline.mHeroProbeManager.registerHeroDrawable(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mHeroProbeManager.unregisterHeroDrawable(this);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLVOVolume::isMirror() const
|
||||
{
|
||||
return mIsMirror;
|
||||
}
|
||||
|
||||
U8 LLVOVolume::mirrorFace() const
|
||||
{
|
||||
return mMirrorFace;
|
||||
}
|
||||
|
||||
BOOL LLVOVolume::isReflectionProbe() const
|
||||
{
|
||||
return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
|
||||
|
|
@ -4605,6 +4655,11 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
|
|||
}
|
||||
|
||||
updateReflectionProbePtr();
|
||||
|
||||
if (isMirror())
|
||||
gPipeline.mHeroProbeManager.registerHeroDrawable(this);
|
||||
else
|
||||
gPipeline.mHeroProbeManager.unregisterHeroDrawable(this);
|
||||
}
|
||||
|
||||
void LLVOVolume::updateReflectionProbePtr()
|
||||
|
|
|
|||
|
|
@ -299,6 +299,11 @@ public:
|
|||
F32 getLightRadius() const;
|
||||
F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
|
||||
F32 getLightCutoff() const;
|
||||
|
||||
// Mirrors
|
||||
bool setIsMirror(BOOL is_mirror);
|
||||
void updateMirrorDrawable();
|
||||
U8 mirrorFace() const override;
|
||||
|
||||
// Reflection Probes
|
||||
bool setIsReflectionProbe(BOOL is_probe);
|
||||
|
|
@ -312,6 +317,8 @@ public:
|
|||
F32 getReflectionProbeNearClip() const;
|
||||
bool getReflectionProbeIsBox() const;
|
||||
bool getReflectionProbeIsDynamic() const;
|
||||
|
||||
BOOL isMirror() const override;
|
||||
|
||||
// Flexible Objects
|
||||
U32 getVolumeInterfaceID() const;
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ F32 LLPipeline::RenderScreenSpaceReflectionDepthRejectBias;
|
|||
F32 LLPipeline::RenderScreenSpaceReflectionAdaptiveStepMultiplier;
|
||||
S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples;
|
||||
S32 LLPipeline::RenderBufferVisualization;
|
||||
bool LLPipeline::RenderMirrors;
|
||||
LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
|
||||
|
||||
const U32 LLPipeline::MAX_BAKE_WIDTH = 512;
|
||||
|
|
@ -598,6 +599,7 @@ void LLPipeline::init()
|
|||
connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionAdaptiveStepMultiplier");
|
||||
connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionGlossySamples");
|
||||
connectRefreshCachedSettingsSafe("RenderBufferVisualization");
|
||||
connectRefreshCachedSettingsSafe("RenderMirrors");
|
||||
connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");
|
||||
connectRefreshCachedSettingsSafe("FSRenderVignette"); // <FS:CR> Import Vignette from Exodus
|
||||
// <FS:Ansariel> Make change to RenderAttachedLights & RenderAttachedParticles instant
|
||||
|
|
@ -690,6 +692,7 @@ void LLPipeline::cleanup()
|
|||
mCubeVB = NULL;
|
||||
|
||||
mReflectionMapManager.cleanup();
|
||||
mHeroProbeManager.cleanup();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -836,11 +839,17 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (mRT == &mMainRT)
|
||||
{ // hacky -- allocate auxillary buffer
|
||||
|
||||
gCubeSnapshot = TRUE;
|
||||
mReflectionMapManager.initReflectionMaps();
|
||||
mHeroProbeManager.initReflectionMaps();
|
||||
|
||||
if (sReflectionProbesEnabled)
|
||||
{
|
||||
gCubeSnapshot = TRUE;
|
||||
mReflectionMapManager.initReflectionMaps();
|
||||
}
|
||||
|
||||
mRT = &mAuxillaryRT;
|
||||
U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled
|
||||
allocateScreenBuffer(res, res, samples);
|
||||
|
|
@ -1153,6 +1162,7 @@ void LLPipeline::refreshCachedSettings()
|
|||
RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier");
|
||||
RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples");
|
||||
RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization");
|
||||
RenderMirrors = gSavedSettings.getBOOL("RenderMirrors");
|
||||
sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled");
|
||||
RenderSpotLight = nullptr;
|
||||
|
||||
|
|
@ -2503,6 +2513,26 @@ void LLPipeline::doOcclusion(LLCamera& camera)
|
|||
|
||||
gGL.setColorMask(true, true);
|
||||
}
|
||||
|
||||
if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot)
|
||||
{
|
||||
gGL.setColorMask(false, false);
|
||||
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
|
||||
gOcclusionCubeProgram.bind();
|
||||
|
||||
if (mCubeVB.isNull())
|
||||
{ //cube VB will be used for issuing occlusion queries
|
||||
mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
mCubeVB->setBuffer();
|
||||
|
||||
mHeroProbeManager.doOcclusion();
|
||||
gOcclusionCubeProgram.unbind();
|
||||
|
||||
gGL.setColorMask(true, true);
|
||||
}
|
||||
|
||||
if (LLPipeline::sUseOcclusion > 1 &&
|
||||
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
|
||||
|
|
@ -3914,6 +3944,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)
|
|||
{
|
||||
//update reflection probe uniform
|
||||
mReflectionMapManager.updateUniforms();
|
||||
mHeroProbeManager.updateUniforms();
|
||||
}
|
||||
|
||||
U32 cur_type = 0;
|
||||
|
|
@ -8828,6 +8859,17 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
|
|||
mReflectionMapManager.mIrradianceMaps->bind(channel);
|
||||
bound = true;
|
||||
}
|
||||
|
||||
if (RenderMirrors)
|
||||
{
|
||||
channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY);
|
||||
if (channel > -1 && mHeroProbeManager.mTexture.notNull())
|
||||
{
|
||||
mHeroProbeManager.mTexture->bind(channel);
|
||||
bound = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (bound)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "lldrawable.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "llreflectionmapmanager.h"
|
||||
#include "llheroprobemanager.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
|
|
@ -459,6 +460,7 @@ public:
|
|||
void handleShadowDetailChanged();
|
||||
|
||||
LLReflectionMapManager mReflectionMapManager;
|
||||
LLHeroProbeManager mHeroProbeManager;
|
||||
|
||||
private:
|
||||
void unloadShaders();
|
||||
|
|
@ -1076,6 +1078,7 @@ public:
|
|||
static F32 RenderScreenSpaceReflectionAdaptiveStepMultiplier;
|
||||
static S32 RenderScreenSpaceReflectionGlossySamples;
|
||||
static S32 RenderBufferVisualization;
|
||||
static bool RenderMirrors;
|
||||
};
|
||||
|
||||
void render_bbox(const LLVector3 &min, const LLVector3 &max);
|
||||
|
|
|
|||
|
|
@ -482,7 +482,8 @@ Ndrg ↔ Nst
|
|||
<spinner label="Kraft X" name="FlexForceX"/>
|
||||
<spinner label="Kraft Y" name="FlexForceY"/>
|
||||
<spinner label="Kraft Z" name="FlexForceZ"/>
|
||||
<check_box label="Licht" name="Light Checkbox Ctrl" tool_tip="Verursacht, dass Objekt Licht emittiert"/>
|
||||
<check_box label="Spiegel" name="Mirror Checkbox Ctrl" tool_tip="Verursacht, dass das Objekt als Spiegel agiert"/>
|
||||
<check_box label="Licht" name="Light Checkbox Ctrl" tool_tip="Verursacht, dass das Objekt Licht emittiert"/>
|
||||
<color_swatch label="" name="colorswatch" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
|
||||
<texture_picker label="" name="light texture control" tool_tip="Klicken, um eine Bild auszuwählen (dieser Effekt funktioniert nur, wenn zeitversetzte Wiedergabe aktiviert ist)"/>
|
||||
<spinner label="Intensität" name="Light Intensity"/>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
<combo_box.item label="Terrain-Texturen" name="Textures"/>
|
||||
<combo_box.item label="Terrain-PBR-Materialien" name="PBRMaterials"/>
|
||||
</combo_box>
|
||||
<text name="detail_texture_text">
|
||||
Terrain-Texturen
|
||||
</text>
|
||||
<text name="detail_texture_text">
|
||||
Maximale Größe: 1024x1024
|
||||
</text>
|
||||
|
|
|
|||
|
|
@ -2931,15 +2931,23 @@ Low ↔ Lwst
|
|||
name="FlexForceZ"
|
||||
top_pad="4"
|
||||
width="128" />
|
||||
|
||||
<check_box
|
||||
height="16"
|
||||
label="Mirror"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
name="Mirror Checkbox Ctrl"
|
||||
tool_tip="Causes object to be a mirror"
|
||||
top_pad="8"
|
||||
width="60" />
|
||||
<check_box
|
||||
height="16"
|
||||
label="Light"
|
||||
layout="topleft"
|
||||
left="10"
|
||||
left_pad="10"
|
||||
name="Light Checkbox Ctrl"
|
||||
tool_tip="Causes object to emit light"
|
||||
top_pad="10"
|
||||
top_delta="0"
|
||||
width="60" />
|
||||
<color_swatch
|
||||
can_apply_immediately="true"
|
||||
|
|
|
|||
|
|
@ -92,6 +92,20 @@
|
|||
name="PBRMaterials"
|
||||
value="PBRMaterials" />
|
||||
</combo_box>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
halign="left"
|
||||
valign="center"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
name="detail_texture_text"
|
||||
top_delta="0"
|
||||
left_delta="0"
|
||||
width="170">
|
||||
Terrain Textures
|
||||
</text>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
|
|
@ -102,7 +116,7 @@
|
|||
layout="topleft"
|
||||
top_delta="0"
|
||||
left_delta="180"
|
||||
name="detail_texture_text"
|
||||
name="detail_texture_limits_text"
|
||||
width="200">
|
||||
Maximum size: 1024x1024
|
||||
</text>
|
||||
|
|
|
|||
Loading…
Reference in New Issue