diff --git a/indra/newview/app_settings/settings_alchemy.xml b/indra/newview/app_settings/settings_alchemy.xml index 54224097ef..4f3f51cc00 100644 --- a/indra/newview/app_settings/settings_alchemy.xml +++ b/indra/newview/app_settings/settings_alchemy.xml @@ -2446,13 +2446,13 @@ AlchemyRenderTerrainTessDensity Comment - Base density of the terrain tessellation: metres of patch edge per level, divided by the distance to the camera, so at 64 a 16 m patch is split 64 ways (25 cm) within 16 m of the camera, 16 ways (1 m) at 64 m and not at all past 1 km. The terrain detail slider multiplies it. Triangle count grows with the square; clamped to 8 to 256. + Base density of the terrain tessellation: metres of patch edge per level, divided by the distance to the camera, so at 48 a 16 m patch is split 48 ways (33 cm) within 16 m of the camera, 12 ways (1.3 m) at 64 m and not at all past 768 m. The terrain detail slider multiplies it. Triangle count grows with the square; clamped to 8 to 256. Persist 1 Type F32 Value - 64 + 48 AlchemyRenderTerrainTessRasterSegment diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index 6b421511e3..48d196df16 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -34,8 +34,6 @@ bool isFarDepth(float d); // deferredUtil.glsl -- depth-convention a vec4 getWaterFogView(vec3 pos); -uniform int above_water; - // Void water has no floor. The sky behind it keeps the cleared far depth, which an infinite projection // reconstructs a thousand km out and a finite one at its far plane, wherever that falls relative to the surface; // it is fogged instead as water this deep past where the ray enters, at any distance. @@ -45,28 +43,8 @@ uniform vec4 waterPlane; void main() { vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5; + // From above, the hardware depth test (LLPipeline::doWaterHaze) keeps the field off what lies in front of it. float depth = getDepth(tc.xy); - if (above_water > 0) - { - // we want to depth test when the camera is above water, but some GPUs have a hard time - // with depth testing against render targets that are bound for sampling in the same shader - // so we do it manually here - - // The matching hardware LLGLDepthTest in pipeline.cpp auto-translates its func under - // reverse-Z; keep this in sync. Under reverse-Z clip.z/clip.w is already the [0,1] - // ndc z (no *0.5+0.5), and "fragment behind stored geometry" is the smaller depth. -#ifdef REVERSE_Z - float cur_depth = vary_fragcoord.z/vary_fragcoord.w; - if (cur_depth < depth) -#else - float cur_depth = vary_fragcoord.z/vary_fragcoord.w*0.5+0.5; - if (cur_depth > depth) -#endif - { - discard; - } - - } vec4 pos = getPositionWithDepth(tc, depth); diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index fb3519a475..fbb54341a3 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -55,12 +55,13 @@ in vec3 view; in vec3 vary_position; vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color); -void mirrorClip(vec3 position); +bool mirrorClipped(vec3 position); void water_wave_normals(sampler2D map_a, sampler2D map_b, vec2 r, out vec3 big, out vec3 little_xy, out vec3 little_zw); void main() { - mirrorClip(vary_position); + // Discarded at the end: the wave normals take derivatives. + bool clipped = mirrorClipped(vary_position); vec2 screen_tc = gl_FragCoord.xy / screen_res; vec4 color; @@ -84,5 +85,14 @@ void main() fb = applyWaterFogViewLinearNoClip(vary_position, fb); + // Compiled only in the mirror variant: a discard the compiler cannot see is dead costs every fragment its early + // depth test. +#ifdef MIRROR_CLIP + if (clipped) + { + discard; + } +#endif + frag_color = max(fb, vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index d7696e4004..21e7d75168 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -40,7 +40,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color); -void mirrorClip(vec3 pos); +bool mirrorClipped(vec3 pos); // PBR interface vec2 BRDF(float NoV, float roughness); @@ -130,7 +130,8 @@ void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave void main() { - mirrorClip(vary_position); + // Discarded at the end: the wave normals and the shadow take derivatives. + bool clipped = mirrorClipped(vary_position); // The plane's frame and the light in eye space, the same at every point: agent z and x through the view. vec3 vN = normal_matrix[2]; @@ -326,6 +327,15 @@ void main() } } + // Compiled only in the mirror variant: a discard the compiler cannot see is dead costs every fragment its early + // depth test. +#ifdef MIRROR_CLIP + if (clipped) + { + discard; + } +#endif + // Not capped at 1: the glint and bright reflections are HDR and have to reach white and bloom, and // what shows through the surface must match the shore beside it. The alpha is the glint's glow, which // the pool adds to the glow of what lies beneath. diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 757c27276a..cd6ce03f81 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -86,7 +86,7 @@ namespace // Pinned (density 0, which terrainTC reads as the grid's level) exactly when the programs were built with the // spacing that cuts the grid's level into its segments (TERRAIN_TESS_PINNED), from the same latched input, and // above 0 otherwise whatever a debug RenderTerrainLODFactor says. - static LLCachedControl tess_density(gSavedSettings, "AlchemyRenderTerrainTessDensity", 64.f); + static LLCachedControl tess_density(gSavedSettings, "AlchemyRenderTerrainTessDensity", 48.f); static LLCachedControl raster_segment(gSavedSettings, "AlchemyRenderTerrainTessRasterSegment", 8.f); const F32 density = gPipeline.shaderInputs().mLocal.mTerrainTessPinned ? 0.f diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 453c82752d..da39c15dca 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -12420,6 +12420,13 @@ void LLPipeline::doWaterHaze() return; } + // Nor where this view's water does not refract (ALRenderResourcePlan::refractsWater): its opaque surface hides what + // lies under it, which is all the haze fogs, and where an exclusion prim removed it the haze fogs nothing either. + if (!sUnderWaterRender && !ALRenderResourcePlan::refractsWater(renderPack(), sRenderTransparentWater)) + { + return; + } + if (RenderDeferredAtmospheric) { // The scene's depth as the haze reads it, after the pools before it wrote it in this binding.