diff options
Diffstat (limited to 'indra')
44 files changed, 1210 insertions, 57 deletions
| diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 756d0b5db8..f5966b71de 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -582,7 +582,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"); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 350d84ae6c..a86434fe65 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1825,6 +1825,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; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index d2adfa4a3d..1af9bca42e 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,6 +109,7 @@ public:          PARAMS_EXTENDED_MESH = 0x70,          PARAMS_RENDER_MATERIAL = 0x80,          PARAMS_REFLECTION_PROBE = 0x90, +        PARAMS_MIRROR = 0x100,  	};  public: @@ -172,6 +173,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; diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 71caff1686..ee2a4c769a 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -685,6 +685,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)  		mMaterialUpdatePending = true;  	}  	mMaterial = pMaterialParams; +      	return TEM_CHANGE_TEXTURE;  } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index f5f2c0172d..0935147688 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -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]; } diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ccfb8f69be..be5ad08fbe 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -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)      { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index b8071248e2..71b9b0f4fb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -57,6 +57,7 @@ public:      bool hasAlphaMask = false;      bool hasReflectionProbes = false;      bool attachNothing = false; +    bool hasHeroProbes = false;  };  // ============= Structure for caching shader uniforms =============== diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 0e7f9e1331..8ae23989c9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -238,6 +238,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)              return FALSE;          }  	} +     +    if (features->hasHeroProbes) +    { +        if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl")) +        { +            return FALSE; +        } +    }      if (features->hasShadows)  	{ @@ -643,6 +651,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) @@ -1248,6 +1257,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"); @@ -1260,6 +1272,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"); @@ -1453,6 +1466,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"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 79a24773e1..5824c03e2a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -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" @@ -279,6 +283,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" diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8eef7cd9d4..e180f8bf43 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -519,6 +519,7 @@ set(viewer_SOURCE_FILES      llrecentpeople.cpp      llreflectionmap.cpp      llreflectionmapmanager.cpp +    llheroprobemanager.cpp      llregioninfomodel.cpp      llregionposition.cpp      llremoteparcelrequest.cpp @@ -1158,6 +1159,7 @@ set(viewer_HEADER_FILES      llrecentpeople.h      llreflectionmap.h      llreflectionmapmanager.h +    llheroprobemanager.h      llregioninfomodel.h      llregionposition.h      llremoteparcelrequest.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5d8d4b199c..a6b9aa0526 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9186,6 +9186,17 @@        <real>0.00</real>      </array>    </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>1</integer> +  </map>    <key>RenderScreenSpaceReflections</key>    <map>      <key>Comment</key> @@ -10390,6 +10401,39 @@        <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> diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 7cdddfe8db..65706e2c3f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -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  } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index faa273b834..9b98a37925 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -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)      { diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 9ecdf0bf77..cb6f34713c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -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;  }  // ============================================================================================================= diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index acff03ec4b..db0daa9b7e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -49,6 +49,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; @@ -70,12 +87,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; @@ -289,6 +306,7 @@ float getShadow(vec3 pos, vec3 norm)  void main()  { +    applyClip(vary_position);      waterClip();      // diffcol == diffuse map combined with vertex color @@ -416,9 +434,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  } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 906e66ecc8..d9dc83bb10 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -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; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 35e99c5bd2..8b7aea24ed 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -32,6 +32,14 @@ uniform sampler2D specularRect;  uniform sampler2D normalMap;  uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl +uniform samplerCubeArray   heroProbes; + +layout (std140) uniform HeroProbeData +{ +    vec4 heroPosition[1]; +    int heroProbeCount; +}; +  const float M_PI = 3.14159265;  #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO) @@ -108,8 +116,8 @@ vec3 pbrBaseLight(vec3 diffuseColor,                    vec3 additive,                    vec3 atten); -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,  -                    float perceptualRoughness,  +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, +                    float perceptualRoughness,                      float metallic,                      vec3 n, // normal                      vec3 v, // surface point to camera @@ -182,9 +190,9 @@ void main()      vec3  irradiance = vec3(0);      vec3  radiance  = vec3(0); -    if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) +    if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR))      { -        vec3 orm = texture(specularRect, tc).rgb;  +        vec3 orm = texture(specularRect, tc).rgb;          float perceptualRoughness = orm.g;          float metallic = orm.b;          float ao = orm.r; @@ -204,10 +212,16 @@ 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); +        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; +                  if (do_atmospherics)          {              color = atmosFragLightingLinear(color, additive, atten);          } +              }      else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))      { @@ -265,6 +279,9 @@ void main()              // add radiance map              applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); + +            color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; +          }          color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a); @@ -280,14 +297,11 @@ void main()              color = atmosFragLightingLinear(color, additive, atten);          }     } - -      #ifdef WATER_FOG          vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));          color       = fogged.rgb;      #endif -      frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results      frag_color.a = 0.0;  } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e20658d327..fbf52ad2d8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1518,6 +1518,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; diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 970e8c8b2a..fc182fc2e2 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -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: diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 6a7e05ac74..373103ce0a 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -190,6 +190,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; ) diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c1776705f9..2c04224fa0 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -488,6 +488,11 @@ U16 LLFace::getGeometry(LLStrider<LLVector3> &vertices, LLStrider<LLVector3> &no  	return mGeomIndex;  } +LLVector3 LLFace::getAverageNormal() +{ +    return mAverageNormal; +} +  void LLFace::updateCenterAgent()  {  	if (mDrawablep->isActive()) @@ -1889,14 +1894,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			F32* normals = (F32*) norm.get();  			LLVector4a* src = vf.mNormals;  			LLVector4a* end = src+num_vertices; -			 + +            LLVector4a normal_total; +  			while (src < end)  			{	  				LLVector4a normal;  				mat_normal.rotate(*src++, normal);  				normal.store4a(normals); +                normal_total.add(normal);  				normals += 4;  			} + +			normal_total.div(LLVector4a(num_vertices)); + +			mAverageNormal = LLVector3(normal_total[0], normal_total[1], normal_total[2]);  		}  		if (rebuild_tangent) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index eb3b47d6d6..d4f4313073 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -176,6 +176,8 @@ public:  								LLStrider<LLVector3> &normals,  								LLStrider<LLVector2> &texCoords,   								LLStrider<U16>  &indices); +     +    LLVector3       getAverageNormal();  	S32 getColors(LLStrider<LLColor4U> &colors);  	S32 getIndices(LLStrider<U16> &indices); @@ -278,6 +280,9 @@ private:  	U32			mIndicesCount;  	U32			mIndicesIndex;		// index into mVertexBuffer's index array  	S32         mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; +     +    LLVector3   mAverageNormal; +    bool        mHasAverageNormal;  	LLXformMatrix* mXform; diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1fb3577dd7..9590066b55 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -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); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp new file mode 100644 index 0000000000..b6db123cd9 --- /dev/null +++ b/indra/newview/llheroprobemanager.cpp @@ -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::sReflectionProbesEnabled || 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->mirrorPlacementMode(); +            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; +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h new file mode 100644 index 0000000000..68cfdbfd99 --- /dev/null +++ b/indra/newview/llheroprobemanager.h @@ -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; +}; + diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index cb28fb4770..51aa2f4891 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1768,6 +1768,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)  					getChild<LLUICtrl>("shinyOffsetV")->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);  				} diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index d36662c11b..89c3c67286 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -143,6 +143,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(); @@ -232,7 +233,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); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index d6c36bbfb7..2bad5d4235 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -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); @@ -305,6 +310,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); @@ -746,6 +755,21 @@ 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 LLPanelVolume::sendIsReflectionProbe()  {      LLViewerObject* objectp = mObject; @@ -1412,6 +1436,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)  { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 01b7ebb75c..a658351624 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -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); diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index ec54fa1165..5fc9851709 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -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() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 7ea0fe6187..9e888f20d0 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -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;  }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 915c8893a4..b793cc3bdd 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -300,8 +300,8 @@ void LLReflectionMapManager::update()              }          } -        if (realtime &&  -            closestDynamic == nullptr &&  +        if (realtime && +            closestDynamic == nullptr &&              probe->mCubeIndex != -1 &&              probe->getIsDynamic())          { @@ -316,7 +316,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; @@ -556,7 +556,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. @@ -717,6 +717,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(); @@ -881,14 +882,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 @@ -900,14 +901,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); @@ -1124,7 +1125,7 @@ void LLReflectionMapManager::setUniforms()      }      if (mUBO == 0) -    {  +    {          updateUniforms();      }      glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); @@ -1305,8 +1306,8 @@ void LLReflectionMapManager::initReflectionMaps()      }  } -void LLReflectionMapManager::cleanup()  -{  +void LLReflectionMapManager::cleanup() +{      mVertexBuffer = nullptr;      mRenderTarget.release(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index b77a33da89..72707df7b0 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -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 @@ -108,6 +110,7 @@ public:  private:      friend class LLPipeline; +    friend class LLHeroProbeManager;      // initialize mCubeFree array to default values      void initCubeFree(); @@ -119,7 +122,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) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 04ca62e0ec..a1e7d69ae4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1063,7 +1063,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; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a1d068461e..74d9397318 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -313,7 +313,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mLastUpdateCached(FALSE),  	mCachedMuteListUpdateTime(0),  	mCachedOwnerInMuteList(false), -	mRiggedAttachedWarned(false) +	mRiggedAttachedWarned(false), +mIsMirror(false), +mMirrorPlacementMode(3)  {  	if (!is_global)  	{ @@ -1147,6 +1149,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, @@ -1523,11 +1558,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  					std::string temp_string;  					mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); +                    detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); +                      					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); @@ -1907,6 +1945,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				{  					std::string temp_string;  					dp->unpackString(temp_string, "Text"); +                     +                    detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); +                      					LLColor4U coloru;  					dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");  					coloru.mV[3] = 255 - coloru.mV[3]; @@ -5303,7 +5344,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 @@ -6237,6 +6277,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para            new_block = new LLReflectionProbeParams();            break;        } +      case LLNetworkData::PARAMS_MIRROR: +      { +          new_block = new LLMirrorParams(); +          break; +      }  	  default:  	  {  		  LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 898b21e1ae..c165f164a8 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -257,6 +257,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   mirrorPlacementMode() 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  @@ -877,6 +879,9 @@ protected:  	F32 mPhysicsCost;  	F32 mLinksetPhysicsCost; +    bool    mIsMirror; +    U8      mMirrorPlacementMode; +          // If true, "shrink wrap" this volume in its spatial partition.  See "shrinkWrap"      bool mShouldShrinkWrap = false; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 61ccc1d43f..2380e112aa 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2074,6 +2074,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()              gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1");          } +        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); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ba2b6e1c7c..e0ec8eec25 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5304,7 +5304,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; @@ -5335,6 +5335,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[] = { @@ -5441,6 +5449,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; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6e8a5b2f4e..4da6a1360f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -374,7 +374,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 diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index ec2f490742..91e64d611c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -249,6 +249,9 @@ LLVOVolume::~LLVOVolume()  	mTextureAnimp = NULL;  	delete mVolumeImpl;  	mVolumeImpl = NULL; +     +    if (mIsMirror) +        gPipeline.mHeroProbeManager.unregisterHeroDrawable(this);  	gMeshRepo.unregisterMesh(this); @@ -996,7 +999,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); @@ -3319,6 +3327,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::mirrorPlacementMode() const +{ +    return mMirrorPlacementMode; +} +  BOOL LLVOVolume::isReflectionProbe() const  {      return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -4369,6 +4419,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() diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index aadc1fbcf3..848f455e2a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -294,6 +294,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   mirrorPlacementMode() const override;      // Reflection Probes      bool setIsReflectionProbe(BOOL is_probe); @@ -307,6 +312,8 @@ public:      F32 getReflectionProbeNearClip() const;      bool getReflectionProbeIsBox() const;      bool getReflectionProbeIsDynamic() const; +     +    BOOL isMirror() const override;  	// Flexible Objects  	U32 getVolumeInterfaceID() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9266c84540..c18f503c61 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -637,6 +637,7 @@ void LLPipeline::cleanup()  	mCubeVB = NULL;      mReflectionMapManager.cleanup(); +    mHeroProbeManager.cleanup();  }  //============================================================================ @@ -767,6 +768,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)      { // hacky -- allocate auxillary buffer          gCubeSnapshot = TRUE;          mReflectionMapManager.initReflectionMaps(); +        mHeroProbeManager.initReflectionMaps();          mRT = &mAuxillaryRT;          U32 res = mReflectionMapManager.mProbeResolution * 4;  //multiply by 4 because probes will be 16x super sampled          allocateScreenBuffer(res, res, samples); @@ -2402,6 +2404,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)) @@ -3779,6 +3801,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)          {              //update reflection probe uniform              mReflectionMapManager.updateUniforms(); +            mHeroProbeManager.updateUniforms();          }  		U32 cur_type = 0; @@ -8444,6 +8467,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)          mReflectionMapManager.mIrradianceMaps->bind(channel);          bound = true;      } +     +    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)      { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index d4c6432e55..299eaedea7 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -39,6 +39,7 @@  #include "lldrawable.h"  #include "llrendertarget.h"  #include "llreflectionmapmanager.h" +#include "llheroprobemanager.h"  #include <stack> @@ -448,6 +449,7 @@ public:      void handleShadowDetailChanged();      LLReflectionMapManager mReflectionMapManager; +    LLHeroProbeManager mHeroProbeManager;  private:  	void unloadShaders(); diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 9966fe0b56..510351b471 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2410,7 +2410,15 @@ even though the user gets a free copy.               name="object_horizontal"               top_pad="10"               width="278" /> - +            <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" | 
