From 36d9fa90150d30a0a0851cc0da87531014c1d93d Mon Sep 17 00:00:00 2001 From: Ptolemy Date: Tue, 21 Jun 2022 16:31:35 -0700 Subject: SL-17274: Add view_dir uniform --- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview/app_settings') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 61757882bb..4dd5c88211 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -1,5 +1,5 @@ /** - * @file class2/deferred/softenLightF.glsl + * @file class3/deferred/softenLightF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code @@ -85,6 +85,8 @@ vec3 srgb_to_linear(vec3 c); vec4 applyWaterFogView(vec3 pos, vec4 color); #endif +uniform vec3 view_dir; // PBR + void main() { vec2 tc = vary_fragcoord.xy; -- cgit v1.3 From 31e2fa5e50bc5aad265e8ec12613223eeb3ae3e1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 21 Jun 2022 22:44:30 -0500 Subject: SL-17600 WIP -- Proper radiance maps (not just mipped cubemaps). --- autobuild.xml | 56 +++++++ indra/cmake/VulkanGltf.cmake | 5 + indra/llrender/llcubemaparray.cpp | 44 ++++++ indra/llrender/llcubemaparray.h | 9 +- indra/newview/CMakeLists.txt | 1 + .../shaders/class1/interface/radianceGenF.glsl | 167 +++++++++++++++++++++ .../shaders/class1/interface/radianceGenV.glsl | 38 +++++ .../shaders/class3/deferred/reflectionProbeF.glsl | 7 +- indra/newview/llreflectionmapmanager.cpp | 50 +++++- indra/newview/llreflectionmapmanager.h | 1 + indra/newview/llviewershadermgr.cpp | 12 ++ indra/newview/llviewershadermgr.h | 1 + 12 files changed, 384 insertions(+), 7 deletions(-) create mode 100644 indra/cmake/VulkanGltf.cmake create mode 100644 indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl (limited to 'indra/newview/app_settings') diff --git a/autobuild.xml b/autobuild.xml index aaff2d1360..712b917b16 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3461,6 +3461,62 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors version 3.0.16.565299 + vulkan_gltf + + canonical_repo + https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr + copyright + Copyright (c) 2018 Sascha Willems + description + Vulkan GLTF Sample Implementation + license + Copyright (c) 2018 Sascha Willems + license_file + LICENSES/vulkan_gltf.txt + name + vulkan_gltf + platforms + + darwin64 + + archive + + hash + 8cff2060843db3db788511ee34a8e8cc + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101316/891509/vulkan_gltf-1-darwin64-572743.tar.bz2 + + name + darwin64 + + windows + + archive + + hash + 58eea384be49ba756ce9c5e66669540b + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101318/891520/vulkan_gltf-1-windows-572743.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 79b6a11622c2f83cfc2b7cd1fafb867b + url + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101319/891521/vulkan_gltf-1-windows64-572743.tar.bz2 + + name + windows64 + + + version + 1 + xmlrpc-epi copyright diff --git a/indra/cmake/VulkanGltf.cmake b/indra/cmake/VulkanGltf.cmake new file mode 100644 index 0000000000..94541d5307 --- /dev/null +++ b/indra/cmake/VulkanGltf.cmake @@ -0,0 +1,5 @@ +# -*- cmake -*- +include(Prebuilt) + +use_prebuilt_binary(vulkan_gltf) + diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index e4081c1154..438d92cdba 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -53,6 +53,50 @@ GLenum LLCubeMapArray::sTargets[6] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB }; +LLVector3 LLCubeMapArray::sLookVecs[6] = +{ + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), + LLVector3(0, 1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1) +}; + +LLVector3 LLCubeMapArray::sUpVecs[6] = +{ + LLVector3(0, -1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1), + LLVector3(0, -1, 0), + LLVector3(0, -1, 0) +}; + +LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] = +{ + LLVector3(0, 0, -1), //GOOD + LLVector3(0, 0, 1), //GOOD + + LLVector3(1, 0, 0), // GOOD + LLVector3(1, 0, 0), // GOOD + + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), +}; + +LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] = +{ + LLVector3(-1, 0, 0), //GOOD + LLVector3(1, 0, 0), //GOOD + + LLVector3(0, 1, 0), // GOOD + LLVector3(0, -1, 0), // GOOD + + LLVector3(0, 0, -1), + LLVector3(0, 0, 1) +}; + LLCubeMapArray::LLCubeMapArray() : mTextureStage(0) { diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index 52e21f1dda..cbc0692afb 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -32,13 +32,20 @@ class LLVector3; -// Environment map hack! class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); static GLenum sTargets[6]; + + // look and up vectors for each cube face (agent space) + static LLVector3 sLookVecs[6]; + static LLVector3 sUpVecs[6]; + + // look and up vectors for each cube face (clip space) + static LLVector3 sClipToCubeLookVecs[6]; + static LLVector3 sClipToCubeUpVecs[6]; // allocate a cube map array // res - resolution of each cube face diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0d2b99a8cd..5e0d3b52b4 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -56,6 +56,7 @@ include(UnixInstall) include(ViewerMiscLibs) include(ViewerManager) include(VisualLeakDetector) +include(VulkanGltf) include(ZLIB) include(URIPARSER) diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl new file mode 100644 index 0000000000..27008b8a1c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -0,0 +1,167 @@ +/** + * @file radianceGenF.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$ + */ + + +/*[EXTRA_CODE_HERE]*/ + +#define REFMAP_COUNT 256 + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform samplerCubeArray reflectionProbes; + +VARYING vec3 vary_dir; + +// ============================================================================================================= +// Parts of this file are (c) 2018 Sascha Willems +// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/prefilterenvmap.frag +/* +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// ============================================================================================================= + + +uniform float roughness; + +uniform int numSamples; + +const float PI = 3.1415926536; + +// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ +float random(vec2 co) +{ + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); +} + +vec2 hammersley2d(uint i, uint N) +{ + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); +} + +// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf +vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) +{ + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); +} + +// Normal Distribution function +float D_GGX(float dotNH, float roughness) +{ + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); +} + +vec3 prefilterEnvMap(vec3 R, float roughness) +{ + vec3 N = R; + vec3 V = R; + vec3 color = vec3(0.0); + float totalWeight = 0.0; + float envMapDim = 256.0; + for(uint i = 0u; i < numSamples; i++) { + vec2 Xi = hammersley2d(i, numSamples); + vec3 H = importanceSample_GGX(Xi, roughness, N); + vec3 L = 2.0 * dot(V, H) * H - V; + float dotNL = clamp(dot(N, L), 0.0, 1.0); + if(dotNL > 0.0) { + // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ + + float dotNH = clamp(dot(N, H), 0.0, 1.0); + float dotVH = clamp(dot(V, H), 0.0, 1.0); + + // Probability Distribution Function + float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; + // Slid angle of current smple + float omegaS = 1.0 / (float(numSamples) * pdf); + // Solid angle of 1 pixel across all cube faces + float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); + // Biased (+1.0) mip level for better result + float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); + color += textureLod(reflectionProbes, vec4(L,REFMAP_COUNT), mipLevel).rgb * dotNL; + totalWeight += dotNL; + + } + } + return (color / totalWeight); +} + +void main() +{ + vec3 N = normalize(vary_dir); + frag_color = vec4(prefilterEnvMap(N, roughness), 1.0); +} +// ============================================================================================================= + diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl new file mode 100644 index 0000000000..5f5d9396ff --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl @@ -0,0 +1,38 @@ +/** + * @file radianceGenV.glsl + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_dir; + +void main() +{ + gl_Position = vec4(position, 1.0); + + vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 4a40f691be..40378b49ea 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -334,8 +334,9 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) 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; + //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 textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod).rgb; //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb; } } @@ -450,7 +451,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, reflection_lods-1); + ambenv = sampleProbeAmbient(pos, norm, reflection_lods-2); if (glossiness > 0.0) { diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 752427f0fa..025b8457c1 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -80,7 +80,8 @@ void LLReflectionMapManager::update() if (mTexture.isNull()) { mTexture = new LLCubeMapArray(); - mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); + // store LL_REFLECTION_PROBE_COUNT+1 cube maps, final cube map is used for render target and radiance map generation source) + mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT+2); } if (!mRenderTarget.isComplete()) @@ -395,7 +396,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; mRenderTarget.flush(); - // generate mipmaps + // downsample to placeholder map { LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); @@ -451,7 +452,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) if (mip >= 0) { mTexture->bind(0); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, LL_REFLECTION_PROBE_COUNT * 6 + face, 0, 0, res, res); mTexture->unbind(); } mMipChain[i].flush(); @@ -463,6 +465,48 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.unbind(); } + + if (face == 5) + { + //generate radiance map + gRadianceGenProgram.bind(); + S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + + 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); + + for (int i = 0; i < mMipChain.size(); ++i) + { + mMipChain[i].bindTarget(); + static LLStaticHashedString sRoughness("roughness"); + static LLStaticHashedString sNumSamples("numSamples"); + + gRadianceGenProgram.uniform1i(sNumSamples, 32); + gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); + + gGL.begin(gGL.QUADS); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, 1, -1); + gGL.end(); + gGL.flush(); + + + + S32 res = mMipChain[i].getWidth(); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + mMipChain[i].flush(); + } + } + } } void LLReflectionMapManager::rebuild() diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 3b5cdc5520..551a461e63 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -29,6 +29,7 @@ #include "llreflectionmap.h" #include "llrendertarget.h" #include "llcubemaparray.h" +#include "llcubemap.h" class LLSpatialGroup; class LLViewerObject; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d4ee754d5c..d5ca915da5 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -85,6 +85,7 @@ LLGLSLShader gCustomAlphaProgram; LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; LLGLSLShader gReflectionMipProgram; +LLGLSLShader gRadianceGenProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gTwoTextureCompareProgram; @@ -762,6 +763,7 @@ void LLViewerShaderMgr::unloadShaders() gGlowCombineProgram.unload(); gSplatTextureRectProgram.unload(); gReflectionMipProgram.unload(); + gRadianceGenProgram.unload(); gGlowCombineFXAAProgram.unload(); gTwoTextureAddProgram.unload(); gTwoTextureCompareProgram.unload(); @@ -3821,6 +3823,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() } } + if (success) + { + gRadianceGenProgram.mName = "Radiance Gen Shader"; + gRadianceGenProgram.mShaderFiles.clear(); + gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenV.glsl", GL_VERTEX_SHADER_ARB)); + gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenF.glsl", GL_FRAGMENT_SHADER_ARB)); + gRadianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gRadianceGenProgram.createShader(NULL, NULL); + } + if( !success ) { mShaderLevel[SHADER_INTERFACE] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index f0187db302..fa5b2121b9 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -162,6 +162,7 @@ extern LLGLSLShader gCustomAlphaProgram; extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gReflectionMipProgram; +extern LLGLSLShader gRadianceGenProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; -- cgit v1.3 From d0d1b832d4983f35ab29947eb6fda54a8aa48f8a Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 22 Jun 2022 13:25:50 -0500 Subject: SL-17600 Proper irradiance probes. --- indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + .../shaders/class1/interface/irradianceGenF.glsl | 99 +++++++++++++++++ .../shaders/class1/interface/irradianceGenV.glsl | 38 +++++++ .../shaders/class1/interface/radianceGenF.glsl | 5 +- .../shaders/class3/deferred/reflectionProbeF.glsl | 120 +++++++++++++++++---- indra/newview/llreflectionmapmanager.cpp | 68 +++++++++++- indra/newview/llreflectionmapmanager.h | 6 +- indra/newview/llviewershadermgr.cpp | 12 +++ indra/newview/llviewershadermgr.h | 1 + indra/newview/pipeline.cpp | 14 ++- 11 files changed, 334 insertions(+), 31 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl (limited to 'indra/newview/app_settings') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index e2e1ff9714..10939db5e4 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1171,6 +1171,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("bumpMap2"); mReservedUniforms.push_back("environmentMap"); mReservedUniforms.push_back("reflectionProbes"); + mReservedUniforms.push_back("irradianceProbes"); mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); mReservedUniforms.push_back("fullbright"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index d3bb2b9db4..5b19dd53d1 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -81,6 +81,7 @@ public: BUMP_MAP2, // "bumpMap2" ENVIRONMENT_MAP, // "environmentMap" REFLECTION_PROBES, // "reflectionProbes" + IRRADIANCE_PROBES, // "irradianceProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" FULLBRIGHT, // "fullbright" diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl new file mode 100644 index 0000000000..2028509775 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl @@ -0,0 +1,99 @@ +/** + * @file irradianceGenF.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$ + */ + + +/*[EXTRA_CODE_HERE]*/ + + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform samplerCubeArray reflectionProbes; +uniform int sourceIdx; + +VARYING vec3 vary_dir; + +// ============================================================================================================= +// Parts of this file are (c) 2018 Sascha Willems +// SNIPPED FROM https://github.com/SaschaWillems/Vulkan-glTF-PBR/blob/master/data/shaders/irradiancecube.frag +/* +MIT License + +Copyright (c) 2018 Sascha Willems + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// ============================================================================================================= + + + +#define PI 3.1415926535897932384626433832795 + +float deltaPhi = PI/16.0; +float deltaTheta = deltaPhi*0.25; + +void main() +{ + vec3 N = normalize(vary_dir); + vec3 up = vec3(0.0, 1.0, 0.0); + vec3 right = normalize(cross(up, N)); + up = cross(N, right); + + const float TWO_PI = PI * 2.0; + const float HALF_PI = PI * 0.5; + + vec3 color = vec3(0.0); + uint sampleCount = 0u; + for (float phi = 0.0; phi < TWO_PI; phi += deltaPhi) { + for (float theta = 0.0; theta < HALF_PI; theta += deltaTheta) { + vec3 tempVec = cos(phi) * right + sin(phi) * up; + vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; + color += textureLod(reflectionProbes, vec4(sampleVector, sourceIdx), 3).rgb * cos(theta) * sin(theta); + sampleCount++; + } + } + frag_color = vec4(PI * color / float(sampleCount), 1.0); +} +// ============================================================================================================= + diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl new file mode 100644 index 0000000000..5190abf17c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl @@ -0,0 +1,38 @@ +/** + * @file irradianceGenV.glsl + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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$ + */ + +uniform mat4 modelview_matrix; + +ATTRIBUTE vec3 position; + +VARYING vec3 vary_dir; + +void main() +{ + gl_Position = vec4(position, 1.0); + + vary_dir = vec3(modelview_matrix * vec4(position, 1.0)).xyz; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 27008b8a1c..3fc227eae7 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -26,8 +26,6 @@ /*[EXTRA_CODE_HERE]*/ -#define REFMAP_COUNT 256 - #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_color; #else @@ -35,6 +33,7 @@ out vec4 frag_color; #endif uniform samplerCubeArray reflectionProbes; +uniform int sourceIdx; VARYING vec3 vary_dir; @@ -150,7 +149,7 @@ vec3 prefilterEnvMap(vec3 R, float roughness) float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); // Biased (+1.0) mip level for better result float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); - color += textureLod(reflectionProbes, vec4(L,REFMAP_COUNT), mipLevel).rgb * dotNL; + color += textureLod(reflectionProbes, vec4(L,sourceIdx), mipLevel).rgb * dotNL; totalWeight += dotNL; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 40378b49ea..83348077d7 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 @@ #define REF_SAMPLE_COUNT 64 //maximum number of samples to consider uniform samplerCubeArray reflectionProbes; +uniform samplerCubeArray irradianceProbes; layout (std140, binding = 1) uniform ReflectionProbes { @@ -308,7 +309,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i) -// Tap a sphere based reflection probe +// Tap a reflection probe // pos - position of pixel // dir - pixel normal // lod - which mip to bias towards (lower is higher res, sharper reflections) @@ -334,10 +335,36 @@ vec3 tapRefMap(vec3 pos, vec3 dir, float lod, vec3 c, float r2, int i) 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 textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod).rgb; - //return texture(reflectionProbes, vec4(v.xyz, refIndex[i].x)).rgb; + } +} + +// Tap an irradiance map +// pos - position of pixel +// dir - pixel normal +// 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 tapIrradianceMap(vec3 pos, vec3 dir, 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; + { + return texture(irradianceProbes, vec4(v.xyz, refIndex[i].x)).rgb * refParams[i].x; } } @@ -371,7 +398,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) float atten = 1.0-max(d2-r2, 0.0)/(rr-r2); w *= atten; //w *= p; // boost weight based on priority - col += refcol*w*max(minweight, refParams[i].x); + col += refcol*w; wsum += w; } @@ -394,7 +421,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) float w = 1.0/d2; w *= w; - col += refcol*w*max(minweight, refParams[i].x); + col += refcol*w; wsum += w; } } @@ -408,24 +435,75 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight) return col; } -vec3 sampleProbeAmbient(vec3 pos, vec3 dir, float lod) +vec3 sampleProbeAmbient(vec3 pos, vec3 dir) { - vec3 col = sampleProbes(pos, dir, lod, 0.f); + // modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further + // as irradiance map mixing is tuned independently of radiance map mixing + float wsum = 0.0; + vec3 col = vec3(0,0,0); + float vd2 = dot(pos,pos); // view distance squared - //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; + float minweight = 1.0; - return col; + for (int idx = 0; idx < probeInfluences; ++idx) + { + int i = probeIndex[idx]; + if (abs(refIndex[i].w) < max_priority) + { + continue; + } + 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 = tapIrradianceMap(pos, dir, 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 = tapIrradianceMap(pos, dir, 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; } // brighten a color so that at least one component is 1 @@ -451,7 +529,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, inout vec3 l vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, reflection_lods-2); + ambenv = sampleProbeAmbient(pos, norm); if (glossiness > 0.0) { diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 025b8457c1..dfd0d1b9a9 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -80,8 +80,11 @@ void LLReflectionMapManager::update() if (mTexture.isNull()) { mTexture = new LLCubeMapArray(); - // store LL_REFLECTION_PROBE_COUNT+1 cube maps, final cube map is used for render target and radiance map generation source) + // store LL_REFLECTION_PROBE_COUNT+2 cube maps, final two cube maps are used for render target and radiance map generation source) mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT+2); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, LL_REFLECTION_PROBE_COUNT); } if (!mRenderTarget.isComplete()) @@ -396,6 +399,13 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; mRenderTarget.flush(); + S32 targetIdx = LL_REFLECTION_PROBE_COUNT; + + if (probe != mUpdatingProbe) + { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel + targetIdx += 1; + } + // downsample to placeholder map { LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -453,7 +463,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { mTexture->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, LL_REFLECTION_PROBE_COUNT * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res); mTexture->unbind(); } mMipChain[i].flush(); @@ -472,7 +482,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gRadianceGenProgram.bind(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); mTexture->bind(channel); - + static LLStaticHashedString sSourceIdx("sourceIdx"); + gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx); + for (int cf = 0; cf < 6; ++cf) { // for each cube face LLCoordFrame frame; @@ -499,13 +511,59 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.end(); gGL.flush(); - - S32 res = mMipChain[i].getWidth(); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); mMipChain[i].flush(); } } + gRadianceGenProgram.unbind(); + + //generate irradiance map + gIrradianceGenProgram.bind(); + channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + mTexture->bind(channel); + + gIrradianceGenProgram.uniform1i(sSourceIdx, targetIdx); + + int start_mip = 0; + // find the mip target to start with based on irradiance map resolution + for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) + { + if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + { + break; + } + } + + 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); + + for (int i = start_mip; i < mMipChain.size(); ++i) + { + mMipChain[i].bindTarget(); + + gGL.begin(gGL.QUADS); + gGL.vertex3f(-1, -1, -1); + gGL.vertex3f(1, -1, -1); + gGL.vertex3f(1, 1, -1); + gGL.vertex3f(-1, 1, -1); + gGL.end(); + gGL.flush(); + + S32 res = mMipChain[i].getWidth(); + mIrradianceMaps->bind(channel); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i-start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + mTexture->bind(channel); + mMipChain[i].flush(); + } + } + gIrradianceGenProgram.unbind(); } } diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 551a461e63..5f0b11ec17 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -39,6 +39,7 @@ class LLViewerObject; // reflection probe resolution #define LL_REFLECTION_PROBE_RESOLUTION 256 +#define LL_IRRADIANCE_MAP_RESOLUTION 64 // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; @@ -112,9 +113,12 @@ private: std::vector mMipChain; - // storage for reflection probes + // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; + // storage for reflection probe irradiance maps + LLPointer mIrradianceMaps; + // array indicating if a particular cubemap is free bool mCubeFree[LL_REFLECTION_PROBE_COUNT]; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d5ca915da5..c041d2470c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -86,6 +86,7 @@ LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; LLGLSLShader gReflectionMipProgram; LLGLSLShader gRadianceGenProgram; +LLGLSLShader gIrradianceGenProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; LLGLSLShader gTwoTextureCompareProgram; @@ -764,6 +765,7 @@ void LLViewerShaderMgr::unloadShaders() gSplatTextureRectProgram.unload(); gReflectionMipProgram.unload(); gRadianceGenProgram.unload(); + gIrradianceGenProgram.unload(); gGlowCombineFXAAProgram.unload(); gTwoTextureAddProgram.unload(); gTwoTextureCompareProgram.unload(); @@ -3833,6 +3835,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gRadianceGenProgram.createShader(NULL, NULL); } + if (success) + { + gIrradianceGenProgram.mName = "Irradiance Gen Shader"; + gIrradianceGenProgram.mShaderFiles.clear(); + gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenV.glsl", GL_VERTEX_SHADER_ARB)); + gIrradianceGenProgram.mShaderFiles.push_back(make_pair("interface/irradianceGenF.glsl", GL_FRAGMENT_SHADER_ARB)); + gIrradianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gIrradianceGenProgram.createShader(NULL, NULL); + } + if( !success ) { mShaderLevel[SHADER_INTERFACE] = 0; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index fa5b2121b9..87d90b49a9 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -163,6 +163,7 @@ extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gSplatTextureRectProgram; extern LLGLSLShader gReflectionMipProgram; extern LLGLSLShader gRadianceGenProgram; +extern LLGLSLShader gIrradianceGenProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; extern LLGLSLShader gClipProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 028a0db95c..06c9d3c136 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -9205,10 +9205,22 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) { S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + bool bound = false; if (channel > -1 && mReflectionMapManager.mTexture.notNull()) { - // see comments in class2/deferred/softenLightF.glsl for what these uniforms mean mReflectionMapManager.mTexture->bind(channel); + bound = true; + } + + channel = shader.enableTexture(LLShaderMgr::IRRADIANCE_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mReflectionMapManager.mIrradianceMaps.notNull()) + { + mReflectionMapManager.mIrradianceMaps->bind(channel); + bound = true; + } + + if (bound) + { mReflectionMapManager.setUniforms(); F32* m = gGLModelView; -- cgit v1.3 From 6540b4c480d1d4b4c8342a0d093d09f525485659 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 22 Jun 2022 19:56:26 -0500 Subject: SL-17600 Cubemap filter tuning. --- .../shaders/class1/interface/irradianceGenF.glsl | 9 ++-- .../shaders/class1/interface/radianceGenF.glsl | 6 ++- indra/newview/llreflectionmapmanager.cpp | 54 ++++++++++++---------- 3 files changed, 39 insertions(+), 30 deletions(-) (limited to 'indra/newview/app_settings') diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl index 2028509775..4d91395a1b 100644 --- a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl @@ -70,11 +70,12 @@ SOFTWARE. #define PI 3.1415926535897932384626433832795 -float deltaPhi = PI/16.0; -float deltaTheta = deltaPhi*0.25; - void main() { + float deltaPhi = (2.0 * PI) / 11.25; + float deltaTheta = (0.5 * PI) / 4.0; + float mipLevel = 2; + vec3 N = normalize(vary_dir); vec3 up = vec3(0.0, 1.0, 0.0); vec3 right = normalize(cross(up, N)); @@ -89,7 +90,7 @@ void main() for (float theta = 0.0; theta < HALF_PI; theta += deltaTheta) { vec3 tempVec = cos(phi) * right + sin(phi) * up; vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec; - color += textureLod(reflectionProbes, vec4(sampleVector, sourceIdx), 3).rgb * cos(theta) * sin(theta); + color += textureLod(reflectionProbes, vec4(sampleVector, sourceIdx), mipLevel).rgb * cos(theta) * sin(theta); sampleCount++; } } diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 3fc227eae7..94fedce243 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -68,7 +68,7 @@ SOFTWARE. uniform float roughness; -uniform int numSamples; +uniform float mipLevel; const float PI = 3.1415926536; @@ -130,6 +130,8 @@ vec3 prefilterEnvMap(vec3 R, float roughness) vec3 color = vec3(0.0); float totalWeight = 0.0; float envMapDim = 256.0; + int numSamples = 32/max(int(mipLevel), 1); + for(uint i = 0u; i < numSamples; i++) { vec2 Xi = hammersley2d(i, numSamples); vec3 H = importanceSample_GGX(Xi, roughness, N); @@ -148,7 +150,7 @@ vec3 prefilterEnvMap(vec3 R, float roughness) // Solid angle of 1 pixel across all cube faces float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); + //float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f); color += textureLod(reflectionProbes, vec4(L,sourceIdx), mipLevel).rgb * dotNL; totalWeight += dotNL; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index dfd0d1b9a9..bde8c0c51c 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -425,7 +425,8 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f; - for (int i = 0; i < mMipChain.size(); ++i) + //for (int i = 0; i < mMipChain.size(); ++i) + for (int i = 0; i < 1; ++i) { LL_PROFILE_GPU_ZONE("probe mip"); mMipChain[i].bindTarget(); @@ -464,6 +465,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mTexture->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); mTexture->unbind(); } mMipChain[i].flush(); @@ -485,24 +487,28 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) static LLStaticHashedString sSourceIdx("sourceIdx"); gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx); - 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]); + static LLStaticHashedString sMipLevel("mipLevel"); - F32 mat[16]; - frame.getOpenGLRotation(mat); - gGL.loadMatrix(mat); + for (int i = 1; i < mMipChain.size(); ++i) + { + 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); - for (int i = 0; i < mMipChain.size(); ++i) - { mMipChain[i].bindTarget(); static LLStaticHashedString sRoughness("roughness"); - static LLStaticHashedString sNumSamples("numSamples"); - gRadianceGenProgram.uniform1i(sNumSamples, 32); gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); - + gRadianceGenProgram.uniform1f(sMipLevel, llmax((F32)(i - 1), 0.f)); + if (i > 0) + { + gRadianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex); + } gGL.begin(gGL.QUADS); gGL.vertex3f(-1, -1, -1); gGL.vertex3f(1, -1, -1); @@ -523,7 +529,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); mTexture->bind(channel); - gIrradianceGenProgram.uniform1i(sSourceIdx, targetIdx); + gIrradianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex); int start_mip = 0; // find the mip target to start with based on irradiance map resolution @@ -535,17 +541,17 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } } - 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]); + for (int i = start_mip; i < mMipChain.size(); ++i) + { + 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); + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); - for (int i = start_mip; i < mMipChain.size(); ++i) - { mMipChain[i].bindTarget(); gGL.begin(gGL.QUADS); @@ -558,7 +564,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) S32 res = mMipChain[i].getWidth(); mIrradianceMaps->bind(channel); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i-start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); mTexture->bind(channel); mMipChain[i].flush(); } -- cgit v1.3