diff options
-rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
-rw-r--r-- | indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 145 | ||||
-rw-r--r-- | indra/newview/pipeline.cpp | 3 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 9 |
4 files changed, 166 insertions, 2 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3bd49b7c4e..ac449e45ef 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10239,6 +10239,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>RenderReflectionProbeVolumes</key> + <map> + <key>Comment</key> + <string>Render influence volumes of Reflection Probes</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderMaxPartCount</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 977b2e6b24..865b7e7a47 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -262,6 +262,40 @@ vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2) return v; } +void swap(inout float a, inout float b) +{ + float t = a; + a = b; + b = a; +} + +// debug implementation, make no assumptions about origin +bool sphereIntersectDebug(vec3 origin, vec3 dir, vec3 center, float radius2, out float t) +{ + float t0, t1; // solutions for t if the ray intersects + + // geometric solution + vec3 L = center - origin; + float tca = dot(L, dir); + // if (tca < 0) return false; + float d2 = dot(L, L) - tca * tca; + if (d2 > radius2) return false; + float thc = sqrt(radius2 - d2); + t0 = tca - thc; + t1 = tca + thc; + + if (t0 > t1) swap(t0, t1); + + if (t0 < 0) { + t0 = t1; // if t0 is negative, let's use t1 instead + if (t0 < 0) return false; // both t0 and t1 are negative + } + + t = t0; + + return true; +} + // from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ /* vec3 DirectionWS = normalize(PositionWS - CameraWS); @@ -310,6 +344,48 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i) return IntersectPositionCS; } +// cribbed from https://iquilezles.org/articles/intersectors/ +// axis aligned box centered at the origin, with size boxSize +bool boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, out bool behind) +{ + vec3 rd = normalize(p-ro); + + vec3 m = 1.0/rd; // can precompute if traversing a set of aligned boxes + vec3 n = m*ro; // can precompute if traversing a set of aligned boxes + vec3 k = abs(m)*boxSize; + vec3 t1 = -n - k; + vec3 t2 = -n + k; + float tN = max( max( t1.x, t1.y ), t1.z ); + float tF = min( min( t2.x, t2.y ), t2.z ); + if( tN>tF || tF<0.0) return false; // no intersection + + float t = tN < 0 ? tF : tN; + + vec3 v = ro + rd * t; + + v -= ro; + vec3 pos = p - ro; + + behind = dot(v,v) > dot(pos,pos); + + return true; +} + +bool boxIntersectDebug(vec3 origin, vec3 pos, int i, out bool behind) +{ + mat4 clipToLocal = refBox[i]; + + // transform into unit cube space + origin = (clipToLocal * vec4(origin, 1.0)).xyz; + pos = (clipToLocal * vec4(pos, 1.0)).xyz; + + if (boxIntersectionDebug(origin, pos, vec3(1), behind)) + { + return true; + } + + return false; +} // Tap a reflection probe @@ -518,11 +594,76 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, glossenv = sampleProbes(pos, normalize(refnormpersp), lod, errorCorrect); } +void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) +{ + vec3 origin = vec3(0,0,0); + + bool manual_probe = abs(refIndex[i].w) > 2; + + if (refIndex[i].w < 0) + { + vec3 v; + bool behind; + + if (boxIntersectDebug(origin, pos, i, behind)) + { + float w = 0.5; + if (behind) + { + w *= 0.5; + col += vec4(0,0,w,w); + } + else + { + col += vec4(w,w,0,w); + } + } + } + else + { + float r = refSphere[i].w; // radius of sphere volume + float rr = r * r; // radius squared + + float t = 0.0; + + if (sphereIntersectDebug(origin, dir, refSphere[i].xyz, rr, t)) + { + if (t > depth) + { + float w = 0.25/((t-depth)*0.125 + 1.0); + + if (manual_probe) + { + col += vec4(0, 0, w, w); + } + } + else + { + if (manual_probe) + { + float w = 0.5; + + col += vec4(w,w,0,w); + } + } + } + } +} + vec4 sampleReflectionProbesDebug(vec3 pos) { - preProbeSample(pos); + vec4 col = vec4(0,0,0,0); + + vec3 dir = normalize(pos); + + float d = length(pos); - return vec4(probeInfluences*0.25, 0, 0, probeInfluences*0.25); + for (int i = 1; i < refmapCount; ++i) + { + debugTapRefMap(pos, dir, d, i, col); + } + + return col; } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9d792d0801..7bc819d553 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5237,7 +5237,10 @@ void LLPipeline::renderDebug() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_REFLECTION_PROBES) && !hud_only) { mReflectionMapManager.renderDebug(); + } + if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes")) + { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("probe debug display"); bindDeferredShader(gReflectionProbeDisplayProgram, NULL); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index bb9aab9ec0..2512fadec7 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1465,6 +1465,15 @@ function="World.EnvPreset" function="Tools.ShowSelectionLightRadius" /> </menu_item_check> <menu_item_check + label="Show Reflection Probe Volumes" + name="Show Reflection Probe Volumes"> + <menu_item_check.on_check + control="RenderReflectionProbeVolumes" /> + <menu_item_check.on_click + function="ToggleControl" + parameter="RenderReflectionProbeVolumes" /> + </menu_item_check> + <menu_item_check label="Show Selection Beam" name="Show Selection Beam"> <menu_item_check.on_check |