diff options
| -rw-r--r-- | indra/llrender/llglslshader.h | 1 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl | 50 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl | 16 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/materialF.glsl | 64 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl | 44 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl | 476 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl | 436 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolbump.cpp | 9 | ||||
| -rw-r--r-- | indra/newview/llreflectionmapmanager.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llviewershadermgr.cpp | 14 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 53 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 4 | 
13 files changed, 686 insertions, 491 deletions
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index fe0aaae467..6b4778c270 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -58,6 +58,7 @@ public:  	S32 mIndexedTextureChannels;  	bool disableTextureIndex;  	bool hasAlphaMask; +    bool hasReflectionProbes = false;  	bool attachNothing;  	// char numLights; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 8e8f44e99b..bdc1f78201 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -218,6 +218,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		}  	} +    if (features->hasReflectionProbes) +    { +        if (!shader->attachFragmentObject("deferred/reflectionProbeF.glsl")) +        { +            return FALSE; +        } +    } +      if (features->hasAmbientOcclusion)  	{          if (!shader->attachFragmentObject("deferred/aoUtil.glsl")) diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl index 9fcee04c32..a04f611440 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl @@ -35,10 +35,11 @@ out vec4 frag_color;  uniform sampler2D diffuseMap;  #endif +  VARYING vec4 vertex_color;  VARYING vec2 vary_texcoord0;  VARYING vec3 vary_texcoord1; -VARYING vec4 vary_position; +VARYING vec3 vary_position;  uniform samplerCube environmentMap; @@ -54,6 +55,14 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou  vec3 linear_to_srgb(vec3 c);  vec3 srgb_to_linear(vec3 c); +#ifdef HAS_REFLECTION_PROBES +// reflection probe interface +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,  +        vec3 pos, vec3 norm, float glossiness, float envIntensity); +void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); +void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); +#endif +  // See:  //   class1\deferred\fullbrightShinyF.glsl  //   class1\lighting\lightFullbrightShinyF.glsl @@ -70,21 +79,29 @@ void main()  	// SL-9632 HUDs are affected by Atmosphere  	if (no_atmo == 0)  	{ -	vec3 sunlit; -	vec3 amblit; -	vec3 additive; -	vec3 atten; -		vec3 pos = vary_position.xyz/vary_position.w; - -	calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false); -	 -	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	 -	float env_intensity = vertex_color.a; - -	//color.rgb = srgb_to_linear(color.rgb); -		color.rgb = mix(color.rgb, envColor.rgb, env_intensity); -	color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten); -	color.rgb = fullbrightScaleSoftClip(color.rgb); +        vec3 sunlit; +        vec3 amblit; +        vec3 additive; +        vec3 atten; +        vec3 pos = vary_position; +        calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false); + +        float env_intensity = vertex_color.a; +#ifndef HAS_REFLECTION_PROBES +        vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	 +        color.rgb = mix(color.rgb, envColor.rgb, env_intensity); +#else +        vec3 ambenv; +        vec3 glossenv; +        vec3 legacyenv; +        vec3 norm = normalize(vary_texcoord1.xyz); +        vec4 spec = vec4(0,0,0,0); +        sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, env_intensity); +        legacyenv *= 1.5; // fudge brighter +        applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity); +#endif +        color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten); +        color.rgb = fullbrightScaleSoftClip(color.rgb);  	}  /* @@ -98,7 +115,6 @@ void main()  */  	color.a = 1.0; -  	//color.rgb = linear_to_srgb(color.rgb);  	frag_color = color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl index 2c139430e7..a897198062 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl @@ -44,7 +44,7 @@ ATTRIBUTE vec2 texcoord0;  VARYING vec4 vertex_color;  VARYING vec2 vary_texcoord0;  VARYING vec3 vary_texcoord1; -VARYING vec4 vary_position; +VARYING vec3 vary_position;  #ifdef HAS_SKIN  mat4 getObjectSkinnedTransform(); @@ -61,17 +61,23 @@ void main()      mat4 mat = getObjectSkinnedTransform();      mat = modelview_matrix * mat;      vec4 pos = mat * vert; -    vary_position = gl_Position = projection_matrix * pos; +    gl_Position = projection_matrix * pos;  	vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);  #else  	vec4 pos = (modelview_matrix * vert); -	vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); +	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);  	vec3 norm = normalize(normal_matrix * normal);  #endif -	vec3 ref = reflect(pos.xyz, -norm); -	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; +    vary_position = pos.xyz; +    vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + +#ifndef HAS_REFLECTION_PROBES	 +    vec3 ref = reflect(pos.xyz, -norm);  	vary_texcoord1 = transpose(normal_matrix) * ref.xyz; +#else +    vary_texcoord1 = norm; +#endif  	calcAtmospherics(pos.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index 02d83925ea..c5b1937cfb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -64,6 +64,13 @@ out vec4 frag_color;  float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);  #endif +#ifdef HAS_REFLECTION_PROBES +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,  +        vec3 pos, vec3 norm, float glossiness, float envIntensity); +void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); +void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); +#endif +  uniform samplerCube environmentMap;  uniform sampler2D     lightFunc; @@ -322,6 +329,16 @@ void main()      // lighting from the sun stays sharp      float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);      da = pow(da, 1.0 / 1.3); +    vec3 sun_contrib = min(da, shadow) * sunlit; + +#ifdef HAS_REFLECTION_PROBES +    vec3 ambenv; +    vec3 glossenv; +    vec3 legacyenv; +    sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity); +    amblit = max(ambenv, amblit); +    color.rgb = amblit; +#else      color = amblit; @@ -333,9 +350,8 @@ void main()      ambient *= ambient;      ambient = (1.0 - ambient); -    vec3 sun_contrib = min(da, shadow) * sunlit; -          color *= ambient; +#endif      color += sun_contrib; @@ -345,35 +361,6 @@ void main()      if (spec.a > 0.0)  // specular reflection      { -        /*  // Reverting this specular calculation to previous 'dumbshiny' version - DJH 6/17/2020 -            // Preserving the refactored version as a comment for potential reconsideration, -            // overriding the general rule to avoid pollutiong the source with commented code. -            // -            //  If you're reading this in 2021+, feel free to obliterate. - -        vec3 npos = -normalize(pos.xyz); - -        //vec3 ref = dot(pos+lv, norm); -        vec3 h = normalize(light_dir.xyz + npos); -        float nh = dot(norm.xyz, h); -        float nv = dot(norm.xyz, npos); -        float vh = dot(npos, h); -        float sa = nh; -        float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5; - -        float gtdenom = 2 * nh; -        float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh)); - -        if (nh > 0.0) -        { -            float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da); -            vec3 sp = sun_contrib*scol / 6.0f; -            sp = clamp(sp, vec3(0), vec3(1)); -            bloom = dot(sp, sp) / 4.0; -            color += sp * spec.rgb; -        } -        */ -          float sa        = dot(refnormpersp, sun_dir.xyz);          vec3  dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r); @@ -385,10 +372,24 @@ void main()          glare = max(glare, spec_contrib.b);          color += spec_contrib; + +#ifdef HAS_REFLECTION_PROBES +        applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); +#endif      } +      color = mix(color.rgb, diffcol.rgb, diffuse.a); +#ifdef HAS_REFLECTION_PROBES +    if (envIntensity > 0.0) +    {  // add environmentmap +        //fudge darker +        legacyenv *= 0.5*diffuse.a+0.5; +         +        applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); +    } +#else      if (envIntensity > 0.0)      {          //add environmentmap @@ -403,6 +404,7 @@ void main()          cur_glare *= envIntensity*4.0;          glare += cur_glare;      } +#endif      color = atmosFragLighting(color, additive, atten);      color = scaleSoftClipFrag(color); diff --git a/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl new file mode 100644 index 0000000000..8f3e38b08b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl @@ -0,0 +1,44 @@ +/** + * @file class1/deferred/reflectionProbeF.glsl + * + * $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$ + */ + +// fallback stub -- will be used if actual reflection probe shader failed to load (output pink so it's obvious) +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,  +        vec3 pos, vec3 norm, float glossiness, float envIntensity) +{ +    ambenv = vec3(1,0,1); +    glossenv = vec3(1,0,1); +    legacyenv = vec3(1,0,1); +} + +void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm) +{ +    color = vec3(1,0,1); +} + +void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity) +{ +    color = vec3(1,0,1); +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl new file mode 100644 index 0000000000..8c1323ba1a --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -0,0 +1,476 @@ +/** + * @file class2/deferred/reflectionProbeF.glsl + * + * $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$ + */ + +#extension GL_ARB_shader_texture_lod : enable + +#define FLT_MAX 3.402823466e+38 + +#define REFMAP_COUNT 256 +#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider + +uniform samplerCubeArray   reflectionProbes; + +layout (std140, binding = 1) uniform ReflectionProbes +{ +    // list of OBBs for user override probes +    // box is a set of 3 planes outward facing planes and the depth of the box along that plane +    // for each box refBox[i]... +    /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation +    //  box[3][0..2] - plane thickness +    mat4 refBox[REFMAP_COUNT]; +    // list of bounding spheres for reflection probes sorted by distance to camera (closest first) +    vec4 refSphere[REFMAP_COUNT]; +    // index  of cube map in reflectionProbes for a corresponding reflection probe +    // e.g. cube map channel of refSphere[2] is stored in refIndex[2] +    // refIndex.x - cubemap channel in reflectionProbes +    // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index) +    // refIndex.z - number of neighbors +    // refIndex.w - priority, if negative, this probe has a box influence +    ivec4 refIndex[REFMAP_COUNT]; + +    // neighbor list data (refSphere indices, not cubemap array layer) +    ivec4 refNeighbor[1024]; + +    // number of reflection probes present in refSphere +    int refmapCount; + +    // intensity of ambient light from reflection probes +    float reflectionAmbiance; +}; + +// Inputs +uniform mat3 env_mat; + +// list of probeIndexes shader will actually use after "getRefIndex" is called +// (stores refIndex/refSphere indices, NOT rerflectionProbes layer) +int probeIndex[REF_SAMPLE_COUNT]; + +// number of probes stored in probeIndex +int probeInfluences = 0; + +bool isAbove(vec3 pos, vec4 plane) +{ +    return (dot(plane.xyz, pos) + plane.w) > 0; +} + +// return true if probe at index i influences position pos +bool shouldSampleProbe(int i, vec3 pos) +{ +    if (refIndex[i].w < 0) +    { +        vec4 v = refBox[i] * vec4(pos, 1.0); +        if (abs(v.x) > 1 ||  +            abs(v.y) > 1 || +            abs(v.z) > 1) +        { +            return false; +        } +    } +    else +    { +        vec3 delta = pos.xyz - refSphere[i].xyz; +        float d = dot(delta, delta); +        float r2 = refSphere[i].w; +        r2 *= r2; + +        if (d > r2) +        { //outside bounding sphere +            return false; +        } +    } + +    return true; +} + +// call before sampleRef +// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT +// overall algorithm --  +void preProbeSample(vec3 pos) +{ +    // TODO: make some sort of structure that reduces the number of distance checks + +    for (int i = 0; i < refmapCount; ++i) +    { +        // found an influencing probe +        if (shouldSampleProbe(i, pos)) +        { +            probeIndex[probeInfluences] = i; +            ++probeInfluences; + +            int neighborIdx = refIndex[i].y; +            if (neighborIdx != -1) +            { +                int neighborCount = min(refIndex[i].z, REF_SAMPLE_COUNT-1); + +                int count = 0; +                while (count < neighborCount) +                { +                    // check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index) + +                    int idx = refNeighbor[neighborIdx].x; +                    if (shouldSampleProbe(idx, pos)) +                    { +                        probeIndex[probeInfluences++] = idx; +                        if (probeInfluences == REF_SAMPLE_COUNT) +                        { +                            return; +                        } +                    } +                    count++; +                    if (count == neighborCount) +                    { +                        return; +                    } + +                    idx = refNeighbor[neighborIdx].y; +                    if (shouldSampleProbe(idx, pos)) +                    { +                        probeIndex[probeInfluences++] = idx; +                        if (probeInfluences == REF_SAMPLE_COUNT) +                        { +                            return; +                        } +                    } +                    count++; +                    if (count == neighborCount) +                    { +                        return; +                    } + +                    idx = refNeighbor[neighborIdx].z; +                    if (shouldSampleProbe(idx, pos)) +                    { +                        probeIndex[probeInfluences++] = idx; +                        if (probeInfluences == REF_SAMPLE_COUNT) +                        { +                            return; +                        } +                    } +                    count++; +                    if (count == neighborCount) +                    { +                        return; +                    } + +                    idx = refNeighbor[neighborIdx].w; +                    if (shouldSampleProbe(idx, pos)) +                    { +                        probeIndex[probeInfluences++] = idx; +                        if (probeInfluences == REF_SAMPLE_COUNT) +                        { +                            return; +                        } +                    } +                    count++; +                    if (count == neighborCount) +                    { +                        return; +                    } + +                    ++neighborIdx; +                } + +                return; +            } +        } +    } +} + +// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection + +// original reference implementation: +/* +bool intersect(const Ray &ray) const  +{  +        float t0, t1; // solutions for t if the ray intersects  +#if 0  +        // geometric solution +        Vec3f L = center - orig;  +        float tca = L.dotProduct(dir);  +        // if (tca < 0) return false; +        float d2 = L.dotProduct(L) - tca * tca;  +        if (d2 > radius2) return false;  +        float thc = sqrt(radius2 - d2);  +        t0 = tca - thc;  +        t1 = tca + thc;  +#else  +        // analytic solution +        Vec3f L = orig - center;  +        float a = dir.dotProduct(dir);  +        float b = 2 * dir.dotProduct(L);  +        float c = L.dotProduct(L) - radius2;  +        if (!solveQuadratic(a, b, c, t0, t1)) return false;  +#endif  +        if (t0 > t1) std::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;  +} */ + +// adapted -- assume that origin is inside sphere, return distance from origin to edge of sphere +vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2) +{  +        float t0, t1; // solutions for t if the ray intersects  + +        vec3 L = center - origin;  +        float tca = dot(L,dir); + +        float d2 = dot(L,L) - tca * tca;  + +        float thc = sqrt(radius2 - d2);  +        t0 = tca - thc;  +        t1 = tca + thc;  +  +        vec3 v = origin + dir * t1; +        return v;  +}  + +// from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ +/* +vec3 DirectionWS = normalize(PositionWS - CameraWS); +vec3 ReflDirectionWS = reflect(DirectionWS, NormalWS); + +// Intersection with OBB convertto unit box space +// Transform in local unit parallax cube space (scaled and rotated) +vec3 RayLS = MulMatrix( float(3x3)WorldToLocal, ReflDirectionWS); +vec3 PositionLS = MulMatrix( WorldToLocal, PositionWS); + +vec3 Unitary = vec3(1.0f, 1.0f, 1.0f); +vec3 FirstPlaneIntersect  = (Unitary - PositionLS) / RayLS; +vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; +vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); +float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); + +// Use Distance in WS directly to recover intersection +vec3 IntersectPositionWS = PositionWS + ReflDirectionWS * Distance; +vec3 ReflDirectionWS = IntersectPositionWS - CubemapPositionWS; + +return texCUBE(envMap, ReflDirectionWS); +*/ + +// get point of intersection with given probe's box influence volume +// origin - ray origin in clip space +// dir - ray direction in clip space +// i - probe index in refBox/refSphere +vec3 boxIntersect(vec3 origin, vec3 dir, int i) +{ +    // Intersection with OBB convertto unit box space +    // Transform in local unit parallax cube space (scaled and rotated) +    mat4 clipToLocal = refBox[i]; + +    vec3 RayLS = mat3(clipToLocal) * dir; +    vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; + +    vec3 Unitary = vec3(1.0f, 1.0f, 1.0f); +    vec3 FirstPlaneIntersect  = (Unitary - PositionLS) / RayLS; +    vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; +    vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); +    float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); + +    // Use Distance in CS directly to recover intersection +    vec3 IntersectPositionCS = origin + dir * Distance; + +    return IntersectPositionCS; +} + + + +// Tap a sphere based reflection probe +// pos - position of pixel +// dir - pixel normal +// lod - which mip to bias towards (lower is higher res, sharper reflections) +// c - center of probe +// r2 - radius of probe squared +// i - index of probe  +// vi - point at which reflection vector struck the influence volume, in clip space +vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) +{ +    //lod = max(lod, 1); +    // parallax adjustment + +    vec3 v; +    if (refIndex[i].w < 0) +    { +        v = boxIntersect(pos, dir, i); +    } +    else +    { +        v = sphereIntersect(pos, dir, c, r2); +    } + +    v -= c; +    v = env_mat * v; +    { +        float min_lod = textureQueryLod(reflectionProbes,v).y; // lower is higher res +        return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), max(min_lod, lod)).rgb; +        //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb; +    } +} + +vec3 sampleProbes(vec3 pos, vec3 dir, float lod) +{ +    float wsum = 0.0; +    vec3 col = vec3(0,0,0); +    float vd2 = dot(pos,pos); // view distance squared + +    for (int idx = 0; idx < probeInfluences; ++idx) +    { +        int i = probeIndex[idx]; +        float r = refSphere[i].w; // radius of sphere volume +        float p = float(abs(refIndex[i].w)); // priority +        float rr = r*r; // radius squred +        float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down) +        vec3 delta = pos.xyz-refSphere[i].xyz; +        float d2 = dot(delta,delta); +        float r2 = r1*r1;  +         +        { +            vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, rr, i); +             +            float w = 1.0/d2; + +            float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); +            w *= atten; +            w *= p; // boost weight based on priority +            col += refcol*w; +             +            wsum += w; +        } +    } + +    if (probeInfluences <= 1) +    { //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera  +        for (int idx = 0; idx < 8; ++idx) +        { +            if (refIndex[idx].w < 0) +            { // don't fallback to box probes, they are *very* specific +                continue; +            } +            int i = idx; +            vec3 delta = pos.xyz-refSphere[i].xyz; +            float d2 = dot(delta,delta); +             +            { +                vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, d2, i); +                 +                float w = 1.0/d2; +                w *= w; +                col += refcol*w; +                wsum += w; +            } +        } +    } + +    if (wsum > 0.0) +    { +        col *= 1.0/wsum; +    } +     +    return col; +} + +vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod) +{ +    vec3 col = sampleProbes(pos, dir, lod); + +    //desaturate +    vec3 hcol = col *0.5; +     +    col *= 2.0; +    col = vec3( +        col.r + hcol.g + hcol.b, +        col.g + hcol.r + hcol.b, +        col.b + hcol.r + hcol.g +    ); +     +    col *= 0.333333; + +    return col*reflectionAmbiance; + +} + +// brighten a color so that at least one component is 1 +vec3 brighten(vec3 c) +{ +    float m = max(max(c.r, c.g), c.b); + +    if (m == 0) +    { +        return vec3(1,1,1); +    } + +    return c * 1.0/m; +} + + +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,  +        vec3 pos, vec3 norm, float glossiness, float envIntensity) +{ +    // TODO - don't hard code lods +    float reflection_lods = 8; +    preProbeSample(pos); + +    vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + +    ambenv = sampleProbeAmbient(pos, norm, reflection_lods-1); + +    if (glossiness > 0.0) +    { +        float lod = (1.0-glossiness)*reflection_lods; +        glossenv = sampleProbes(pos, normalize(refnormpersp), lod); +    } + +    if (envIntensity > 0.0) +    { +        legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0); +    } +} + +void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm) +{ +    glossenv *= 0.35; // fudge darker +    float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz); +    float minf = spec.a * 0.1; +    fresnel = fresnel * (1.0-minf) + minf; +    glossenv *= spec.rgb*min(fresnel, 1.0); +    color.rgb += glossenv; +} + + void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity) + { +    vec3 reflected_color = legacyenv; //*0.5; //fudge darker +    vec3 lookAt = normalize(pos); +    float fresnel = 1.0+dot(lookAt, norm.xyz); +    fresnel *= fresnel; +    fresnel = min(fresnel+envIntensity, 1.0); +    reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb); +    color = mix(color.rgb, reflected_color, envIntensity); + }
\ No newline at end of file diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index d6b173b89d..d88400dddb 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -42,38 +42,8 @@ uniform sampler2DRect specularRect;  uniform sampler2DRect normalMap;  uniform sampler2DRect lightMap;  uniform sampler2DRect depthMap; -uniform samplerCube   environmentMap; -uniform samplerCubeArray   reflectionProbes;  uniform sampler2D     lightFunc; -layout (std140, binding = 1) uniform ReflectionProbes -{ -    // list of OBBs for user override probes -    // box is a set of 3 planes outward facing planes and the depth of the box along that plane -    // for each box refBox[i]... -    /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation -    //  box[3][0..2] - plane thickness -    mat4 refBox[REFMAP_COUNT]; -    // list of bounding spheres for reflection probes sorted by distance to camera (closest first) -    vec4 refSphere[REFMAP_COUNT]; -    // index  of cube map in reflectionProbes for a corresponding reflection probe -    // e.g. cube map channel of refSphere[2] is stored in refIndex[2] -    // refIndex.x - cubemap channel in reflectionProbes -    // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index) -    // refIndex.z - number of neighbors -    // refIndex.w - priority, if negative, this probe has a box influence -    ivec4 refIndex[REFMAP_COUNT]; - -    // neighbor list data (refSphere indices, not cubemap array layer) -    ivec4 refNeighbor[1024]; - -    // number of reflection probes present in refSphere -    int refmapCount; - -    // intensity of ambient light from reflection probes -    float reflectionAmbiance; -}; -  uniform float blur_size;  uniform float blur_fidelity; @@ -98,6 +68,12 @@ vec3  scaleSoftClipFrag(vec3 l);  vec3  fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);  vec3  fullbrightScaleSoftClip(vec3 light); +// reflection probe interface +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,  +        vec3 pos, vec3 norm, float glossiness, float envIntensity); +void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); +void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); +  vec3 linear_to_srgb(vec3 c);  vec3 srgb_to_linear(vec3 c); @@ -105,376 +81,8 @@ vec3 srgb_to_linear(vec3 c);  vec4 applyWaterFogView(vec3 pos, vec4 color);  #endif -// list of probeIndexes shader will actually use after "getRefIndex" is called -// (stores refIndex/refSphere indices, NOT rerflectionProbes layer) -int probeIndex[REF_SAMPLE_COUNT]; - -// number of probes stored in probeIndex -int probeInfluences = 0; - -bool isAbove(vec3 pos, vec4 plane) -{ -    return (dot(plane.xyz, pos) + plane.w) > 0; -} - -// return true if probe at index i influences position pos -bool shouldSampleProbe(int i, vec3 pos) -{ -    if (refIndex[i].w < 0) -    { -        vec4 v = refBox[i] * vec4(pos, 1.0); -        if (abs(v.x) > 1 ||  -            abs(v.y) > 1 || -            abs(v.z) > 1) -        { -            return false; -        } -    } -    else -    { -        vec3 delta = pos.xyz - refSphere[i].xyz; -        float d = dot(delta, delta); -        float r2 = refSphere[i].w; -        r2 *= r2; - -        if (d > r2) -        { //outside bounding sphere -            return false; -        } -    } - -    return true; -} - -// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT -// overall algorithm --  -void getRefIndex(vec3 pos) -{ -    // TODO: make some sort of structure that reduces the number of distance checks - -    for (int i = 0; i < refmapCount; ++i) -    { -        // found an influencing probe -        if (shouldSampleProbe(i, pos)) -        { -            probeIndex[probeInfluences] = i; -            ++probeInfluences; - -            int neighborIdx = refIndex[i].y; -            if (neighborIdx != -1) -            { -                int neighborCount = min(refIndex[i].z, REF_SAMPLE_COUNT-1); - -                int count = 0; -                while (count < neighborCount) -                { -                    // check up to REF_SAMPLE_COUNT-1 neighbors (neighborIdx is ivec4 index) - -                    int idx = refNeighbor[neighborIdx].x; -                    if (shouldSampleProbe(idx, pos)) -                    { -                        probeIndex[probeInfluences++] = idx; -                        if (probeInfluences == REF_SAMPLE_COUNT) -                        { -                            return; -                        } -                    } -                    count++; -                    if (count == neighborCount) -                    { -                        return; -                    } - -                    idx = refNeighbor[neighborIdx].y; -                    if (shouldSampleProbe(idx, pos)) -                    { -                        probeIndex[probeInfluences++] = idx; -                        if (probeInfluences == REF_SAMPLE_COUNT) -                        { -                            return; -                        } -                    } -                    count++; -                    if (count == neighborCount) -                    { -                        return; -                    } - -                    idx = refNeighbor[neighborIdx].z; -                    if (shouldSampleProbe(idx, pos)) -                    { -                        probeIndex[probeInfluences++] = idx; -                        if (probeInfluences == REF_SAMPLE_COUNT) -                        { -                            return; -                        } -                    } -                    count++; -                    if (count == neighborCount) -                    { -                        return; -                    } - -                    idx = refNeighbor[neighborIdx].w; -                    if (shouldSampleProbe(idx, pos)) -                    { -                        probeIndex[probeInfluences++] = idx; -                        if (probeInfluences == REF_SAMPLE_COUNT) -                        { -                            return; -                        } -                    } -                    count++; -                    if (count == neighborCount) -                    { -                        return; -                    } - -                    ++neighborIdx; -                } - -                return; -            } -        } -    } -} - -// from https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection - -// original reference implementation: -/* -bool intersect(const Ray &ray) const  -{  -        float t0, t1; // solutions for t if the ray intersects  -#if 0  -        // geometric solution -        Vec3f L = center - orig;  -        float tca = L.dotProduct(dir);  -        // if (tca < 0) return false; -        float d2 = L.dotProduct(L) - tca * tca;  -        if (d2 > radius2) return false;  -        float thc = sqrt(radius2 - d2);  -        t0 = tca - thc;  -        t1 = tca + thc;  -#else  -        // analytic solution -        Vec3f L = orig - center;  -        float a = dir.dotProduct(dir);  -        float b = 2 * dir.dotProduct(L);  -        float c = L.dotProduct(L) - radius2;  -        if (!solveQuadratic(a, b, c, t0, t1)) return false;  -#endif  -        if (t0 > t1) std::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;  -} */ - -// adapted -- assume that origin is inside sphere, return distance from origin to edge of sphere -vec3 sphereIntersect(vec3 origin, vec3 dir, vec3 center, float radius2) -{  -        float t0, t1; // solutions for t if the ray intersects  - -        vec3 L = center - origin;  -        float tca = dot(L,dir); - -        float d2 = dot(L,L) - tca * tca;  - -        float thc = sqrt(radius2 - d2);  -        t0 = tca - thc;  -        t1 = tca + thc;  -  -        vec3 v = origin + dir * t1; -        return v;  -}  - -// from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ -/* -vec3 DirectionWS = normalize(PositionWS - CameraWS); -vec3 ReflDirectionWS = reflect(DirectionWS, NormalWS); - -// Intersection with OBB convertto unit box space -// Transform in local unit parallax cube space (scaled and rotated) -vec3 RayLS = MulMatrix( float(3x3)WorldToLocal, ReflDirectionWS); -vec3 PositionLS = MulMatrix( WorldToLocal, PositionWS); - -vec3 Unitary = vec3(1.0f, 1.0f, 1.0f); -vec3 FirstPlaneIntersect  = (Unitary - PositionLS) / RayLS; -vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; -vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); -float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); - -// Use Distance in WS directly to recover intersection -vec3 IntersectPositionWS = PositionWS + ReflDirectionWS * Distance; -vec3 ReflDirectionWS = IntersectPositionWS - CubemapPositionWS; - -return texCUBE(envMap, ReflDirectionWS); -*/ - -// get point of intersection with given probe's box influence volume -// origin - ray origin in clip space -// dir - ray direction in clip space -// i - probe index in refBox/refSphere -vec3 boxIntersect(vec3 origin, vec3 dir, int i) -{ -    // Intersection with OBB convertto unit box space -    // Transform in local unit parallax cube space (scaled and rotated) -    mat4 clipToLocal = refBox[i]; - -    vec3 RayLS = mat3(clipToLocal) * dir; -    vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; - -    vec3 Unitary = vec3(1.0f, 1.0f, 1.0f); -    vec3 FirstPlaneIntersect  = (Unitary - PositionLS) / RayLS; -    vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; -    vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); -    float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); - -    // Use Distance in CS directly to recover intersection -    vec3 IntersectPositionCS = origin + dir * Distance; - -    return IntersectPositionCS; -} - - - -// Tap a sphere based reflection probe -// pos - position of pixel -// dir - pixel normal -// lod - which mip to bias towards (lower is higher res, sharper reflections) -// c - center of probe -// r2 - radius of probe squared -// i - index of probe  -// vi - point at which reflection vector struck the influence volume, in clip space -vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) -{ -    //lod = max(lod, 1); -    // parallax adjustment - -    vec3 v; -    if (refIndex[i].w < 0) -    { -        v = boxIntersect(pos, dir, i); -    } -    else -    { -        v = sphereIntersect(pos, dir, c, r2); -    } - -    v -= c; -    v = env_mat * v; -    { -        float min_lod = textureQueryLod(reflectionProbes,v).y; // lower is higher res -        return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), max(min_lod, lod)).rgb; -        //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb; -    } -} - -vec3 sampleRefMap(vec3 pos, vec3 dir, float lod) -{ -    float wsum = 0.0; -    vec3 col = vec3(0,0,0); -    float vd2 = dot(pos,pos); // view distance squared - -    for (int idx = 0; idx < probeInfluences; ++idx) -    { -        int i = probeIndex[idx]; -        float r = refSphere[i].w; // radius of sphere volume -        float p = float(abs(refIndex[i].w)); // priority -        float rr = r*r; // radius squred -        float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down) -        vec3 delta = pos.xyz-refSphere[i].xyz; -        float d2 = dot(delta,delta); -        float r2 = r1*r1;  -         -        { -            vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, rr, i); -             -            float w = 1.0/d2; - -            float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); -            w *= atten; -            w *= p; // boost weight based on priority -            col += refcol*w; -             -            wsum += w; -        } -    } - -    if (probeInfluences <= 1) -    { //edge-of-scene probe or no probe influence, mix in with embiggened version of probes closest to camera  -        for (int idx = 0; idx < 8; ++idx) -        { -            if (refIndex[idx].w < 0) -            { // don't fallback to box probes, they are *very* specific -                continue; -            } -            int i = idx; -            vec3 delta = pos.xyz-refSphere[i].xyz; -            float d2 = dot(delta,delta); -             -            { -                vec3 refcol = tapRefMap(pos, dir, lod, refSphere[i].xyz, d2, i); -                 -                float w = 1.0/d2; -                w *= w; -                col += refcol*w; -                wsum += w; -            } -        } -    } - -    if (wsum > 0.0) -    { -        col *= 1.0/wsum; -    } -     -    return col; -} - -vec3 sampleAmbient(vec3 pos, vec3 dir, float lod) -{ -    vec3 col = sampleRefMap(pos, dir, lod); - -    //desaturate -    vec3 hcol = col *0.5; -     -    col *= 2.0; -    col = vec3( -        col.r + hcol.g + hcol.b, -        col.g + hcol.r + hcol.b, -        col.b + hcol.r + hcol.g -    ); -     -    col *= 0.333333; - -    return col*reflectionAmbiance; - -} - -// brighten a color so that at least one component is 1 -vec3 brighten(vec3 c) -{ -    float m = max(max(c.r, c.g), c.b); - -    if (m == 0) -    { -        return vec3(1,1,1); -    } - -    return c * 1.0/m; -} -  void main()  { -    float reflection_lods = 8; // TODO -- base this on resolution of reflection map instead of hard coding -      vec2  tc           = vary_fragcoord.xy;      float depth        = texture2DRect(depthMap, tc.xy).r;      vec4  pos          = getPositionWithDepth(tc, depth); @@ -504,13 +112,15 @@ void main()      vec3 additive;      vec3 atten; -    getRefIndex(pos.xyz); -      calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);      //vec3 amb_vec = env_mat * norm.xyz; -    vec3 ambenv = sampleAmbient(pos.xyz, norm.xyz, reflection_lods-1); +    vec3 ambenv; +    vec3 glossenv; +    vec3 legacyenv; +    sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity); +      amblit = max(ambenv, amblit);      color.rgb = amblit*ambocc; @@ -527,7 +137,6 @@ void main()      vec3 refnormpersp = reflect(pos.xyz, norm.xyz); -    vec3 env_vec         = env_mat * refnormpersp;      if (spec.a > 0.0)  // specular reflection      {          float sa        = dot(normalize(refnormpersp), light_dir.xyz); @@ -539,27 +148,16 @@ void main()          color.rgb += spec_contrib;          // add reflection map - EXPERIMENTAL WORK IN PROGRESS -         -        float lod = (1.0-spec.a)*reflection_lods; -        vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), lod); -        reflected_color *= 0.35; // fudge darker -        float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz); -        float minf = spec.a * 0.1; -        fresnel = fresnel * (1.0-minf) + minf; -        reflected_color *= spec.rgb*min(fresnel, 1.0); -        color.rgb += reflected_color; +        applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);      }      color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);      if (envIntensity > 0.0)      {  // add environmentmap -        vec3 reflected_color = sampleRefMap(pos.xyz, normalize(refnormpersp), 0.0)*0.5; //fudge darker -        float fresnel = 1.0+dot(normalize(pos.xyz), norm.xyz); -        fresnel *= fresnel; -        fresnel = min(fresnel+envIntensity, 1.0); -        reflected_color *= (envIntensity*fresnel)*brighten(spec.rgb); -        color = mix(color.rgb, reflected_color, envIntensity); +        //fudge darker +        legacyenv *= 0.5*diffuse.a+0.5;; +        applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);      }      if (norm.w < 0.5) @@ -577,6 +175,8 @@ void main()      // convert to linear as fullscreen lights need to sum in linear colorspace      // and will be gamma (re)corrected downstream...      //color = vec3(ambocc); -    //color = ambenv;     +    //color = ambenv; +    //color.b = diffuse.a;      frag_color.rgb = srgb_to_linear(color.rgb); +    frag_color.a = bloom;  } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 0df0137b7a..3fe3896aa2 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -460,6 +460,11 @@ void LLDrawPoolBump::beginFullbrightShiny()  		LLVector4 vec4(vec, gShinyOrigin.mV[3]);  		shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); +        if (shader->mFeatures.hasReflectionProbes) +        { +            gPipeline.bindReflectionProbes(*shader); +        } +  		// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for   		// the cube map in the one pass shiny shaders  		gGL.getTexUnit(1)->disable(); @@ -520,6 +525,10 @@ void LLDrawPoolBump::endFullbrightShiny()  	if( cube_map )  	{  		cube_map->disable(); +        if (shader->mFeatures.hasReflectionProbes) +        { +            gPipeline.unbindReflectionProbes(*shader); +        }  		shader->unbind();  	} diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 8aacbba6be..5fe510fb56 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -506,6 +506,8 @@ void LLReflectionMapManager::setUniforms()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; +    // TODO -- avoid repacking UBO unnecessarily +          // structure for packing uniform buffer object      // see class2/deferred/softenLightF.glsl      struct ReflectionProbeData diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 10577b1804..875f585310 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -977,6 +977,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/deferredUtil.glsl",                    1) );  	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/shadowUtil.glsl",                      1) );  	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/aoUtil.glsl",                          1) ); +    index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl",                llmax(mShaderLevel[SHADER_DEFERRED], 1)) );  	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",                    mShaderLevel[SHADER_LIGHTING] ) );  	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl",                   mShaderLevel[SHADER_LIGHTING] ) );  	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",          mShaderLevel[SHADER_LIGHTING] ) ); @@ -1503,6 +1504,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()              gDeferredMaterialProgram[i].mFeatures.hasGamma = true;              gDeferredMaterialProgram[i].mFeatures.hasShadows = use_sun_shadow; +            if (mShaderLevel[SHADER_DEFERRED] > 1) +            { +                gDeferredMaterialProgram[i].mFeatures.hasReflectionProbes = true; +                gDeferredMaterialProgram[i].addPermutation("HAS_REFLECTION_PROBES", "1"); +            } +              if (has_skin)              {                  gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1"); @@ -2202,6 +2209,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; +        if (gDeferredFullbrightShinyProgram.mShaderLevel >= 2) // TODO : make this a 3 when reflection probes are restricted to class 3 +        { +            gDeferredFullbrightShinyProgram.addPermutation("HAS_REFLECTION_PROBES", "1"); +            gDeferredFullbrightShinyProgram.mFeatures.hasReflectionProbes = true; +        }          success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram);  		success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL);  		llassert(success); @@ -2274,6 +2286,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredSoftenProgram.mFeatures.hasGamma = true;  		gDeferredSoftenProgram.mFeatures.isDeferred = true;  		gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow; +        gDeferredSoftenProgram.mFeatures.hasReflectionProbes = true;          gDeferredSoftenProgram.clearPermutations();  		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); @@ -2324,6 +2337,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;          gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;          gDeferredSoftenWaterProgram.mFeatures.hasShadows = use_sun_shadow; +        gDeferredSoftenWaterProgram.mFeatures.hasReflectionProbes = true;          if (ambient_kill)          { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4cf8157623..b4b70a3e11 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8208,30 +8208,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_  	stop_glerror(); -    bool setup_env_mat = false;  	channel = shader.enableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);  	if (channel > -1)  	{  		LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;  		if (cube_map)  		{ -            setup_env_mat = true;  			cube_map->enable(channel);  			cube_map->bind();  		} -	} -    channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); -    if (channel > -1 && mReflectionMapManager.mTexture.notNull()) -    { -        // see comments in class2/deferred/softenLightF.glsl for what these uniforms mean -        mReflectionMapManager.mTexture->bind(channel); -        mReflectionMapManager.setUniforms(); -        setup_env_mat = true; -    } - -    if (setup_env_mat) -    {          F32* m = gGLModelView;          F32 mat[] = { m[0], m[1], m[2], @@ -8239,8 +8225,10 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_                        m[8], m[9], m[10] };          shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); -    } +	} +    bindReflectionProbes(shader); +          if (gAtmosphere)      {          // bind precomputed textures necessary for calculating sun and sky luminance @@ -9163,7 +9151,35 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)  		}  	} -    channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP); +    unbindReflectionProbes(shader); + +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +	gGL.getTexUnit(0)->activate(); +	shader.unbind(); +} + +void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) +{ +    S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); +    if (channel > -1 && mReflectionMapManager.mTexture.notNull()) +    { +        // see comments in class2/deferred/softenLightF.glsl for what these uniforms mean +        mReflectionMapManager.mTexture->bind(channel); +        mReflectionMapManager.setUniforms(); + +        F32* m = gGLModelView; + +        F32 mat[] = { m[0], m[1], m[2], +                      m[4], m[5], m[6], +                      m[8], m[9], m[10] }; + +        shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); +    } +} + +void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader) +{ +    S32 channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP);      if (channel > -1 && mReflectionMapManager.mTexture.notNull())      {          mReflectionMapManager.mTexture->unbind(); @@ -9172,12 +9188,9 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)              gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE);          }      } - -	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -	gGL.getTexUnit(0)->activate(); -	shader.unbind();  } +  inline float sgn(float a)  {      if (a > 0.0F) return (1.0F); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 88eaca558a..5cbd1eb550 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -294,6 +294,10 @@ public:  	void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);  	void unbindDeferredShader(LLGLSLShader& shader); + +    void bindReflectionProbes(LLGLSLShader& shader); +    void unbindReflectionProbes(LLGLSLShader& shader); +  	void renderDeferredLighting(LLRenderTarget* light_target);  	void postDeferredGammaCorrect(LLRenderTarget* screen_target);  | 
