summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--autobuild.xml164
-rw-r--r--indra/cmake/GLEXT.cmake4
-rw-r--r--indra/cmake/LLRender.cmake2
-rw-r--r--indra/cmake/TinyGLTF.cmake7
-rw-r--r--indra/cmake/Tracy.cmake1
-rw-r--r--indra/cmake/VulkanGltf.cmake5
-rw-r--r--indra/llcommon/llassettype.cpp1
-rw-r--r--indra/llcommon/llassettype.h5
-rw-r--r--indra/llcommon/llframetimer.cpp6
-rw-r--r--indra/llcommon/llprofiler.h35
-rw-r--r--indra/llfilesystem/lldiskcache.cpp1
-rw-r--r--indra/llimage/llimage.cpp9
-rw-r--r--indra/llimage/llimage.h1
-rw-r--r--indra/llinventory/llfoldertype.h4
-rw-r--r--indra/llinventory/llinventorytype.cpp4
-rw-r--r--indra/llinventory/llinventorytype.h5
-rw-r--r--indra/llinventory/llsettingssky.cpp17
-rw-r--r--indra/llinventory/llsettingssky.h6
-rw-r--r--indra/llmath/v4color.h12
-rw-r--r--indra/llprimitive/CMakeLists.txt8
-rw-r--r--indra/llprimitive/lldaeloader.cpp42
-rw-r--r--indra/llprimitive/lldaeloader.h3
-rw-r--r--indra/llprimitive/llgltfloader.cpp402
-rw-r--r--indra/llprimitive/llgltfloader.h206
-rw-r--r--indra/llprimitive/llgltfmaterial.h101
-rw-r--r--indra/llprimitive/llmaterial.cpp11
-rw-r--r--indra/llprimitive/llmaterial.h6
-rw-r--r--indra/llprimitive/llmaterialid.cpp7
-rw-r--r--indra/llprimitive/llmaterialid.h1
-rw-r--r--indra/llprimitive/llmodelloader.cpp13
-rw-r--r--indra/llprimitive/llprimitive.cpp262
-rw-r--r--indra/llprimitive/llprimitive.h79
-rw-r--r--indra/llprimitive/lltextureentry.h8
-rw-r--r--indra/llprimitive/tests/llmessagesystem_stub.cpp2
-rw-r--r--indra/llprimitive/tests/llprimitive_test.cpp40
-rw-r--r--indra/llrender/CMakeLists.txt2
-rw-r--r--indra/llrender/llcubemap.cpp257
-rw-r--r--indra/llrender/llcubemap.h24
-rw-r--r--indra/llrender/llcubemaparray.cpp157
-rw-r--r--indra/llrender/llcubemaparray.h67
-rw-r--r--indra/llrender/llgl.cpp73
-rw-r--r--indra/llrender/llgl.h2
-rw-r--r--indra/llrender/llglheaders.h22
-rw-r--r--indra/llrender/llglslshader.cpp114
-rw-r--r--indra/llrender/llglslshader.h8
-rw-r--r--indra/llrender/llimagegl.cpp55
-rw-r--r--indra/llrender/llimagegl.h2
-rw-r--r--indra/llrender/llrender.cpp4
-rw-r--r--indra/llrender/llrender.h3
-rw-r--r--indra/llrender/llrendertarget.cpp12
-rw-r--r--indra/llrender/llshadermgr.cpp42
-rw-r--r--indra/llrender/llshadermgr.h9
-rw-r--r--indra/llrender/llvertexbuffer.cpp6
-rw-r--r--indra/llui/llui.h3
-rw-r--r--indra/llwindow/llwindowwin32.cpp12
-rw-r--r--indra/newview/CMakeLists.txt11
-rw-r--r--indra/newview/app_settings/settings.xml97
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl292
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl16
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialF.glsl10
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/moonF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl1
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl1
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl151
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl145
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl)60
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/starsF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/waterF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl100
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl)19
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl168
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl)19
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl75
-rw-r--r--indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl1
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl477
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/skyF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl44
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl49
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl52
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl68
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl119
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl63
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl166
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl70
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl79
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl202
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl122
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl70
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl40
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl111
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/indirect.glsl44
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/materialF.glsl455
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl190
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl)16
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl375
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl164
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl (renamed from indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl)29
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl566
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl73
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl66
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl74
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl67
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl49
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl157
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl62
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/skyF.glsl126
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/skyV.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl600
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl38
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl362
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl57
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl61
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl59
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl43
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl115
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterF.glsl174
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/waterV.glsl95
-rw-r--r--indra/newview/featuretable.txt42
-rw-r--r--indra/newview/featuretable_mac.txt41
-rw-r--r--indra/newview/licenses-mac.txt52
-rw-r--r--indra/newview/licenses-win32.txt49
-rw-r--r--indra/newview/llagentcamera.cpp6
-rw-r--r--indra/newview/llappviewer.cpp29
-rw-r--r--indra/newview/llcontrolavatar.cpp5
-rw-r--r--indra/newview/llcontrolavatar.h1
-rw-r--r--indra/newview/lldrawable.cpp3
-rw-r--r--indra/newview/lldrawpool.cpp4
-rw-r--r--indra/newview/lldrawpool.h5
-rw-r--r--indra/newview/lldrawpoolalpha.cpp16
-rw-r--r--indra/newview/lldrawpoolbump.cpp10
-rw-r--r--indra/newview/lldrawpoolpbropaque.cpp146
-rw-r--r--indra/newview/lldrawpoolpbropaque.h65
-rw-r--r--indra/newview/llface.cpp13
-rw-r--r--indra/newview/llfilepicker.cpp57
-rw-r--r--indra/newview/llfilepicker.h11
-rw-r--r--indra/newview/llfloaterbulkpermission.cpp1
-rw-r--r--indra/newview/llfloatermodelpreview.cpp6
-rw-r--r--indra/newview/llfloaterpreference.cpp51
-rw-r--r--indra/newview/llgltfmateriallist.cpp186
-rw-r--r--indra/newview/llgltfmateriallist.h (renamed from indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl)41
-rw-r--r--indra/newview/llhudicon.cpp52
-rw-r--r--indra/newview/llhudicon.h5
-rw-r--r--indra/newview/llinventorybridge.cpp85
-rw-r--r--indra/newview/llinventorybridge.h11
-rw-r--r--indra/newview/llinventoryfilter.cpp12
-rw-r--r--indra/newview/llinventoryicon.cpp5
-rw-r--r--indra/newview/llmaterialeditor.cpp1736
-rw-r--r--indra/newview/llmaterialeditor.h200
-rw-r--r--indra/newview/llmodelpreview.cpp50
-rw-r--r--indra/newview/llpaneleditsky.cpp15
-rw-r--r--indra/newview/llpaneleditsky.h1
-rw-r--r--indra/newview/llpanelface.cpp232
-rw-r--r--indra/newview/llpanelface.h7
-rw-r--r--indra/newview/llpanelgroupnotices.cpp1
-rw-r--r--indra/newview/llpanelmaininventory.cpp9
-rw-r--r--indra/newview/llpanelobjectinventory.cpp56
-rw-r--r--indra/newview/llpanelvolume.cpp95
-rw-r--r--indra/newview/llpanelvolume.h3
-rw-r--r--indra/newview/llreflectionmap.cpp269
-rw-r--r--indra/newview/llreflectionmap.h102
-rw-r--r--indra/newview/llreflectionmapmanager.cpp832
-rw-r--r--indra/newview/llreflectionmapmanager.h152
-rw-r--r--indra/newview/llselectmgr.cpp4
-rw-r--r--indra/newview/llsettingsvo.cpp1
-rw-r--r--indra/newview/llspatialpartition.cpp52
-rw-r--r--indra/newview/llspatialpartition.h30
-rw-r--r--indra/newview/lltexturectrl.cpp18
-rw-r--r--indra/newview/lltexturectrl.h2
-rw-r--r--indra/newview/lltexturefetch.cpp1
-rw-r--r--indra/newview/lltooldraganddrop.cpp80
-rw-r--r--indra/newview/lltooldraganddrop.h10
-rw-r--r--indra/newview/lltoolselect.cpp9
-rw-r--r--indra/newview/llviewerassettype.cpp1
-rw-r--r--indra/newview/llviewerassetupload.cpp61
-rw-r--r--indra/newview/llviewerassetupload.h35
-rw-r--r--indra/newview/llviewercamera.h13
-rw-r--r--indra/newview/llviewercontrol.cpp5
-rw-r--r--indra/newview/llviewerdisplay.cpp144
-rw-r--r--indra/newview/llviewerfloaterreg.cpp3
-rw-r--r--indra/newview/llviewerinventory.cpp11
-rw-r--r--indra/newview/llviewermenu.cpp30
-rw-r--r--indra/newview/llviewermenufile.cpp41
-rw-r--r--indra/newview/llviewermessage.cpp6
-rw-r--r--indra/newview/llviewerobject.cpp171
-rw-r--r--indra/newview/llviewerobject.h40
-rw-r--r--indra/newview/llviewerobjectlist.cpp167
-rw-r--r--indra/newview/llviewerobjectlist.h8
-rw-r--r--indra/newview/llviewerregion.cpp2
-rw-r--r--indra/newview/llviewershadermgr.cpp113
-rw-r--r--indra/newview/llviewershadermgr.h5
-rw-r--r--indra/newview/llviewertexteditor.cpp1
-rw-r--r--indra/newview/llviewertexture.cpp7
-rw-r--r--indra/newview/llviewertexture.h2
-rw-r--r--indra/newview/llviewerwindow.cpp189
-rw-r--r--indra/newview/llviewerwindow.h19
-rw-r--r--indra/newview/llvoavatar.cpp4
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvograss.cpp2
-rw-r--r--indra/newview/llvograss.h1
-rw-r--r--indra/newview/llvopartgroup.cpp2
-rw-r--r--indra/newview/llvopartgroup.h1
-rw-r--r--indra/newview/llvosurfacepatch.cpp2
-rw-r--r--indra/newview/llvosurfacepatch.h1
-rw-r--r--indra/newview/llvotree.cpp2
-rw-r--r--indra/newview/llvotree.h1
-rw-r--r--indra/newview/llvovolume.cpp312
-rw-r--r--indra/newview/llvovolume.h159
-rw-r--r--indra/newview/llworld.cpp3
-rw-r--r--indra/newview/pipeline.cpp1157
-rw-r--r--indra/newview/pipeline.h80
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Material.pngbin0 -> 684 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml43
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml501
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml201
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml65
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml527
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml46
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml90
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml24
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml23
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml29
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml3
245 files changed, 13686 insertions, 5155 deletions
diff --git a/autobuild.xml b/autobuild.xml
index e0f82a45eb..bf20cb788e 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -759,53 +759,17 @@
<string>glext</string>
<key>platforms</key>
<map>
- <key>darwin64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>1bd3214ac23474ea4c869e386970a1be</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54835/510029/glext-68-darwin64-538965.tar.bz2</string>
- </map>
- <key>name</key>
- <string>darwin64</string>
- </map>
- <key>linux64</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>5f3c9d61b620f949b199ebd8885218ed</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux64-314200.tar.bz2</string>
- </map>
- <key>name</key>
- <string>linux64</string>
- </map>
- <key>windows</key>
- <map>
- <key>archive</key>
- <map>
- <key>hash</key>
- <string>6a311615bce59b01cf73ee65012a9b38</string>
- <key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54951/511711/glext-68-windows-538965.tar.bz2</string>
- </map>
- <key>name</key>
- <string>windows</string>
- </map>
- <key>windows64</key>
+ <key>common</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
- <string>daf619dab1cf7518af6532b18800c4b0</string>
+ <string>4f8dc85863fec36e8d872c31f4abcd05</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54924/511490/glext-68-windows64-538965.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101480/892402/glext-68-common-572829.tar.bz2</string>
</map>
<key>name</key>
- <string>windows64</string>
+ <string>common</string>
</map>
</map>
<key>version</key>
@@ -2492,6 +2456,66 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>0.132.2</string>
</map>
+ <key>tinygltf</key>
+ <map>
+ <key>canonical_repo</key>
+ <string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
+ <key>copyright</key>
+ <string>// Copyright (c) 2015 - Present Syoyo Fujita, Aurélien Chatelain and many contributors.</string>
+ <key>description</key>
+ <string>tinygltf import library</string>
+ <key>license</key>
+ <string>MIT</string>
+ <key>license_file</key>
+ <string>LICENSES/tinygltf_license.txt</string>
+ <key>name</key>
+ <string>tinygltf</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7fd9a99cea31809c89759905fbba30c9</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7fd9a99cea31809c89759905fbba30c9</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7fd9a99cea31809c89759905fbba30c9</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100928/888701/tinygltf-v2.5.0-windows64-572493.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>source</key>
+ <string>https://bitbucket.org/lindenlab/3p-tinygltf</string>
+ <key>source_type</key>
+ <string>git</string>
+ <key>version</key>
+ <string>v2.5.0</string>
+ </map>
<key>tracy</key>
<map>
<key>canonical_repo</key>
@@ -2539,11 +2563,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>b649ee6591e67d2341e886b3fc3484a7</string>
+ <string>dff3dd1db6a4cb0b73f60a5db3ee0de2</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
- <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86974/801642/tracy-v0.7.8.563351-windows64-563351.tar.bz2</string>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/100101/882119/tracy-v0.8.1.571983-windows64-571983.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
@@ -2750,6 +2774,62 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>3.0.16.565299</string>
</map>
+ <key>vulkan_gltf</key>
+ <map>
+ <key>canonical_repo</key>
+ <string>https://bitbucket.org/lindenlab/3p-vulkan-gltf-pbr</string>
+ <key>copyright</key>
+ <string>Copyright (c) 2018 Sascha Willems</string>
+ <key>description</key>
+ <string>Vulkan GLTF Sample Implementation</string>
+ <key>license</key>
+ <string>Copyright (c) 2018 Sascha Willems</string>
+ <key>license_file</key>
+ <string>LICENSES/vulkan_gltf.txt</string>
+ <key>name</key>
+ <string>vulkan_gltf</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>8cff2060843db3db788511ee34a8e8cc</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101316/891509/vulkan_gltf-1-darwin64-572743.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>58eea384be49ba756ce9c5e66669540b</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101318/891520/vulkan_gltf-1-windows-572743.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ <key>windows64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>79b6a11622c2f83cfc2b7cd1fafb867b</string>
+ <key>url</key>
+ <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/101319/891521/vulkan_gltf-1-windows64-572743.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>1</string>
+ </map>
<key>xmlrpc-epi</key>
<map>
<key>copyright</key>
diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake
index 9fd3923bfd..a749644202 100644
--- a/indra/cmake/GLEXT.cmake
+++ b/indra/cmake/GLEXT.cmake
@@ -2,9 +2,7 @@
include(Prebuilt)
if (NOT USESYSTEMLIBS)
- if (WINDOWS OR LINUX)
- use_prebuilt_binary(glext)
- endif (WINDOWS OR LINUX)
+ use_prebuilt_binary(glext)
use_prebuilt_binary(glh_linear)
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
endif (NOT USESYSTEMLIBS)
diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake
index 868922451f..2d9d3725ad 100644
--- a/indra/cmake/LLRender.cmake
+++ b/indra/cmake/LLRender.cmake
@@ -3,10 +3,12 @@
include(Variables)
include(FreeType)
include(GLH)
+include(GLEXT)
set(LLRENDER_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llrender
${GLH_INCLUDE_DIR}
+ ${GLEXT_INCLUDE_DIR}
)
if (BUILD_HEADLESS)
diff --git a/indra/cmake/TinyGLTF.cmake b/indra/cmake/TinyGLTF.cmake
new file mode 100644
index 0000000000..bb731637a0
--- /dev/null
+++ b/indra/cmake/TinyGLTF.cmake
@@ -0,0 +1,7 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+use_prebuilt_binary(tinygltf)
+
+set(TINYGLTF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinygltf)
+
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake
index cfff956bcf..dba57eb920 100644
--- a/indra/cmake/Tracy.cmake
+++ b/indra/cmake/Tracy.cmake
@@ -12,6 +12,7 @@ if (USE_TRACY)
if (WINDOWS)
MESSAGE(STATUS "Including Tracy for Windows: '${TRACY_INCLUDE_DIR}'")
+ set(TRACY_LIBRARY "TracyClient")
endif (WINDOWS)
if (DARWIN)
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/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index e6cc06e8d0..f08cc18036 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -96,6 +96,7 @@ LLAssetDictionary::LLAssetDictionary()
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
+ addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true));
addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 652c548d59..e8df8574f7 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -127,8 +127,9 @@ public:
AT_RESERVED_6 = 55,
AT_SETTINGS = 56, // Collection of settings
-
- AT_COUNT = 57,
+ AT_MATERIAL = 57, // Render Material
+
+ AT_COUNT = 58,
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index c54029e8b4..58af32f1af 100644
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -30,9 +30,9 @@
#include "llframetimer.h"
// We don't bother building a stand alone lib; we just need to include the one source file for Tracy support
-#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
- #include "TracyClient.cpp"
-#endif // LL_PROFILER_CONFIGURATION
+//#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
+// #include "TracyClient.cpp"
+//#endif // LL_PROFILER_CONFIGURATION
// Static members
//LLTimer LLFrameTimer::sInternalTimer;
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index f9d7ae7ce4..bc46128d21 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -86,8 +86,8 @@ extern thread_local bool gProfilerEnabled;
#define TRACY_ONLY_IPV4 1
#include "Tracy.hpp"
- // Mutually exclusive with detailed memory tracing
- #define LL_PROFILER_ENABLE_TRACY_OPENGL 0
+ // Disable memory tracing when enabled, but enabled
+ #define LL_PROFILER_ENABLE_TRACY_OPENGL 1
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
@@ -104,8 +104,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER
#define LL_PROFILER_FRAME_END
@@ -121,8 +119,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_INFO(name) (void)(name); // Not supported
#define LL_PROFILE_ZONE_WARN(name) (void)(name); // Not supported
- #define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
- #define LL_PROFILE_FREE(ptr) (void)(ptr);
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
#define LL_PROFILER_FRAME_END FrameMark
@@ -138,14 +134,37 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_ZONE_ERR(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000 ) // RGB yellow
#define LL_PROFILE_ZONE_INFO(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF ) // RGB cyan
#define LL_PROFILE_ZONE_WARN(name) LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 ) // RGB red
- #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
- #define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#endif
#else
#define LL_PROFILER_FRAME_END
#define LL_PROFILER_SET_THREAD_NAME( name ) (void)(name)
#endif // LL_PROFILER
+#if LL_PROFILER_ENABLE_TRACY_OPENGL
+#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
+#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
+#define LL_PROFILER_GPU_COLLECT TracyGpuCollect
+#define LL_PROFILER_GPU_CONTEXT TracyGpuContext
+
+// disable memory tracking (incompatible with GPU tracing
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#else
+#define LL_PROFILE_GPU_ZONE(name) (void)name;
+#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
+#define LL_PROFILER_GPU_COLLECT
+#define LL_PROFILER_GPU_CONTEXT
+
+#if LL_PROFILER_CONFIG > 1
+#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
+#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
+#else
+#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
+#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#endif
+
+#endif
+
#include "llprofilercategories.h"
#endif // LL_PROFILER_H
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index ee43a599f7..538446d732 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -209,6 +209,7 @@ const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at)
{ LLAssetType::AT_PERSON, "PERSON" },
{ LLAssetType::AT_MESH, "MESH" },
{ LLAssetType::AT_SETTINGS, "SETTINGS" },
+ { LLAssetType::AT_MATERIAL, "MATERIAL" },
{ LLAssetType::AT_UNKNOWN, "UNKNOWN" }
};
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 0fa027c9c3..ad7124b5aa 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -815,6 +815,15 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
++sRawImageCount;
}
+LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components)
+ : LLImageBase()
+{
+ if (allocateDataSize(width, height, components))
+ {
+ memcpy(getData(), data, width * height * components);
+ }
+}
+
LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
: LLImageBase()
{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 7a588cfb03..59c192d9f8 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -184,6 +184,7 @@ protected:
public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
+ LLImageRaw(const U8* data, U16 width, U16 height, S8 components);
LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index 1f174520da..19f4d61b5b 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -93,9 +93,13 @@ public:
FT_SETTINGS = 56,
+ FT_MATERIAL = 57,
+
FT_COUNT,
FT_NONE = -1
+
+ // When adding, see note at bottom of LLAssetType::Etype
};
static EType lookup(const std::string& type_name);
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 853ed655f5..ceda2f3caf 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -86,6 +86,7 @@ LLInventoryDictionary::LLInventoryDictionary()
addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET));
addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON));
addEntry(LLInventoryType::IT_SETTINGS, new InventoryEntry("settings", "settings", 1, LLAssetType::AT_SETTINGS));
+ addEntry(LLInventoryType::IT_MATERIAL, new InventoryEntry("material", "render material", 1, LLAssetType::AT_MATERIAL));
}
@@ -153,7 +154,8 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_NONE, // 53 AT_RESERVED_4
LLInventoryType::IT_NONE, // 54 AT_RESERVED_5
- LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS
+ LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS <- why doesnt this match the value in llassettype.h? -brad
+ LLInventoryType::IT_MATERIAL, // 57 AT_MATERIAL
};
// static
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index b6e7fb047f..a5543814d8 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -65,7 +65,8 @@ public:
IT_WIDGET = 23,
IT_PERSON = 24,
IT_SETTINGS = 25,
- IT_COUNT = 26,
+ IT_MATERIAL = 26,
+ IT_COUNT = 27,
IT_UNKNOWN = 255,
IT_NONE = -1
@@ -118,6 +119,8 @@ public:
ICONNAME_SETTINGS_WATER,
ICONNAME_SETTINGS_DAY,
+ ICONNAME_MATERIAL,
+
ICONNAME_INVALID,
ICONNAME_UNKNOWN,
ICONNAME_COUNT,
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 83a92f08d0..d4e616abc2 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -131,6 +131,8 @@ const std::string LLSettingsSky::SETTING_SKY_MOISTURE_LEVEL("moisture_level");
const std::string LLSettingsSky::SETTING_SKY_DROPLET_RADIUS("droplet_radius");
const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level");
+const std::string LLSettingsSky::SETTING_REFLECTION_PROBE_AMBIANCE("reflection_probe_ambiance");
+
const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad");
static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver
@@ -630,6 +632,9 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal,
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+ validation.push_back(Validator(SETTING_REFLECTION_PROBE_AMBIANCE, false, LLSD::TypeReal,
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
+
validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
validation.push_back(Validator(SETTING_MIE_CONFIG, true, LLSD::TypeArray, &validateMieLayers));
@@ -755,6 +760,8 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position)
dfltsetting[SETTING_SKY_DROPLET_RADIUS] = 800.0f;
dfltsetting[SETTING_SKY_ICE_LEVEL] = 0.0f;
+ dfltsetting[SETTING_REFLECTION_PROBE_AMBIANCE] = 0.0f;
+
dfltsetting[SETTING_RAYLEIGH_CONFIG] = rayleighConfigDefault();
dfltsetting[SETTING_MIE_CONFIG] = mieConfigDefault();
dfltsetting[SETTING_ABSORPTION_CONFIG] = absorptionConfigDefault();
@@ -1132,6 +1139,11 @@ void LLSettingsSky::setSkyIceLevel(F32 ice_level)
setValue(SETTING_SKY_ICE_LEVEL, ice_level);
}
+void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance)
+{
+ setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance);
+}
+
void LLSettingsSky::setAmbientColor(const LLColor3 &val)
{
mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue();
@@ -1420,6 +1432,11 @@ F32 LLSettingsSky::getSkyIceLevel() const
return mSettings[SETTING_SKY_ICE_LEVEL].asReal();
}
+F32 LLSettingsSky::getReflectionProbeAmbiance() const
+{
+ return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal();
+}
+
F32 LLSettingsSky::getSkyBottomRadius() const
{
return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal();
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index fa9326f006..715d31518b 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -97,6 +97,8 @@ public:
static const std::string SETTING_SKY_DROPLET_RADIUS;
static const std::string SETTING_SKY_ICE_LEVEL;
+ static const std::string SETTING_REFLECTION_PROBE_AMBIANCE;
+
static const std::string SETTING_LEGACY_HAZE;
static const LLUUID DEFAULT_ASSET_ID;
@@ -131,6 +133,8 @@ public:
F32 getSkyDropletRadius() const;
F32 getSkyIceLevel() const;
+ F32 getReflectionProbeAmbiance() const;
+
// Return first (only) profile layer represented in LLSD
LLSD getRayleighConfig() const;
LLSD getMieConfig() const;
@@ -159,6 +163,8 @@ public:
void setSkyDropletRadius(F32 radius);
void setSkyIceLevel(F32 ice_level);
+ void setReflectionProbeAmbiance(F32 ambiance);
+
//---------------------------------------------------------------------
LLColor3 getAmbientColor() const;
void setAmbientColor(const LLColor3 &val);
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 175edf1471..f2863be531 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -88,7 +88,8 @@ class LLColor4
const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
const LLColor4& setAlpha(F32 a);
@@ -334,6 +335,15 @@ inline const LLColor4& LLColor4::set(const F32 *vec)
return (*this);
}
+inline const LLColor4& LLColor4::set(const F64 *vec)
+{
+ mV[VX] = static_cast<F32>(vec[VX]);
+ mV[VY] = static_cast<F32>(vec[VY]);
+ mV[VZ] = static_cast<F32>(vec[VZ]);
+ mV[VW] = static_cast<F32>(vec[VW]);
+ return (*this);
+}
+
// deprecated
inline const LLColor4& LLColor4::setVec(F32 x, F32 y, F32 z)
{
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt
index 7b6d04b096..bb14bb9242 100644
--- a/indra/llprimitive/CMakeLists.txt
+++ b/indra/llprimitive/CMakeLists.txt
@@ -10,15 +10,19 @@ include(LLCoreHttp)
include(LLXML)
include(LLPhysicsExtensions)
include(LLCharacter)
+include(LLRender)
+include(TinyGLTF)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
+ ${LLRENDER_INCLUDE_DIRS}
${LIBS_PREBUILT_DIR}/include/collada
${LIBS_PREBUILT_DIR}/include/collada/1.4
${LLCHARACTER_INCLUDE_DIRS}
+ ${TINYGLTF_INCLUDE_DIR}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -28,6 +32,7 @@ include_directories(SYSTEM
set(llprimitive_SOURCE_FILES
lldaeloader.cpp
+ llgltfloader.cpp
llmaterialid.cpp
llmaterial.cpp
llmaterialtable.cpp
@@ -46,6 +51,8 @@ set(llprimitive_SOURCE_FILES
set(llprimitive_HEADER_FILES
CMakeLists.txt
lldaeloader.h
+ llgltfloader.h
+ llgltfmaterial.h
legacy_object_types.h
llmaterial.h
llmaterialid.h
@@ -90,6 +97,7 @@ if (LL_TESTS)
INCLUDE(LLAddBuildTest)
SET(llprimitive_TEST_SOURCE_FILES
llmediaentry.cpp
+ llprimitive.cpp
)
LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")
endif (LL_TESTS)
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 68654486a4..50f4a4306e 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2504,20 +2504,6 @@ bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh, LLSD&
return (status == LLModel::NO_ERRORS);
}
-//static
-LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh)
-{
- LLVolumeParams volume_params;
- volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
- LLModel* ret = new LLModel(volume_params, 0.f);
- createVolumeFacesFromDomMesh(ret, mesh);
- if (ret->mLabel.empty())
- {
- ret->mLabel = getElementLabel(mesh);
- }
- return ret;
-}
-
//static diff version supports creating multiple models when material counts spill
// over the 8 face server-side limit
//
@@ -2608,31 +2594,3 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
return true;
}
-
-bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh)
-{
- if (mesh)
- {
- pModel->ClearFacesAndMaterials();
-
- LLSD placeholder;
- addVolumeFacesFromDomMesh(pModel, mesh, placeholder);
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- pModel->normalizeVolumeFaces();
- pModel->optimizeVolumeFaces();
-
- if (pModel->getNumVolumeFaces() > 0)
- {
- return true;
- }
- }
- }
- else
- {
- LL_WARNS() << "no mesh found" << LL_ENDL;
- }
-
- return false;
-}
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 2b211343e1..52ad908870 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -90,9 +90,6 @@ protected:
bool verifyController( domController* pController );
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh, LLSD& log_msg);
- static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
-
- static LLModel* loadModelFromDomMesh(domMesh* mesh);
// Loads a mesh breaking it into one or more models as necessary
// to get around volume face limitations while retaining >8 materials
diff --git a/indra/llprimitive/llgltfloader.cpp b/indra/llprimitive/llgltfloader.cpp
new file mode 100644
index 0000000000..6041c9c273
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.cpp
@@ -0,0 +1,402 @@
+/**
+ * @file LLGLTFLoader.cpp
+ * @brief LLGLTFLoader class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llgltfloader.h"
+
+// Import & define single-header gltf import/export lib
+#define TINYGLTF_IMPLEMENTATION
+#define TINYGLTF_USE_CPP14 // default is C++ 11
+
+// tinygltf by default loads image files using STB
+#define STB_IMAGE_IMPLEMENTATION
+// to use our own image loading:
+// 1. replace this definition with TINYGLTF_NO_STB_IMAGE
+// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data)
+
+// tinygltf saves image files using STB
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data)
+
+// Additionally, disable inclusion of STB header files entirely with
+// TINYGLTF_NO_INCLUDE_STB_IMAGE
+// TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
+#include "tinygltf/tiny_gltf.h"
+
+
+// TODO: includes inherited from dae loader. Validate / prune
+
+#include <boost/lexical_cast.hpp>
+
+#include "llsdserialize.h"
+#include "lljoint.h"
+
+#include "glh/glh_linear.h"
+#include "llmatrix4a.h"
+
+#include <boost/regex.hpp>
+#include <boost/algorithm/string/replace.hpp>
+
+static const std::string lod_suffix[LLModel::NUM_LODS] =
+{
+ "_LOD0",
+ "_LOD1",
+ "_LOD2",
+ "",
+ "_PHYS",
+};
+
+
+LLGLTFLoader::LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit) //,
+ //bool preprocess)
+ : LLModelLoader( filename,
+ lod,
+ load_cb,
+ joint_lookup_func,
+ texture_load_func,
+ state_cb,
+ opaque_userdata,
+ jointTransformMap,
+ jointsFromNodes,
+ jointAliasMap,
+ maxJointsPerMesh ),
+ //mPreprocessGLTF(preprocess),
+ mMeshesLoaded(false),
+ mMaterialsLoaded(false)
+{
+}
+
+LLGLTFLoader::~LLGLTFLoader() {}
+
+bool LLGLTFLoader::OpenFile(const std::string &filename)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename.rfind(".gltf"))
+ { // file is binary
+ mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg, &warn_msg, filename);
+ }
+
+ if (!mGltfLoaded)
+ {
+ if (!warn_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load warning: " << warn_msg.c_str() << LL_ENDL;
+ if (!error_msg.empty())
+ LL_WARNS("GLTF_IMPORT") << "gltf load error: " << error_msg.c_str() << LL_ENDL;
+ return false;
+ }
+
+ mMeshesLoaded = parseMeshes();
+ if (mMeshesLoaded) uploadMeshes();
+
+ mMaterialsLoaded = parseMaterials();
+ if (mMaterialsLoaded) uploadMaterials();
+
+ return (mMeshesLoaded || mMaterialsLoaded);
+}
+
+bool LLGLTFLoader::parseMeshes()
+{
+ if (!mGltfLoaded) return false;
+
+ // 2022-04 DJH Volume params from dae example. TODO understand PCODE
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+
+ for (tinygltf::Mesh mesh : mGltfModel.meshes)
+ {
+ LLModel *pModel = new LLModel(volume_params, 0.f);
+
+ if (populateModelFromMesh(pModel, mesh) &&
+ (LLModel::NO_ERRORS == pModel->getStatus()) &&
+ validate_model(pModel))
+ {
+ mModelList.push_back(pModel);
+ }
+ else
+ {
+ setLoadState(ERROR_MODEL + pModel->getStatus());
+ delete(pModel);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh)
+{
+ pModel->mLabel = mesh.name;
+ int pos_idx, norm_idx, tan_idx, uv0_idx, uv1_idx, color0_idx, color1_idx;
+ tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
+
+ auto prims = mesh.primitives;
+ for (auto prim : prims)
+ {
+ if (prim.indices >= 0) indices_a = mGltfModel.accessors[prim.indices];
+
+ pos_idx = (prim.attributes.count("POSITION") > 0) ? prim.attributes.at("POSITION") : -1;
+ if (pos_idx >= 0)
+ {
+ positions_a = mGltfModel.accessors[pos_idx];
+ if (TINYGLTF_COMPONENT_TYPE_FLOAT != positions_a.componentType)
+ continue;
+ auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
+ auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
+ //auto type = positions_vb.
+ //if (positions_buf.name
+ }
+
+ norm_idx = (prim.attributes.count("NORMAL") > 0) ? prim.attributes.at("NORMAL") : -1;
+ tan_idx = (prim.attributes.count("TANGENT") > 0) ? prim.attributes.at("TANGENT") : -1;
+ uv0_idx = (prim.attributes.count("TEXCOORDS_0") > 0) ? prim.attributes.at("TEXCOORDS_0") : -1;
+ uv1_idx = (prim.attributes.count("TEXCOORDS_1") > 0) ? prim.attributes.at("TEXCOORDS_1") : -1;
+ color0_idx = (prim.attributes.count("COLOR_0") > 0) ? prim.attributes.at("COLOR_0") : -1;
+ color1_idx = (prim.attributes.count("COLOR_1") > 0) ? prim.attributes.at("COLOR_1") : -1;
+
+ if (prim.mode == TINYGLTF_MODE_TRIANGLES)
+ {
+ //auto pos = mesh. TODO resume here DJH 2022-04
+ }
+ }
+
+ //pModel->addFace()
+ return false;
+}
+
+bool LLGLTFLoader::parseMaterials()
+{
+ if (!mGltfLoaded) return false;
+
+ // fill local texture data structures
+ mSamplers.clear();
+ for (auto in_sampler : mGltfModel.samplers)
+ {
+ gltf_sampler sampler;
+ sampler.magFilter = in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
+ sampler.minFilter = in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;;
+ sampler.wrapS = in_sampler.wrapS;
+ sampler.wrapT = in_sampler.wrapT;
+ sampler.name = in_sampler.name; // unused
+ mSamplers.push_back(sampler);
+ }
+
+ mImages.clear();
+ for (auto in_image : mGltfModel.images)
+ {
+ gltf_image image;
+ image.numChannels = in_image.component;
+ image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes
+ image.pixelType = in_image.pixel_type; // Maps exactly, i.e. TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
+ image.size = in_image.image.size();
+ image.height = in_image.height;
+ image.width = in_image.width;
+ image.data = in_image.image.data();
+
+ if (in_image.as_is)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Unsupported image encoding" << LL_ENDL;
+ return false;
+ }
+
+ if (image.size != image.height * image.width * image.numChannels * image.bytesPerChannel)
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image size error" << LL_ENDL;
+ return false;
+ }
+
+ mImages.push_back(image);
+ }
+
+ mTextures.clear();
+ for (auto in_tex : mGltfModel.textures)
+ {
+ gltf_texture tex;
+ tex.imageIdx = in_tex.source;
+ tex.samplerIdx = in_tex.sampler;
+ tex.imageUuid.setNull();
+
+ if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size())
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture sampler/image index error" << LL_ENDL;
+ return false;
+ }
+
+ mTextures.push_back(tex);
+ }
+
+ // parse each material
+ for (tinygltf::Material gltf_material : mGltfModel.materials)
+ {
+ gltf_render_material mat;
+ mat.name = gltf_material.name;
+
+ tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
+ mat.hasPBR = true; // Always true, for now
+
+ mat.baseColor.set(pbr.baseColorFactor.data());
+ mat.hasBaseTex = pbr.baseColorTexture.index >= 0;
+ mat.baseColorTexIdx = pbr.baseColorTexture.index;
+ mat.baseColorTexCoords = pbr.baseColorTexture.texCoord;
+
+ mat.metalness = pbr.metallicFactor;
+ mat.roughness = pbr.roughnessFactor;
+ mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0;
+ mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
+ mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord;
+
+ mat.normalScale = gltf_material.normalTexture.scale;
+ mat.hasNormalTex = gltf_material.normalTexture.index >= 0;
+ mat.normalTexIdx = gltf_material.normalTexture.index;
+ mat.normalTexCoords = gltf_material.normalTexture.texCoord;
+
+ mat.occlusionScale = gltf_material.occlusionTexture.strength;
+ mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0;
+ mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
+ mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord;
+
+ mat.emissiveColor.set(gltf_material.emissiveFactor.data());
+ mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0;
+ mat.emissiveTexIdx = gltf_material.emissiveTexture.index;
+ mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord;
+
+ mat.alphaMode = gltf_material.alphaMode;
+ mat.alphaMask = gltf_material.alphaCutoff;
+
+ if ((mat.hasNormalTex && (mat.normalTexIdx >= mTextures.size())) ||
+ (mat.hasOcclusionTex && (mat.occlusionTexIdx >= mTextures.size())) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexIdx >= mTextures.size())) ||
+ (mat.hasBaseTex && (mat.baseColorTexIdx >= mTextures.size())) ||
+ (mat.hasMRTex && (mat.metalRoughTexIdx >= mTextures.size())))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Texture resource index error" << LL_ENDL;
+ return false;
+ }
+
+ if ((mat.hasNormalTex && (mat.normalTexCoords > 2)) || // mesh can have up to 3 sets of UV
+ (mat.hasOcclusionTex && (mat.occlusionTexCoords > 2)) ||
+ (mat.hasEmissiveTex && (mat.emissiveTexCoords > 2)) ||
+ (mat.hasBaseTex && (mat.baseColorTexCoords > 2)) ||
+ (mat.hasMRTex && (mat.metalRoughTexCoords > 2)))
+ {
+ LL_WARNS("GLTF_IMPORT") << "Image texcoord index error" << LL_ENDL;
+ return false;
+ }
+
+ mMaterials.push_back(mat);
+ }
+
+ return true;
+}
+
+// TODO: convert raw vertex buffers to UUIDs
+void LLGLTFLoader::uploadMeshes()
+{
+ llassert(0);
+}
+
+// convert raw image buffers to texture UUIDs & assemble into a render material
+void LLGLTFLoader::uploadMaterials()
+{
+ for (gltf_render_material mat : mMaterials) // Initially 1 material per gltf file, but design for multiple
+ {
+ if (mat.hasBaseTex)
+ {
+ gltf_texture& gtex = mTextures[mat.baseColorTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasMRTex)
+ {
+ gltf_texture& gtex = mTextures[mat.metalRoughTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasNormalTex)
+ {
+ gltf_texture& gtex = mTextures[mat.normalTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasOcclusionTex)
+ {
+ gltf_texture& gtex = mTextures[mat.occlusionTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+
+ if (mat.hasEmissiveTex)
+ {
+ gltf_texture& gtex = mTextures[mat.emissiveTexIdx];
+ if (gtex.imageUuid.isNull())
+ {
+ gtex.imageUuid = imageBufferToTextureUUID(gtex);
+ }
+ }
+ }
+}
+
+LLUUID LLGLTFLoader::imageBufferToTextureUUID(const gltf_texture& tex)
+{
+ //gltf_image& image = mImages[tex.imageIdx];
+ //gltf_sampler& sampler = mSamplers[tex.samplerIdx];
+
+ // fill an LLSD container with image+sampler data
+
+ // upload texture
+
+ // retrieve UUID
+
+ return LLUUID::null;
+}
diff --git a/indra/llprimitive/llgltfloader.h b/indra/llprimitive/llgltfloader.h
new file mode 100644
index 0000000000..b4d6ca1940
--- /dev/null
+++ b/indra/llprimitive/llgltfloader.h
@@ -0,0 +1,206 @@
+/**
+ * @file LLGLTFLoader.h
+ * @brief LLGLTFLoader class definition
+ *
+ * $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$
+ */
+
+#ifndef LL_LLGLTFLoader_H
+#define LL_LLGLTFLoader_H
+
+#include "tinygltf/tiny_gltf.h"
+
+#include "llglheaders.h"
+#include "llmodelloader.h"
+
+// gltf_* structs are temporary, used to organize the subset of data that eventually goes into the material LLSD
+
+class gltf_sampler
+{
+public:
+ // Uses GL enums
+ S32 minFilter; // GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR or GL_LINEAR_MIPMAP_LINEAR
+ S32 magFilter; // GL_NEAREST or GL_LINEAR
+ S32 wrapS; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ S32 wrapT; // GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT or GL_REPEAT
+ //S32 wrapR; // Found in some sample files, but not part of glTF 2.0 spec. Ignored.
+ std::string name; // optional, currently unused
+ // extensions and extras are sampler optional fields that we don't support - at least initially
+};
+
+class gltf_image
+{
+public:// Note that glTF images are defined with row 0 at the top (opposite of OpenGL)
+ U8* data; // ptr to decoded image data
+ U32 size; // in bytes, regardless of channel width
+ U32 width;
+ U32 height;
+ U32 numChannels; // range 1..4
+ U32 bytesPerChannel; // converted from gltf "bits", expects only 8, 16 or 32 as input
+ U32 pixelType; // one of (TINYGLTF_COMPONENT_TYPE)_UNSIGNED_BYTE, _UNSIGNED_SHORT, _UNSIGNED_INT, or _FLOAT
+};
+
+class gltf_texture
+{
+public:
+ U32 imageIdx;
+ U32 samplerIdx;
+ LLUUID imageUuid = LLUUID::null;
+};
+
+class gltf_render_material
+{
+public:
+ std::string name;
+
+ // scalar values
+ LLColor4 baseColor; // linear encoding. Multiplied with vertex color, if present.
+ double metalness;
+ double roughness;
+ double normalScale; // scale applies only to X,Y components of normal
+ double occlusionScale; // strength multiplier for occlusion
+ LLColor4 emissiveColor; // emissive mulitiplier, assumed linear encoding (spec 2.0 is silent)
+ std::string alphaMode; // "OPAQUE", "MASK" or "BLEND"
+ double alphaMask; // alpha cut-off
+
+ // textures
+ U32 baseColorTexIdx; // always sRGB encoded
+ U32 metalRoughTexIdx; // always linear, roughness in G channel, metalness in B channel
+ U32 normalTexIdx; // linear, valid range R[0-1], G[0-1], B[0.5-1]. Normal = texel * 2 - vec3(1.0)
+ U32 occlusionTexIdx; // linear, occlusion in R channel, 0 meaning fully occluded, 1 meaning not occluded
+ U32 emissiveTexIdx; // always stored as sRGB, in nits (candela / meter^2)
+
+ // texture coordinates
+ U32 baseColorTexCoords;
+ U32 metalRoughTexCoords;
+ U32 normalTexCoords;
+ U32 occlusionTexCoords;
+ U32 emissiveTexCoords;
+
+ // TODO: Add traditional (diffuse, normal, specular) UUIDs here, or add this struct to LL_TextureEntry??
+
+ bool hasPBR;
+ bool hasBaseTex, hasMRTex, hasNormalTex, hasOcclusionTex, hasEmissiveTex;
+
+ // This field is populated after upload
+ LLUUID material_uuid = LLUUID::null;
+
+};
+
+class gltf_mesh
+{
+public:
+ std::string name;
+
+ // TODO add mesh import DJH 2022-04
+
+};
+
+class LLGLTFLoader : public LLModelLoader
+{
+ public:
+ typedef std::map<std::string, LLImportMaterial> material_map;
+
+ LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string> &jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit); //,
+ //bool preprocess );
+ virtual ~LLGLTFLoader();
+
+ virtual bool OpenFile(const std::string &filename);
+
+protected:
+ tinygltf::Model mGltfModel;
+ bool mGltfLoaded;
+ bool mMeshesLoaded;
+ bool mMaterialsLoaded;
+
+ std::vector<gltf_mesh> mMeshes;
+ std::vector<gltf_render_material> mMaterials;
+
+ std::vector<gltf_texture> mTextures;
+ std::vector<gltf_image> mImages;
+ std::vector<gltf_sampler> mSamplers;
+
+private:
+ bool parseMeshes();
+ void uploadMeshes();
+ bool parseMaterials();
+ void uploadMaterials();
+ bool populateModelFromMesh(LLModel* pModel, const tinygltf::Mesh &mesh);
+ LLUUID imageBufferToTextureUUID(const gltf_texture& tex);
+
+ // bool mPreprocessGLTF;
+
+ /* Below inherited from dae loader - unknown if/how useful here
+
+ void processElement(gltfElement *element, bool &badElement, GLTF *gltf);
+ void processGltfModel(LLModel *model, GLTF *gltf, gltfElement *pRoot, gltfMesh *mesh, gltfSkin *skin);
+
+ material_map getMaterials(LLModel *model, gltfInstance_geometry *instance_geo, GLTF *gltf);
+ LLImportMaterial profileToMaterial(gltfProfile_COMMON *material, GLTF *gltf);
+ LLColor4 getGltfColor(gltfElement *element);
+
+ gltfElement *getChildFromElement(gltfElement *pElement, std::string const &name);
+
+ bool isNodeAJoint(gltfNode *pNode);
+ void processJointNode(gltfNode *pNode, std::map<std::string, LLMatrix4> &jointTransforms);
+ void extractTranslation(gltfTranslate *pTranslate, LLMatrix4 &transform);
+ void extractTranslationViaElement(gltfElement *pTranslateElement, LLMatrix4 &transform);
+ void extractTranslationViaSID(gltfElement *pElement, LLMatrix4 &transform);
+ void buildJointToNodeMappingFromScene(gltfElement *pRoot);
+ void processJointToNodeMapping(gltfNode *pNode);
+ void processChildJoints(gltfNode *pParentNode);
+
+ bool verifyCount(int expected, int result);
+
+ // Verify that a controller matches vertex counts
+ bool verifyController(gltfController *pController);
+
+ static bool addVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh, LLSD &log_msg);
+ static bool createVolumeFacesFromGltfMesh(LLModel *model, gltfMesh *mesh);
+
+ static LLModel *loadModelFromGltfMesh(gltfMesh *mesh);
+
+ // Loads a mesh breaking it into one or more models as necessary
+ // to get around volume face limitations while retaining >8 materials
+ //
+ bool loadModelsFromGltfMesh(gltfMesh *mesh, std::vector<LLModel *> &models_out, U32 submodel_limit);
+
+ static std::string getElementLabel(gltfElement *element);
+ static size_t getSuffixPosition(std::string label);
+ static std::string getLodlessLabel(gltfElement *element);
+
+ static std::string preprocessGLTF(std::string filename);
+ */
+
+};
+#endif // LL_LLGLTFLLOADER_H
diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
new file mode 100644
index 0000000000..a8d5fb8e85
--- /dev/null
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -0,0 +1,101 @@
+/**
+ * @file llgltfmaterial.h
+ * @brief Material definition
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llrefcount.h"
+#include "v4color.h"
+#include "v3color.h"
+#include "lluuid.h"
+#include "llmd5.h"
+
+class LLGLTFMaterial : public LLRefCount
+{
+public:
+
+ enum AlphaMode
+ {
+ ALPHA_MODE_OPAQUE = 0,
+ ALPHA_MODE_BLEND,
+ ALPHA_MODE_MASK
+ };
+
+ LLUUID mAlbedoId;
+ LLUUID mNormalId;
+ LLUUID mMetallicRoughnessId;
+ LLUUID mEmissiveId;
+
+ LLColor4 mAlbedoColor = LLColor4(1,1,1,1);
+ LLColor3 mEmissiveColor = LLColor3(0,0,0);
+
+ F32 mMetallicFactor = 0.f;
+ F32 mRoughnessFactor = 0.f;
+ F32 mAlphaCutoff = 0.f;
+
+ bool mDoubleSided = false;
+ AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
+
+ // get a UUID based on a hash of this LLGLTFMaterial
+ LLUUID getHash() const
+ {
+ LLMD5 md5;
+ md5.update((unsigned char*) this, sizeof(this));
+ LLUUID id;
+ md5.raw_digest(id.mData);
+ return id;
+ }
+
+ // set mAlphaMode from string.
+ // Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE
+ void setAlphaMode(const std::string& mode)
+ {
+ if (mode == "MASK")
+ {
+ mAlphaMode = ALPHA_MODE_MASK;
+ }
+ else if (mode == "BLEND")
+ {
+ mAlphaMode = ALPHA_MODE_BLEND;
+ }
+ else
+ {
+ mAlphaMode = ALPHA_MODE_OPAQUE;
+ }
+ }
+
+ const char* getAlphaMode()
+ {
+ switch (mAlphaMode)
+ {
+ case ALPHA_MODE_MASK: return "MASK";
+ case ALPHA_MODE_BLEND: return "BLEND";
+ default: return "OPAQUE";
+ }
+ }
+};
+
+
+
diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp
index a219ac1450..f546ac1645 100644
--- a/indra/llprimitive/llmaterial.cpp
+++ b/indra/llprimitive/llmaterial.cpp
@@ -331,6 +331,17 @@ void LLMaterial::setAlphaMaskCutoff(U8 cutoff)
mAlphaMaskCutoff = cutoff;
}
+LLUUID LLMaterial::getMaterialID() const
+{
+ // TODO - not null
+ return LLUUID::null;
+}
+
+void LLMaterial::setMaterialID(const LLUUID &material_id)
+{
+ // TODO - set
+}
+
LLSD LLMaterial::asLLSD() const
{
LLSD material_data;
diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h
index d58b7ee812..2f8aafc2cf 100644
--- a/indra/llprimitive/llmaterial.h
+++ b/indra/llprimitive/llmaterial.h
@@ -27,8 +27,6 @@
#ifndef LL_LLMATERIAL_H
#define LL_LLMATERIAL_H
-#include <boost/shared_ptr.hpp>
-
#include "llmaterialid.h"
#include "llsd.h"
#include "v4coloru.h"
@@ -54,8 +52,6 @@ public:
ALPHA_SHADER_COUNT = 4
} eShaderCount;
-
-
static const U8 DEFAULT_SPECULAR_LIGHT_EXPONENT = ((U8)(0.2f * 255));
static const LLColor4U DEFAULT_SPECULAR_LIGHT_COLOR;
static const U8 DEFAULT_ENV_INTENSITY = 0;
@@ -119,6 +115,8 @@ public:
void setDiffuseAlphaMode(U8 alpha_mode);
U8 getAlphaMaskCutoff() const;
void setAlphaMaskCutoff(U8 cutoff);
+ LLUUID getMaterialID() const;
+ void setMaterialID(LLUUID const & material_id);
bool isNull() const;
static const LLMaterial null;
diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp
index f88a607c4f..340a83801c 100644
--- a/indra/llprimitive/llmaterialid.cpp
+++ b/indra/llprimitive/llmaterialid.cpp
@@ -155,6 +155,13 @@ std::string LLMaterialID::asString() const
return materialIDString;
}
+LLUUID LLMaterialID::asUUID() const
+{
+ LLUUID ret;
+ memcpy(ret.mData, mID, MATERIAL_ID_SIZE);
+ return ret;
+}
+
std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id)
{
s << material_id.asString();
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
index ee663f8f99..e6165dfc91 100644
--- a/indra/llprimitive/llmaterialid.h
+++ b/indra/llprimitive/llmaterialid.h
@@ -61,6 +61,7 @@ public:
LLSD asLLSD() const;
std::string asString() const;
+ LLUUID asUUID() const;
friend std::ostream& operator<<(std::ostream& s, const LLMaterialID &material_id);
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 5171621007..554ed54de1 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -160,7 +160,8 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
std::string::size_type i = model_filename.rfind(".");
if (i != std::string::npos)
{
- slm_filename.replace(i, model_filename.size()-1, ".slm");
+ slm_filename.resize(i, '\0');
+ slm_filename.append(".slm");
return true;
}
else
@@ -172,7 +173,7 @@ bool LLModelLoader::getSLMFilename(const std::string& model_filename, std::strin
bool LLModelLoader::doLoadModel()
{
//first, look for a .slm file of the same name that was modified later
- //than the .dae
+ //than the specified model file
if (mTrySLM)
{
@@ -182,13 +183,13 @@ bool LLModelLoader::doLoadModel()
llstat slm_status;
if (LLFile::stat(slm_filename, &slm_status) == 0)
{ //slm file exists
- llstat dae_status;
- if (LLFile::stat(mFilename, &dae_status) != 0 ||
- dae_status.st_mtime < slm_status.st_mtime)
+ llstat model_file_status;
+ if (LLFile::stat(mFilename, &model_file_status) != 0 ||
+ model_file_status.st_mtime < slm_status.st_mtime)
{
if (loadFromSLM(slm_filename))
{ //slm successfully loaded, if this fails, fall through and
- //try loading from dae
+ //try loading from model file
mLod = -1; //successfully loading from an slm implicitly sets all
//LoDs
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 67c225d25d..3f0059b759 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -39,6 +39,7 @@
#include "llsdutil_math.h"
#include "llprimtexturelist.h"
#include "llmaterialid.h"
+#include "llsdutil.h"
/**
* exported constants
@@ -80,6 +81,14 @@ const F32 LIGHT_MIN_CUTOFF = 0.0f;
const F32 LIGHT_DEFAULT_CUTOFF = 0.0f;
const F32 LIGHT_MAX_CUTOFF = 180.f;
+// reflection probes
+const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_AMBIANCE = 1.f;
+const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f;
+const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f;
+const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f;
+const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f;
+
// "Tension" => [0,10], increments of 0.1
const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f;
const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f;
@@ -1690,6 +1699,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 28);
case PARAMS_EXTENDED_MESH:
return (size == 4);
+ case PARAMS_RENDER_MATERIAL:
+ return (size > 1);
}
return FALSE;
@@ -1808,6 +1819,118 @@ bool LLLightParams::fromLLSD(LLSD& sd)
//============================================================================
+//============================================================================
+
+LLReflectionProbeParams::LLReflectionProbeParams()
+{
+ mType = PARAMS_REFLECTION_PROBE;
+}
+
+BOOL LLReflectionProbeParams::pack(LLDataPacker &dp) const
+{
+ dp.packF32(mAmbiance, "ambiance");
+ dp.packF32(mClipDistance, "clip_distance");
+ dp.packU8(mFlags, "flags");
+ return TRUE;
+}
+
+BOOL LLReflectionProbeParams::unpack(LLDataPacker &dp)
+{
+ F32 ambiance;
+ F32 clip_distance;
+
+ dp.unpackF32(ambiance, "ambiance");
+ setAmbiance(ambiance);
+
+ dp.unpackF32(clip_distance, "clip_distance");
+ setClipDistance(clip_distance);
+
+ dp.unpackU8(mFlags, "flags");
+
+ return TRUE;
+}
+
+bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_REFLECTION_PROBE)
+ {
+ return false;
+ }
+ const LLReflectionProbeParams *param = (const LLReflectionProbeParams*)&data;
+ if (param->mAmbiance != mAmbiance)
+ {
+ return false;
+ }
+ if (param->mClipDistance != mClipDistance)
+ {
+ return false;
+ }
+ if (param->mFlags != mFlags)
+ {
+ return false;
+ }
+ return true;
+}
+
+void LLReflectionProbeParams::copy(const LLNetworkData& data)
+{
+ const LLReflectionProbeParams *param = (LLReflectionProbeParams*)&data;
+ mType = param->mType;
+ mAmbiance = param->mAmbiance;
+ mClipDistance = param->mClipDistance;
+ mFlags = param->mFlags;
+}
+
+LLSD LLReflectionProbeParams::asLLSD() const
+{
+ LLSD sd;
+ sd["ambiance"] = getAmbiance();
+ sd["clip_distance"] = getClipDistance();
+ sd["flags"] = mFlags;
+ return sd;
+}
+
+bool LLReflectionProbeParams::fromLLSD(LLSD& sd)
+{
+ if (!sd.has("ambiance") ||
+ !sd.has("clip_distance") ||
+ !sd.has("flags"))
+ {
+ return false;
+ }
+
+ setAmbiance((F32)sd["ambiance"].asReal());
+ setClipDistance((F32)sd["clip_distance"].asReal());
+ mFlags = (U8) sd["flags"].asInteger();
+
+ return true;
+}
+
+void LLReflectionProbeParams::setIsBox(bool is_box)
+{
+ if (is_box)
+ {
+ mFlags |= FLAG_BOX_VOLUME;
+ }
+ else
+ {
+ mFlags &= ~FLAG_BOX_VOLUME;
+ }
+}
+
+void LLReflectionProbeParams::setIsDynamic(bool is_dynamic)
+{
+ if (is_dynamic)
+ {
+ mFlags |= FLAG_DYNAMIC;
+ }
+ else
+ {
+ mFlags &= ~FLAG_DYNAMIC;
+ }
+}
+
+//============================================================================
LLFlexibleObjectData::LLFlexibleObjectData()
{
mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS;
@@ -2181,3 +2304,142 @@ bool LLExtendedMeshParams::fromLLSD(LLSD& sd)
return false;
}
+
+//============================================================================
+
+LLRenderMaterialParams::LLRenderMaterialParams()
+{
+ mType = PARAMS_RENDER_MATERIAL;
+}
+
+BOOL LLRenderMaterialParams::pack(LLDataPacker& dp) const
+{
+ U8 count = (U8)llmin((S32)mEntries.size(), 14); //limited to 255 bytes, no more than 14 material ids
+
+ dp.packU8(count, "count");
+ for (auto& entry : mEntries)
+ {
+ dp.packU8(entry.te_idx, "te_idx");
+ dp.packUUID(entry.id, "id");
+ }
+
+ return TRUE;
+}
+
+BOOL LLRenderMaterialParams::unpack(LLDataPacker& dp)
+{
+ U8 count;
+ dp.unpackU8(count, "count");
+ mEntries.resize(count);
+ for (auto& entry : mEntries)
+ {
+ dp.unpackU8(entry.te_idx, "te_idx");
+ dp.unpackUUID(entry.id, "te_id");
+ }
+
+ return TRUE;
+}
+
+bool LLRenderMaterialParams::operator==(const LLNetworkData& data) const
+{
+ if (data.mType != PARAMS_RENDER_MATERIAL)
+ {
+ return false;
+ }
+
+ const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+
+ if (param.mEntries.size() != mEntries.size())
+ {
+ return false;
+ }
+
+ for (auto& entry : mEntries)
+ {
+ if (param.getMaterial(entry.te_idx) != entry.id)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void LLRenderMaterialParams::copy(const LLNetworkData& data)
+{
+ llassert_always(data.mType == PARAMS_RENDER_MATERIAL);
+ const LLRenderMaterialParams& param = static_cast<const LLRenderMaterialParams&>(data);
+ mEntries = param.mEntries;
+}
+
+LLSD LLRenderMaterialParams::asLLSD() const
+{
+ LLSD ret;
+
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ ret[i]["te_idx"] = mEntries[i].te_idx;
+ ret[i]["id"] = mEntries[i].id;
+ }
+
+ return ret;
+}
+
+bool LLRenderMaterialParams::fromLLSD(LLSD& sd)
+{
+ if (sd.isArray())
+ {
+ mEntries.resize(sd.size());
+ for (int i = 0; i < sd.size(); ++i)
+ {
+ if (sd[i].has("te_idx") && sd.has("id"))
+ {
+ mEntries[i].te_idx = sd[i]["te_idx"].asInteger();
+ mEntries[i].id = sd[i]["id"].asUUID();
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void LLRenderMaterialParams::setMaterial(U8 te, const LLUUID& id)
+{
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ if (mEntries[i].te_idx == te)
+ {
+ if (id.isNull())
+ {
+ mEntries.erase(mEntries.begin() + i);
+ }
+ else
+ {
+ mEntries[i].id = id;
+ }
+ return;
+ }
+ }
+
+ mEntries.push_back({ te, id });
+}
+
+const LLUUID& LLRenderMaterialParams::getMaterial(U8 te) const
+{
+ for (int i = 0; i < mEntries.size(); ++i)
+ {
+ if (mEntries[i].te_idx == te)
+ {
+ return mEntries[i].id;
+ }
+ }
+
+ return LLUUID::null;
+}
+
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 309b18faa9..d2adfa4a3d 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -107,6 +107,8 @@ public:
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
+ PARAMS_RENDER_MATERIAL = 0x80,
+ PARAMS_REFLECTION_PROBE = 0x90,
};
public:
@@ -170,6 +172,50 @@ public:
F32 getCutoff() const { return mCutoff; }
};
+extern const F32 REFLECTION_PROBE_MIN_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MAX_AMBIANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE;
+extern const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE;
+extern const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+
+class LLReflectionProbeParams : public LLNetworkData
+{
+public:
+ enum EFlags : U8
+ {
+ FLAG_BOX_VOLUME = 0x01, // use a box influence volume
+ FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe
+ };
+
+protected:
+ F32 mAmbiance = REFLECTION_PROBE_DEFAULT_AMBIANCE;
+ F32 mClipDistance = REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE;
+ U8 mFlags = 0;
+
+public:
+ LLReflectionProbeParams();
+ /*virtual*/ BOOL pack(LLDataPacker& dp) const;
+ /*virtual*/ BOOL unpack(LLDataPacker& dp);
+ /*virtual*/ bool operator==(const LLNetworkData& data) const;
+ /*virtual*/ void copy(const LLNetworkData& data);
+ // LLSD implementations here are provided by Eddy Stryker.
+ // NOTE: there are currently unused in protocols
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setAmbiance(F32 ambiance) { mAmbiance = llclamp(ambiance, REFLECTION_PROBE_MIN_AMBIANCE, REFLECTION_PROBE_MAX_AMBIANCE); }
+ void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
+ void setIsBox(bool is_box);
+ void setIsDynamic(bool is_dynamic);
+
+ F32 getAmbiance() const { return mAmbiance; }
+ F32 getClipDistance() const { return mClipDistance; }
+ bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; }
+ bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; }
+};
+
//-------------------------------------------------
// This structure is also used in the part of the
// code that creates new flexible objects.
@@ -320,6 +366,33 @@ public:
};
+class LLRenderMaterialParams : public LLNetworkData
+{
+private:
+ struct Entry
+ {
+ U8 te_idx;
+ LLUUID id;
+ };
+ std::vector< Entry > mEntries;
+
+public:
+ LLRenderMaterialParams();
+ BOOL pack(LLDataPacker& dp) const override;
+ BOOL unpack(LLDataPacker& dp) override;
+ bool operator==(const LLNetworkData& data) const override;
+ void copy(const LLNetworkData& data) override;
+ LLSD asLLSD() const;
+ operator LLSD() const { return asLLSD(); }
+ bool fromLLSD(LLSD& sd);
+
+ void setMaterial(U8 te_idx, const LLUUID& id);
+ const LLUUID& getMaterial(U8 te_idx) const;
+
+ bool isEmpty() { return mEntries.empty(); }
+};
+
+
// This code is not naming-standards compliant. Leaving it like this for
// now to make the connection to code in
// BOOL packTEMessage(LLDataPacker &dp) const;
@@ -415,12 +488,12 @@ public:
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
- virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
+ virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
virtual void setTESelected(const U8 te, bool sel);
LLMaterialPtr getTEMaterialParams(const U8 index);
-
+
void copyTEs(const LLPrimitive *primitive);
S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;
BOOL packTEMessage(LLMessageSystem *mesgsys) const;
@@ -498,6 +571,8 @@ public:
static LLPCode legacyToPCode(const U8 legacy);
static U8 pCodeToLegacy(const LLPCode pcode);
static bool getTESTAxes(const U8 face, U32* s_axis, U32* t_axis);
+
+ BOOL hasRenderMaterialParams() const;
inline static BOOL isPrimitive(const LLPCode pcode);
inline static BOOL isApp(const LLPCode pcode);
diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index dc2e201044..1549b2ce87 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -32,6 +32,7 @@
#include "llsd.h"
#include "llmaterialid.h"
#include "llmaterial.h"
+#include "llgltfmaterial.h"
// These bits are used while unpacking TEM messages to tell which aspects of
// the texture entry changed.
@@ -134,6 +135,10 @@ public:
S32 setMaterialID(const LLMaterialID& pMaterialID);
S32 setMaterialParams(const LLMaterialPtr pMaterialParams);
+ void setGLTFMaterial(LLGLTFMaterial* material) { mGLTFMaterial = material; }
+ LLGLTFMaterial* getGLTFMaterial() { return mGLTFMaterial; }
+
+
virtual const LLUUID &getID() const { return mID; }
const LLColor4 &getColor() const { return mColor; }
const F32 getAlpha() const { return mColor.mV[VALPHA]; }
@@ -162,6 +167,8 @@ public:
const LLMaterialID& getMaterialID() const { return mMaterialID; };
const LLMaterialPtr getMaterialParams() const { return mMaterial; };
+ LLGLTFMaterial* getGLTFMaterial() const { return mGLTFMaterial; }
+
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
// to NOT return NULL.
@@ -219,6 +226,7 @@ protected:
bool mMaterialUpdatePending;
LLMaterialID mMaterialID;
LLMaterialPtr mMaterial;
+ LLPointer<LLGLTFMaterial> mGLTFMaterial; // if present, ignore mMaterial
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face
diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp
index 04e70945c4..9006833054 100644
--- a/indra/llprimitive/tests/llmessagesystem_stub.cpp
+++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp
@@ -25,7 +25,7 @@
#include "linden_common.h"
-char * _PREHASH_TextureEntry;
+const char * const _PREHASH_TextureEntry = "TextureEntry";
S32 LLMessageSystem::getSizeFast(char const*, char const*) const
{
diff --git a/indra/llprimitive/tests/llprimitive_test.cpp b/indra/llprimitive/tests/llprimitive_test.cpp
index 0d60c7cd15..0ff0795fdc 100644
--- a/indra/llprimitive/tests/llprimitive_test.cpp
+++ b/indra/llprimitive/tests/llprimitive_test.cpp
@@ -71,6 +71,46 @@ private:
S32 mCurrDetailTest;
};
+LLMaterialID::LLMaterialID() {}
+LLMaterialID::LLMaterialID(LLMaterialID const &m) = default;
+LLMaterialID::~LLMaterialID() {}
+void LLMaterialID::set(void const*) { }
+U8 const * LLMaterialID::get() const { return mID; }
+
+LLPrimTextureList::LLPrimTextureList() { }
+LLPrimTextureList::~LLPrimTextureList() { }
+S32 LLPrimTextureList::setBumpMap(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffsetT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry &te) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setRotation(const U8 index, const F32 r) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShiny(const U8 index, const U8 bump_shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setFullbright(const U8 index, const U8 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMaterialID) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMediaTexGen(const U8 index, const U8 media) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setBumpShinyFullbright(const U8 index, const U8 bump) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setID(const U8 index, const LLUUID& id) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setGlow(const U8 index, const F32 glow) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setAlpha(const U8 index, const F32 alpha) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor3& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setColor(const U8 index, const LLColor4& color) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScale(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleS(const U8 index, const F32 s) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setScaleT(const U8 index, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setShiny(const U8 index, const U8 shiny) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setOffset(const U8 index, const F32 s, const F32 t) { return TEM_CHANGE_NONE; }
+S32 LLPrimTextureList::setTexGen(const U8 index, const U8 texgen) { return TEM_CHANGE_NONE; }
+
+LLMaterialPtr LLPrimTextureList::getMaterialParams(const U8 index) { return LLMaterialPtr(); }
+void LLPrimTextureList::copy(LLPrimTextureList const & ptl) { mEntryList = ptl.mEntryList; } // do we need to call getTexture()->newCopy()?
+void LLPrimTextureList::take(LLPrimTextureList &other_list) { }
+void LLPrimTextureList::setSize(S32 new_size) { mEntryList.resize(new_size); }
+void LLPrimTextureList::setAllIDs(const LLUUID &id) { }
+LLTextureEntry * LLPrimTextureList::getTexture(const U8 index) const { return nullptr; }
+S32 LLPrimTextureList::size() const { return mEntryList.size(); }
+
class PRIMITIVE_TEST_SETUP
{
public:
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index baab09a104..a30f47f1d9 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -31,6 +31,7 @@ include_directories(SYSTEM
set(llrender_SOURCE_FILES
llatmosphere.cpp
llcubemap.cpp
+ llcubemaparray.cpp
llfontbitmapcache.cpp
llfontfreetype.cpp
llfontgl.cpp
@@ -58,6 +59,7 @@ set(llrender_HEADER_FILES
llatmosphere.h
llcubemap.h
+ llcubemaparray.h
llfontgl.h
llfontfreetype.h
llfontbitmapcache.h
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 834084674e..473447ad72 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -40,8 +40,9 @@
#include "llglheaders.h"
-const F32 epsilon = 1e-7f;
-const U16 RESOLUTION = 64;
+namespace {
+ const U16 RESOLUTION = 64;
+}
bool LLCubeMap::sUseCubeMaps = true;
@@ -166,6 +167,73 @@ void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
}
}
+void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImages[0] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[0]->setTexName(texname);
+ mImages[0]->setTarget(mTargets[0], LLTexUnit::TT_CUBE_MAP);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
+
+void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages)
+{
+ llassert(rawimages.size() == 6);
+
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ U32 resolution = rawimages[0]->getWidth();
+ U32 components = rawimages[0]->getComponents();
+
+ for (int i = 0; i < 6; i++)
+ {
+ llassert(rawimages[i]->getWidth() == resolution);
+ llassert(rawimages[i]->getHeight() == resolution);
+ llassert(rawimages[i]->getComponents() == components);
+
+ mImages[i] = new LLImageGL(resolution, resolution, components, TRUE);
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
+ mRawImages[i] = rawimages[i];
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, resolution, resolution);
+ }
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
+void LLCubeMap::generateMipMaps()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ mImages[0]->setUseMipMaps(TRUE);
+ mImages[0]->setHasMipMaps(TRUE);
+ enableTexture(0);
+ bind();
+ mImages[0]->setFilteringOption(LLTexUnit::TFO_BILINEAR);
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cmgmm - glGenerateMipmap");
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
+ }
+ gGL.getTexUnit(0)->disable();
+ disable();
+}
+
GLuint LLCubeMap::getGLName()
{
return mImages[0]->getTexName();
@@ -256,191 +324,6 @@ void LLCubeMap::restoreMatrix()
}*/
}
-void LLCubeMap::setReflection (void)
-{
- gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
- mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- mImages[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
-}
-
-LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
-{
- LLVector3 dir;
-
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- dir.mV[curr_coef] = side_dir;
-
- switch (side)
- {
- case 0: // negative X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 1: // positive X
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 2: // negative Y
- dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 3: // positive Y
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- break;
- case 4: // negative Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
- break;
- case 5: // positive Z
- dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
- dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- break;
- default:
- dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
- dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
- }
-
- dir.normVec();
- return dir;
-}
-
-
-BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const
-{
- const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
- const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
- const U8 i_coef = (curr_coef + 1) % 3;
- const U8 j_coef = (i_coef + 1) % 3;
-
- outside = TRUE;
- if (side_dir * dir.mV[curr_coef] < 0)
- return FALSE;
-
- LLVector3 ray;
-
- F32 norm_val = fabs(dir.mV[curr_coef]);
-
- if (norm_val < epsilon)
- norm_val = 1e-5f;
-
- ray.mV[curr_coef] = side_dir;
- ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
- ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
-
-
- const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
- const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
-
- switch (side)
- {
- case 0: // negative X
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 1: // positive X
- v_val = RESOLUTION - i_val;
- h_val = RESOLUTION - j_val;
- break;
- case 2: // negative Y
- v_val = RESOLUTION - i_val;
- h_val = j_val;
- break;
- case 3: // positive Y
- v_val = i_val;
- h_val = j_val;
- break;
- case 4: // negative Z
- v_val = RESOLUTION - j_val;
- h_val = RESOLUTION - i_val;
- break;
- case 5: // positive Z
- v_val = RESOLUTION - j_val;
- h_val = i_val;
- break;
- default:
- v_val = i_val;
- h_val = j_val;
- }
-
- outside = ((v_val < 0) || (v_val > RESOLUTION) ||
- (h_val < 0) || (h_val > RESOLUTION));
-
- return TRUE;
-}
-
-BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const
-{
- v_min = h_min = RESOLUTION;
- v_max = h_max = 0;
-
- BOOL fully_outside = TRUE;
- for (U8 vtx = 0; vtx < 4; ++vtx)
- {
- F32 v_val, h_val;
- BOOL outside;
- BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
- if (!outside)
- fully_outside = FALSE;
- if (consider)
- {
- if (v_val < v_min) v_min = v_val;
- if (v_val > v_max) v_max = v_val;
- if (h_val < h_min) h_min = h_val;
- if (h_val > h_max) h_max = h_val;
- }
- }
-
- v_min = llmax(0.0f, v_min);
- v_max = llmin(RESOLUTION - epsilon, v_max);
- h_min = llmax(0.0f, h_min);
- h_max = llmin(RESOLUTION - epsilon, h_max);
-
- return !fully_outside;
-}
-
-
-void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
-{
- LL_PROFILE_ZONE_SCOPED;
- F32 v_min, v_max, h_min, h_max;
- LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
- center.normVec();
-
- for (U8 side = 0; side < 6; ++side)
- {
- if (!project(v_min, v_max, h_min, h_max, side, dir))
- continue;
-
- U8 *td = mRawImages[side]->getData();
-
- U16 v_minu = (U16) v_min;
- U16 v_maxu = (U16) (ceil(v_max) + 0.5);
- U16 h_minu = (U16) h_min;
- U16 h_maxu = (U16) (ceil(h_max) + 0.5);
-
- for (U16 v = v_minu; v < v_maxu; ++v)
- for (U16 h = h_minu; h < h_maxu; ++h)
- //for (U16 v = 0; v < RESOLUTION; ++v)
- // for (U16 h = 0; h < RESOLUTION; ++h)
- {
- const LLVector3 ray = map(side, v, h);
- if (ray * center > 0.999)
- {
- const U32 offset = (RESOLUTION * v + h) * 4;
- for (U8 cc = 0; cc < 3; ++cc)
- td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
- }
- }
- mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
- }
-}
void LLCubeMap::destroyGL()
{
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index a01636d8d4..b9e081cea3 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -40,6 +40,17 @@ class LLCubeMap : public LLRefCount
public:
LLCubeMap(bool init_as_srgb);
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+
+ // initialize as an undefined cubemap at the given resolution
+ // used for render-to-cubemap operations
+ // avoids usage of LLImageRaw
+ void initReflectionMap(U32 resolution, U32 components = 3);
+
+ // init from environment map images
+ // Similar to init, but takes ownership of rawimages and makes this cubemap
+ // respect the resolution of rawimages
+ // Raw images must point to array of six square images that are all the same resolution
+ void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGL();
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
void initGLData();
@@ -54,18 +65,15 @@ public:
void disableTexture(void);
void setMatrix(S32 stage);
void restoreMatrix();
- void setReflection (void);
- void finishPaint();
+ U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
+
+ // generate mip maps for this Cube Map using GL
+ // NOTE: Cube Map MUST already be resident in VRAM
+ void generateMipMaps();
GLuint getGLName();
- LLVector3 map(U8 side, U16 v_val, U16 h_val) const;
- BOOL project(F32& v_val, F32& h_val, BOOL& outside,
- U8 side, const LLVector3& dir) const;
- BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
- U8 side, LLVector3 dir[4]) const;
- void paintIn(LLVector3 dir[4], const LLColor4U& col);
void destroyGL();
public:
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
new file mode 100644
index 0000000000..438d92cdba
--- /dev/null
+++ b/indra/llrender/llcubemaparray.cpp
@@ -0,0 +1,157 @@
+/**
+ * @file llcubemaparray.cpp
+ * @brief LLCubeMap class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llworkerthread.h"
+
+#include "llcubemaparray.h"
+
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "m3math.h"
+#include "m4math.h"
+
+#include "llrender.h"
+#include "llglslshader.h"
+
+#include "llglheaders.h"
+
+//#pragma optimize("", off)
+
+// MUST match order of OpenGL face-layers
+GLenum LLCubeMapArray::sTargets[6] =
+{
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
+ 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)
+{
+
+}
+
+LLCubeMapArray::~LLCubeMapArray()
+{
+}
+
+void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count)
+{
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ mImage = new LLImageGL(resolution, resolution, components, TRUE);
+ mImage->setTexName(texname);
+ mImage->setTarget(sTargets[0], LLTexUnit::TT_CUBE_MAP_ARRAY);
+
+ mImage->setUseMipMaps(TRUE);
+ mImage->setHasMipMaps(TRUE);
+
+ bind(0);
+
+ glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0, GL_RGB, resolution, resolution, count*6, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+
+ mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
+
+ mImage->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+
+ glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY_ARB);
+
+ unbind();
+}
+
+void LLCubeMapArray::bind(S32 stage)
+{
+ mTextureStage = stage;
+ gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_CUBE_MAP_ARRAY, getGLName(), TRUE);
+}
+
+void LLCubeMapArray::unbind()
+{
+ gGL.getTexUnit(mTextureStage)->unbind(LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTextureStage = -1;
+}
+
+GLuint LLCubeMapArray::getGLName()
+{
+ return mImage->getTexName();
+}
+
+void LLCubeMapArray::destroyGL()
+{
+ mImage = NULL;
+}
diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h
new file mode 100644
index 0000000000..cbc0692afb
--- /dev/null
+++ b/indra/llrender/llcubemaparray.h
@@ -0,0 +1,67 @@
+/**
+ * @file llcubemaparray.h
+ * @brief LLCubeMap class definition
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llgl.h"
+
+#include <vector>
+
+class LLVector3;
+
+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
+ // components - number of components per pixel
+ // count - number of cube maps in the array
+ void allocate(U32 res, U32 components, U32 count);
+ void bind(S32 stage);
+ void unbind();
+
+ GLuint getGLName();
+
+ void destroyGL();
+
+protected:
+ friend class LLTexUnit;
+ ~LLCubeMapArray();
+ LLPointer<LLImageGL> mImage;
+ S32 mTextureStage;
+};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 2b7ce155f6..8ebaf77eec 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -86,30 +86,31 @@ void APIENTRY gl_debug_callback(GLenum source,
const GLchar* message,
GLvoid* userParam)
{
- if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
- severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
- severity != GL_DEBUG_SEVERITY_LOW_ARB)
+ if (severity != GL_DEBUG_SEVERITY_HIGH_ARB // &&
+ //severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
+ //severity != GL_DEBUG_SEVERITY_LOW_ARB
+ )
{ //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
return;
}
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
- }
- LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
- LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
- LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
- LL_WARNS() << "Message: " << message << LL_ENDL;
- LL_WARNS() << "-----------------------" << LL_ENDL;
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_ERRS() << "Halting on GL Error" << LL_ENDL;
- }
+ if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+ {
+ LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
+ }
+ LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
+ LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
+ LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
+ LL_WARNS() << "Message: " << message << LL_ENDL;
+ LL_WARNS() << "-----------------------" << LL_ENDL;
+ if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+ {
+ LL_ERRS() << "Halting on GL Error" << LL_ENDL;
+ }
}
#endif
@@ -312,6 +313,15 @@ PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
+// GL_ARB_uniform_buffer_object
+PFNGLGETUNIFORMINDICESPROC glGetUniformIndices = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = NULL;
+
#if LL_WINDOWS
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
#endif
@@ -432,6 +442,7 @@ LLGLManager::LLGLManager() :
mHasTextureRectangle(FALSE),
mHasTextureMultisample(FALSE),
mHasTransformFeedback(FALSE),
+ mHasUniformBufferObject(FALSE),
mMaxSampleMaskWords(0),
mMaxColorTextureSamples(0),
mMaxDepthTextureSamples(0),
@@ -440,6 +451,7 @@ LLGLManager::LLGLManager() :
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
mHasCubeMap(FALSE),
+ mHasCubeMapArray(FALSE),
mHasDebugOutput(FALSE),
mIsAMD(FALSE),
@@ -1053,6 +1065,8 @@ void LLGLManager::initExtensions()
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
+ mHasUniformBufferObject = ExtensionExists("GL_ARB_uniform_buffer_object", gGLHExts.mSysExts);
+ mHasCubeMapArray = ExtensionExists("GL_ARB_texture_cube_map_array", gGLHExts.mSysExts);
#if !LL_DARWIN
mHasPointParameters = ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
#endif
@@ -1165,6 +1179,10 @@ void LLGLManager::initExtensions()
{
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL;
}
+ if (!mHasCubeMapArray)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_cube_map_array" << LL_ENDL;
+ }
// Disable certain things due to known bugs
if (mIsIntel && mHasMipMapGeneration)
@@ -1285,6 +1303,10 @@ void LLGLManager::initExtensions()
mGLMaxVertexRange = 0;
mGLMaxIndexRange = 0;
}
+
+ // same with glTexImage3D et al
+ glTexImage3D = (PFNGLTEXIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glTexImage3D");
+ glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)GLH_EXT_GET_PROC_ADDRESS("glCopyTexSubImage3D");
#endif // !LL_LINUX || LL_LINUX_NV_GL_HEADERS
#if LL_LINUX_NV_GL_HEADERS
// nvidia headers are critically different from mesa-esque
@@ -1318,6 +1340,17 @@ void LLGLManager::initExtensions()
glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
}
+ if (mHasUniformBufferObject)
+ {
+ glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformIndices");
+ glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformName");
+ glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)GLH_EXT_GET_PROC_ADDRESS("glGetUniformBlockIndex");
+ glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockiv");
+ glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformBlockName");
+ glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)GLH_EXT_GET_PROC_ADDRESS("glUniformBlockBinding");
+ }
+
// Assume shader capabilities
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 33cb0706c4..3c40f85654 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -105,6 +105,7 @@ public:
BOOL mHasTextureRectangle;
BOOL mHasTextureMultisample;
BOOL mHasTransformFeedback;
+ BOOL mHasUniformBufferObject;
S32 mMaxSampleMaskWords;
S32 mMaxColorTextureSamples;
S32 mMaxDepthTextureSamples;
@@ -114,6 +115,7 @@ public:
BOOL mHasAnisotropic;
BOOL mHasARBEnvCombine;
BOOL mHasCubeMap;
+ BOOL mHasCubeMapArray;
BOOL mHasDebugOutput;
BOOL mHassRGBTexture;
BOOL mHassRGBFramebuffer;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 3d93cc0762..154f1aa2bd 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -564,15 +564,26 @@ extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB;
+// GL_ARB_uniform_buffer_object
+extern PFNGLGETUNIFORMINDICESPROC glGetUniformIndices;
+extern PFNGLGETACTIVEUNIFORMSIVPROC glGetActiveUniformsiv;
+extern PFNGLGETACTIVEUNIFORMNAMEPROC glGetActiveUniformName;
+extern PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex;
+extern PFNGLGETACTIVEUNIFORMBLOCKIVPROC glGetActiveUniformBlockiv;
+extern PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glGetActiveUniformBlockName;
+extern PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding;
+
#elif LL_DARWIN
//----------------------------------------------------------------------------
// LL_DARWIN
+#define GL_GLEXT_LEGACY
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#define GL_EXT_separate_specular_color 1
-#include <OpenGL/glext.h>
+#define GL_GLEXT_PROTOTYPES
+#include "GL/glext.h"
#include "GL/glh_extensions.h"
@@ -821,14 +832,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#define glGetQueryiv glGetQueryivARB
#define glGetQueryObjectiv glGetQueryObjectivARB
#include <tracy/TracyOpenGL.hpp>
-
- #define LL_PROFILER_GPU_ZONEC(name,color) TracyGpuZoneC(name,color);
- #define LL_PROFILER_GPU_COLLECT TracyGpuCollect
- #define LL_PROFILER_GPU_CONTEXT TracyGpuContext
-#else
- #define LL_PROFILER_GPU_ZONEC(name,color) (void)name;(void)color;
- #define LL_PROFILER_GPU_COLLECT
- #define LL_PROFILER_GPU_CONTEXT
#endif
+
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 185c1450c8..67f82c9c5e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -452,7 +452,7 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
#ifdef GL_INTERLEAVED_ATTRIBS
if (varying_count > 0 && varyings)
{
- glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
+ glTransformFeedbackVaryings((GLuint64) mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
}
#endif
@@ -738,7 +738,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
{
//found it
mUniform[i] = location;
- mTexture[i] = mapUniformTextureChannel(location, type);
+ mTexture[i] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -752,7 +752,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
{
//found it
mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
- mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
+ mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type, size);
return;
}
}
@@ -775,16 +775,38 @@ void LLGLSLShader::removePermutation(std::string name)
mDefines[name].erase();
}
-GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
+GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
if ((type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) ||
- type == GL_SAMPLER_2D_MULTISAMPLE)
+ type == GL_SAMPLER_2D_MULTISAMPLE ||
+ type == GL_SAMPLER_CUBE_MAP_ARRAY_ARB)
{ //this here is a texture
- glUniform1iARB(location, mActiveTextureChannels);
- LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
- return mActiveTextureChannels++;
+ GLint ret = mActiveTextureChannels;
+ if (size == 1)
+ {
+ glUniform1iARB(location, mActiveTextureChannels);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
+ mActiveTextureChannels++;
+ }
+ else
+ {
+ //is array of textures, make sequential after this texture
+ GLint channel[32]; // <=== only support up to 32 texture channels
+ llassert(size <= 32);
+ size = llmin(size, 32);
+ for (int i = 0; i < size; ++i)
+ {
+ channel[i] = mActiveTextureChannels++;
+ }
+ glUniform1ivARB(location, size, channel);
+ LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " <<
+ (mActiveTextureChannels-size) << " through " << (mActiveTextureChannels-1) << LL_ENDL;
+ }
+
+ llassert(mActiveTextureChannels <= 32); // too many textures (probably)
+ return ret;
}
return -1;
}
@@ -832,6 +854,9 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
As example where this situation appear see: "Deferred Material Shader 28/29/30/31"
And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437
+
+ --- davep TODO -- pretty sure the entire block here is superstitious and that the uniform index has nothing to do with the texture channel
+ texture channel should follow the uniform VALUE
*/
@@ -840,6 +865,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
+ S32 reflectionMap = glGetUniformLocationARB(mProgramObject, "reflectionMap");
std::set<S32> skip_index;
@@ -882,6 +908,12 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
continue;
}
+ if (-1 == reflectionMap && std::string(name) == "reflectionMap")
+ {
+ reflectionMap = i;
+ continue;
+ }
+
if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
{
altDiffuseMap = i;
@@ -892,8 +924,9 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;
bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap;
+ bool refLessDiff = reflectionMap < diffuseMap && -1 != reflectionMap;
- if (specularDiff || bumpLessDiff || envLessDiff)
+ if (specularDiff || bumpLessDiff || envLessDiff || refLessDiff)
{
mapUniform(diffuseMap, uniforms);
skip_index.insert(diffuseMap);
@@ -912,6 +945,11 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
mapUniform(environmentMap, uniforms);
skip_index.insert(environmentMap);
}
+
+ if (-1 != reflectionMap) {
+ mapUniform(reflectionMap, uniforms);
+ skip_index.insert(reflectionMap);
+ }
}
}
@@ -1252,6 +1290,30 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
}
}
+void LLGLSLShader::uniform4iv(U32 index, U32 count, const GLint* v)
+{
+ if (mProgramObject)
+ {
+ if (mUniform.size() <= index)
+ {
+ LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ const auto& iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ glUniform1ivARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+
void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
{
if (mProgramObject)
@@ -1489,6 +1551,40 @@ void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
}
}
+void LLGLSLShader::uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], 0, 0, 0);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform1ivARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v[0], v[1], v[2], v[3]);
+ const auto& iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
+ glUniform4ivARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
{
GLint location = getUniformLocation(uniform);
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 85e83dbcb9..68e1a8954d 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -52,12 +52,13 @@ public:
bool hasShadows;
bool hasAmbientOcclusion;
bool hasSrgb;
- bool encodesNormal;
+ bool encodesNormal; // include: shaders\class1\environment\encodeNormF.glsl
bool isDeferred;
bool hasIndirect;
S32 mIndexedTextureChannels;
bool disableTextureIndex;
bool hasAlphaMask;
+ bool hasReflectionProbes = false;
bool attachNothing;
// char numLights;
@@ -178,6 +179,7 @@ public:
void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void uniform1iv(U32 index, U32 count, const GLint* i);
+ void uniform4iv(U32 index, U32 count, const GLint* i);
void uniform1fv(U32 index, U32 count, const GLfloat* v);
void uniform2fv(U32 index, U32 count, const GLfloat* v);
void uniform3fv(U32 index, U32 count, const GLfloat* v);
@@ -188,6 +190,8 @@ public:
void uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
void uniform1i(const LLStaticHashedString& uniform, GLint i);
+ void uniform1iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
+ void uniform4iv(const LLStaticHashedString& uniform, U32 count, const GLint* v);
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
@@ -207,7 +211,7 @@ public:
GLint getUniformLocation(U32 index);
GLint getAttribLocation(U32 attrib);
- GLint mapUniformTextureChannel(GLint location, GLenum type);
+ GLint mapUniformTextureChannel(GLint location, GLenum type, GLint size);
void clearPermutations();
void addPermutation(std::string name, std::string value);
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9bd3a0a6b0..89dd68da76 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -812,6 +812,7 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
if (LLRender::sGLCoreProfile)
{
+ LL_PROFILE_GPU_ZONE("generate mip map");
glGenerateMipmap(mTarget);
}
stop_glerror();
@@ -1519,6 +1520,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// Call with void data, vmem is allocated but unitialized
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ LL_PROFILE_GPU_ZONE("createGLTexture");
checkActiveThread();
bool main_thread = on_main_thread();
@@ -1688,26 +1690,38 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
LL_PROFILE_ZONE_NAMED("cglt - sync");
if (gGLManager.mHasSync)
{
- // post a sync to the main thread (will execute before tex name swap lambda below)
- // glFlush calls here are partly superstitious and partly backed by observation
- // on AMD hardware
- glFlush();
- auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- glFlush();
- LL::WorkQueue::postMaybe(
- mMainQueue,
- [=]()
- {
- LL_PROFILE_ZONE_NAMED("cglt - wait sync");
- {
- LL_PROFILE_ZONE_NAMED("glWaitSync");
- glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
- }
+ if (gGLManager.mIsNVIDIA)
+ {
+ // wait for texture upload to finish before notifying main thread
+ // upload is complete
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ glDeleteSync(sync);
+ }
+ else
+ {
+ // post a sync to the main thread (will execute before tex name swap lambda below)
+ // glFlush calls here are partly superstitious and partly backed by observation
+ // on AMD hardware
+ glFlush();
+ auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ LL::WorkQueue::postMaybe(
+ mMainQueue,
+ [=]()
{
- LL_PROFILE_ZONE_NAMED("glDeleteSync");
- glDeleteSync(sync);
- }
- });
+ LL_PROFILE_ZONE_NAMED("cglt - wait sync");
+ {
+ LL_PROFILE_ZONE_NAMED("glWaitSync");
+ glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ }
+ {
+ LL_PROFILE_ZONE_NAMED("glDeleteSync");
+ glDeleteSync(sync);
+ }
+ });
+ }
}
else
{
@@ -1724,8 +1738,11 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
syncTexName(new_tex_name);
unref();
});
+
+ LL_PROFILER_GPU_COLLECT;
}
+
void LLImageGL::syncTexName(LLGLuint texname)
{
if (texname != 0)
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 4d5b60d6bc..b419c9fab5 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -161,7 +161,7 @@ public:
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
-
+ void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index a03a27cf94..3adb47f493 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -71,6 +71,7 @@ static const GLenum sGLTextureType[] =
GL_TEXTURE_2D,
GL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_CUBE_MAP_ARRAY_ARB,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_3D
};
@@ -888,6 +889,9 @@ void LLRender::init()
glCullFace(GL_BACK);
+ // necessary for reflection maps
+ glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+
if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
{ //bind a dummy vertex array object so we're core profile compliant
#ifdef GL_ARB_vertex_array_object
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index e2489876e4..095ed400f4 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -52,7 +52,7 @@ class LLTexture ;
#define LL_MATRIX_STACK_DEPTH 32
-class LLTexUnit
+class LLTexUnit
{
friend class LLRender;
public:
@@ -63,6 +63,7 @@ public:
TT_TEXTURE = 0, // Standard 2D Texture
TT_RECT_TEXTURE, // Non power of 2 texture
TT_CUBE_MAP, // 6-sided cube map texture
+ TT_CUBE_MAP_ARRAY, // Array of cube maps
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
TT_NONE, // No texture type is currently enabled
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 0408010513..fa46e0f7d0 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -119,6 +119,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy)
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
@@ -219,6 +220,7 @@ void LLRenderTarget::releaseColorAttachment()
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (color_fmt == 0)
{
return true;
@@ -315,6 +317,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
bool LLRenderTarget::allocateDepth()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mStencil)
{
//use render buffers where stencil buffers are in play
@@ -395,6 +398,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
void LLRenderTarget::release()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
if (mDepth)
{
if (mStencil)
@@ -469,6 +473,8 @@ void LLRenderTarget::release()
void LLRenderTarget::bindTarget()
{
+ llassert(mFBO);
+
if (mFBO)
{
stop_glerror();
@@ -484,13 +490,11 @@ void LLRenderTarget::bindTarget()
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x4000FF )
glDrawBuffersARB(mTex.size(), drawbuffers);
}
if (mTex.empty())
{ //no color buffer to draw to
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffer", 0x0000FF )
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
@@ -511,6 +515,8 @@ void LLRenderTarget::bindTarget()
void LLRenderTarget::clear(U32 mask_in)
{
+ LL_PROFILE_GPU_ZONE("clear");
+ llassert(mFBO);
U32 mask = GL_COLOR_BUFFER_BIT;
if (mUseDepth)
{
@@ -576,6 +582,7 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
void LLRenderTarget::flush(bool fetch_depth)
{
gGL.flush();
+ llassert(mFBO);
if (!mFBO)
{
gGL.getTexUnit(0)->bind(this);
@@ -675,6 +682,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
}
{
+ LL_PROFILE_GPU_ZONE("copyContentsToFramebuffer");
GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE;
LLGLDepthTest depth(write_depth, write_depth);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index c100c182dd..686eaddc24 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"))
@@ -712,8 +720,15 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
{
if (major_version >= 4)
{
- //set version to 400
- shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ //set version to 400 or 420
+ if (minor_version >= 20)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 420\n");
+ }
+ else
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 400\n");
+ }
}
else if (major_version == 3)
{
@@ -772,7 +787,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
extra_code_text[extra_code_count++] = strdup("#define shadow2DRect(a,b) vec2(texture(a,b))\n");
}
}
-
+
+ // Use alpha float to store bit flags
+ // See: C++: addDeferredAttachment(), shader: frag_data[2]
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
+ extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
+ extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
+
if (defines)
{
for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
@@ -1148,13 +1170,19 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
mReservedUniforms.push_back("color");
-
+ mReservedUniforms.push_back("emissiveColor");
+ mReservedUniforms.push_back("metallicFactor");
+ mReservedUniforms.push_back("roughnessFactor");
+
mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("emissiveMap");
mReservedUniforms.push_back("bumpMap");
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");
@@ -1201,6 +1229,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("minimum_alpha");
mReservedUniforms.push_back("emissive_brightness");
+ // Deferred
mReservedUniforms.push_back("shadow_matrix");
mReservedUniforms.push_back("env_mat");
mReservedUniforms.push_back("shadow_clip");
@@ -1225,8 +1254,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("depth_cutoff");
mReservedUniforms.push_back("norm_cutoff");
mReservedUniforms.push_back("shadow_target_width");
+ mReservedUniforms.push_back("view_dir"); // DEFERRED_VIEW_DIR
- llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_VIEW_DIR+1);
mReservedUniforms.push_back("tc_scale");
mReservedUniforms.push_back("rcp_screen_res");
@@ -1256,6 +1286,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("positionMap");
mReservedUniforms.push_back("diffuseRect");
mReservedUniforms.push_back("specularRect");
+ mReservedUniforms.push_back("emissiveRect");
mReservedUniforms.push_back("noiseMap");
mReservedUniforms.push_back("lightFunc");
mReservedUniforms.push_back("lightMap");
@@ -1326,6 +1357,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("halo_map");
mReservedUniforms.push_back("moon_brightness");
mReservedUniforms.push_back("cloud_variance");
+ mReservedUniforms.push_back("reflection_probe_ambiance");
mReservedUniforms.push_back("sh_input_r");
mReservedUniforms.push_back("sh_input_g");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 67c0d6ab10..9e8f848491 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -74,12 +74,18 @@ public:
PROJECTOR_LOD, // "proj_lod"
PROJECTOR_AMBIENT_LOD, // "proj_ambient_lod"
DIFFUSE_COLOR, // "color"
+ EMISSIVE_COLOR, // "emissiveColor"
+ METALLIC_FACTOR, // "metallicFactor"
+ ROUGHNESS_FACTOR, // "roughnessFactor"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
+ EMISSIVE_MAP, // "emissiveMap"
BUMP_MAP, // "bumpMap"
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"
@@ -142,6 +148,7 @@ public:
DEFERRED_DEPTH_CUTOFF, // "depth_cutoff"
DEFERRED_NORM_CUTOFF, // "norm_cutoff"
DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width"
+ DEFERRED_VIEW_DIR, // "view_dir"
FXAA_TC_SCALE, // "tc_scale"
FXAA_RCP_SCREEN_RES, // "rcp_screen_res"
@@ -168,6 +175,7 @@ public:
DEFERRED_POSITION, // "positionMap"
DEFERRED_DIFFUSE, // "diffuseRect"
DEFERRED_SPECULAR, // "specularRect"
+ DEFERRED_EMISSIVE, // "emissiveRect"
DEFERRED_NOISE, // "noiseMap"
DEFERRED_LIGHTFUNC, // "lightFunc"
DEFERRED_LIGHT, // "lightMap"
@@ -242,6 +250,7 @@ public:
CLOUD_VARIANCE, // "cloud_variance"
+ REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b"
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 6338cab96a..b1b69f1508 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -624,7 +624,6 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
stop_glerror();
LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawRangeElements", 0xFFFF00 )
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
LLGLSLShader::stopProfile(count, mode);
@@ -642,7 +641,6 @@ void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32
U16* idx = ((U16*)getIndicesPointer()) + indices_offset;
- LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
idx);
}
@@ -688,8 +686,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
stop_glerror();
LLGLSLShader::startProfile();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0xA0FFA0 )
- glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
+ glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT,
((U16*) getIndicesPointer()) + indices_offset);
LLGLSLShader::stopProfile(count, mode);
stop_glerror();
@@ -736,7 +733,6 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
LLGLSLShader::startProfile();
{
- LL_PROFILER_GPU_ZONEC("gl.DrawArrays", 0xFF4040)
glDrawArrays(sGLMode[mode], first, count);
}
LLGLSLShader::stopProfile(count, mode);
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 30dbd7248f..86b23c8c93 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -76,7 +76,8 @@ enum EDragAndDropType
DAD_WIDGET = 16,
DAD_PERSON = 17,
DAD_SETTINGS = 18,
- DAD_COUNT = 19, // number of types in this enum
+ DAD_MATERIAL = 19,
+ DAD_COUNT = 20, // number of types in this enum
};
// Reasons for drags to be denied.
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 4c3aeb4695..1f23040260 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -1623,8 +1623,6 @@ const S32 max_format = (S32)num_formats - 1;
return FALSE;
}
- LL_PROFILER_GPU_CONTEXT
-
if (!gGLManager.initGL())
{
OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK);
@@ -1656,6 +1654,8 @@ const S32 max_format = (S32)num_formats - 1;
swapBuffers();
}
+ LL_PROFILER_GPU_CONTEXT;
+
return TRUE;
}
@@ -1809,6 +1809,7 @@ void* LLWindowWin32::createSharedContext()
void LLWindowWin32::makeContextCurrent(void* contextPtr)
{
wglMakeCurrent(mhDC, (HGLRC) contextPtr);
+ LL_PROFILER_GPU_CONTEXT;
}
void LLWindowWin32::destroySharedContext(void* contextPtr)
@@ -3586,10 +3587,13 @@ void LLWindowWin32::swapBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32;
ASSERT_MAIN_THREAD();
- glFlush(); //superstitious flush for maybe frame stall removal?
+ {
+ LL_PROFILE_GPU_ZONE("flush");
+ glFlush(); //superstitious flush for maybe frame stall removal?
+ }
SwapBuffers(mhDC);
- LL_PROFILER_GPU_COLLECT
+ LL_PROFILER_GPU_COLLECT;
}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c577d062f9..b67bc91277 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(ZLIBNG)
include(URIPARSER)
@@ -187,6 +188,7 @@ set(viewer_SOURCE_FILES
lldrawpoolbump.cpp
lldrawpoolground.cpp
lldrawpoolmaterials.cpp
+ lldrawpoolpbropaque.cpp
lldrawpoolsimple.cpp
lldrawpoolsky.cpp
lldrawpoolterrain.cpp
@@ -342,6 +344,7 @@ set(viewer_SOURCE_FILES
llgesturemgr.cpp
llgiveinventory.cpp
llglsandbox.cpp
+ llgltfmateriallist.cpp
llgroupactions.cpp
llgroupiconctrl.cpp
llgrouplist.cpp
@@ -403,6 +406,7 @@ set(viewer_SOURCE_FILES
llmaniptranslate.cpp
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
+ llmaterialeditor.cpp
llmaterialmgr.cpp
llmediactrl.cpp
llmediadataclient.cpp
@@ -545,6 +549,8 @@ set(viewer_SOURCE_FILES
llproductinforequest.cpp
llprogressview.cpp
llrecentpeople.cpp
+ llreflectionmap.cpp
+ llreflectionmapmanager.cpp
llregioninfomodel.cpp
llregionposition.cpp
llremoteparcelrequest.cpp
@@ -822,6 +828,7 @@ set(viewer_HEADER_FILES
lldrawpoolavatar.h
lldrawpoolbump.h
lldrawpoolmaterials.h
+ lldrawpoolpbropaque.h
lldrawpoolground.h
lldrawpoolsimple.h
lldrawpoolsky.h
@@ -980,6 +987,7 @@ set(viewer_HEADER_FILES
llgesturelistener.h
llgesturemgr.h
llgiveinventory.h
+ llgltfmateriallist.h
llgroupactions.h
llgroupiconctrl.h
llgrouplist.h
@@ -1040,6 +1048,7 @@ set(viewer_HEADER_FILES
llmaniptranslate.h
llmarketplacefunctions.h
llmarketplacenotifications.h
+ llmaterialeditor.h
llmaterialmgr.h
llmediactrl.h
llmediadataclient.h
@@ -1169,6 +1178,8 @@ set(viewer_HEADER_FILES
llproductinforequest.h
llprogressview.h
llrecentpeople.h
+ llreflectionmap.h
+ llreflectionmapmanager.h
llregioninfomodel.h
llregionposition.h
llremoteparcelrequest.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 16d8cd9f06..8a86faa18d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1252,6 +1252,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>BulkChangeIncludeMaterials</key>
+ <map>
+ <key>Comment</key>
+ <string>Bulk permission changes affect materials</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>BulkChangeEveryoneCopy</key>
<map>
<key>Comment</key>
@@ -8795,13 +8806,13 @@
<key>RenderAvatarCloth</key>
<map>
<key>Comment</key>
- <string>Controls if avatars use wavy cloth</string>
+ <string>DEPRECATED - only false supported - Controls if avatars use wavy cloth</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>RenderComplexityColorMin</key>
<map>
@@ -9610,16 +9621,28 @@
<real>368.0</real>
</map>
+ <key>RenderPBR</key>
+ <map>
+ <key>Comment</key>
+ <string>Use PBR rendering pipeline (Physically Based Rendering).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+
<key>RenderDeferred</key>
<map>
<key>Comment</key>
- <string>Use deferred rendering pipeline (Advanced Lighting Model).</string>
+ <string>DEPRECATED (only true supported) - Use deferred rendering pipeline (Advanced Lighting Model).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>RenderDeferredSun</key>
@@ -9834,7 +9857,7 @@
<key>RenderFogRatio</key>
<map>
<key>Comment</key>
- <string>Distance from camera where fog reaches maximum density (fraction or multiple of far clip distance)</string>
+ <string>DEPRECATED - Distance from camera where fog reaches maximum density (fraction or multiple of far clip distance)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -9845,7 +9868,7 @@
<key>RenderGamma</key>
<map>
<key>Comment</key>
- <string>Sets gamma exponent for renderer</string>
+ <string>DEPRECATED - Sets gamma exponent for renderer</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10238,7 +10261,7 @@
<key>RenderObjectBump</key>
<map>
<key>Comment</key>
- <string>Show bumpmapping on primitives</string>
+ <string>DEPRECATED (only TRUE supported) Show bumpmapping on primitives</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -10279,8 +10302,53 @@
<key>Value</key>
<integer>2</integer>
</map>
+ <key>RenderReflectionProbeDetail</key>
+ <map>
+ <key>Comment</key>
+ <string>Detail of reflections.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
- <key>RenderReflectionRes</key>
+ <key>RenderReflectionProbeDrawDistance</key>
+ <map>
+ <key>Comment</key>
+ <string>Camera far clip to use when updating reflection probes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>64</real>
+ </map>
+ <key>RenderReflectionProbeAmbiance</key>
+ <map>
+ <key>Comment</key>
+ <string>Amount reflection probes contribute to ambient light.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0</real>
+ </map>
+ <key>RenderReflectionProbeTextureHackID</key>
+ <map>
+ <key>Comment</key>
+ <string>HACK -- Any object with a diffuse texture with this ID will be treated as a user override reflection probe. (default is "Violet Info Hub" photo from Library)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>6b186931-05da-eafa-a3ed-a012a33bbfb6</string>
+ </map>
+
+ <key>RenderReflectionRes</key>
<map>
<key>Comment</key>
<string>Reflection map resolution.</string>
@@ -11156,6 +11224,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>SelectInvisibleObjects</key>
+ <map>
+ <key>Comment</key>
+ <string>Select invisible objects</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>SelectOwnedOnly</key>
<map>
<key>Comment</key>
@@ -14865,7 +14944,7 @@
<key>WindLightUseAtmosShaders</key>
<map>
<key>Comment</key>
- <string>Whether to enable or disable WindLight atmospheric shaders.</string>
+ <string>DEPRECATED (only true supported) - Whether to enable or disable WindLight atmospheric shaders.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
index 23adbded5e..73c125bbdc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
@@ -29,8 +29,6 @@ uniform sampler2DRect depthMap;
uniform float ssao_radius;
uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -83,14 +81,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
{
float ret = 1.0;
vec3 pos_world = pos.xyz;
- vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
+
float angle_hidden = 0.0;
float points = 0;
- float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
-
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+ vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
for (int i = 0; i < 8; i++)
{
vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
@@ -105,14 +103,14 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
//(k should vary inversely with # of samples, but this is taken care of later)
float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
- angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
+ angle_hidden = angle_hidden + funky_val * min(1.0/dist2, 1.0);
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
points = points + diffz_val;
}
-
- angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
+
+ angle_hidden = min(angle_hidden/points, 1.0);
float points_val = (points > 0.0) ? 1.0 : 0.0;
ret = (1.0 - (points_val * angle_hidden));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 60d83cc623..22b3bd1463 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -52,6 +52,6 @@ void main()
frag_data[0] = vec4(diff.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 596d0274af..fa3634f3b6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -69,36 +69,47 @@ void main()
tc_mod *= 2.0;
tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
- for (int i = 1; i < 4; i++)
+ // TODO: move this to kern instead of building kernel per pixel
+ vec3 k[7];
+ k[0] = kern[0];
+ k[2] = kern[1];
+ k[4] = kern[2];
+ k[6] = kern[3];
+
+ k[1] = (k[0]+k[2])*0.5f;
+ k[3] = (k[2]+k[4])*0.5f;
+ k[5] = (k[4]+k[6])*0.5f;
+
+ for (int i = 1; i < 7; i++)
{
- vec2 samptc = tc + kern[i].z*dlt;
+ vec2 samptc = tc + k[i].z*dlt*2.0;
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture2DRect(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
- for (int i = 1; i < 4; i++)
+ for (int i = 1; i < 7; i++)
{
- vec2 samptc = tc - kern[i].z*dlt;
+ vec2 samptc = tc - k[i].z*dlt*2.0;
vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
+ col += texture2DRect(lightMap, samptc)*k[i].xyxx;
+ defined_weight += k[i].xy;
}
}
col /= defined_weight.xyxx;
- col.y *= col.y;
+ //col.y *= max(col.y, 0.75);
frag_color = col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index b5677a07ee..749ec3a6ac 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -64,5 +64,5 @@ void main()
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(tnorm);
- frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
index ae1ac5de7f..348e0f5228 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -124,7 +124,7 @@ void main()
/// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, alpha1);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
- frag_data[2] = vec4(0,0,0,1);
+ frag_data[2] = vec4(0,0,0,GBUFFER_FLAG_SKIP_ATMOS);
gl_FragDepth = 0.99995f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index e27bbce094..ad3a93128d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -25,10 +25,75 @@
uniform sampler2DRect normalMap;
uniform sampler2DRect depthMap;
+uniform sampler2D projectionMap; // rgba
+
+// projected lighted params
+uniform mat4 proj_mat; //screen space to light space projector
+uniform vec3 proj_n; // projector normal
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform float proj_focus; // distance from plane to begin blurring
+uniform float proj_lod ; // (number of mips in proj map)
+uniform float proj_range; // range between near clip and far clip plane of projection
+
+// light params
+uniform vec3 color; // light_color
+uniform float size; // light_size
uniform mat4 inv_proj;
uniform vec2 screen_res;
+const float M_PI = 3.14159265;
+
+vec3 srgb_to_linear(vec3 cs);
+
+// In:
+// lv unnormalized surface to light vector
+// n normal of the surface
+// pos unnormalized camera to surface vector
+// Out:
+// l normalized surace to light vector
+// nl diffuse angle
+// nh specular angle
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v,
+ out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist)
+{
+ l = normalize(lv);
+ h = normalize(l + v);
+ nh = clamp(dot(n, h), 0.0, 1.0);
+ nl = clamp(dot(n, l), 0.0, 1.0);
+ nv = clamp(dot(n, v), 0.0, 1.0);
+ vh = clamp(dot(v, h), 0.0, 1.0);
+
+ lightDist = length(lv);
+}
+
+// In:
+// light_center
+// pos
+// Out:
+// dist
+// l_dist
+// lv
+// proj_tc Projector Textue Coordinates
+bool clipProjectedLightVars(vec3 light_center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc )
+{
+ lv = light_center - pos.xyz;
+ dist = length(lv);
+ bool clipped = (dist >= size);
+ if ( !clipped )
+ {
+ dist /= size;
+
+ l_dist = -dot(lv, proj_n);
+ vec4 projected_point = (proj_mat * vec4(pos.xyz, 1.0));
+ clipped = (projected_point.z < 0.0);
+ projected_point.xyz /= projected_point.w;
+ proj_tc = projected_point;
+ }
+
+ return clipped;
+}
+
vec2 getScreenCoordinate(vec2 screenpos)
{
vec2 sc = screenpos.xy * 2.0;
@@ -39,6 +104,8 @@ vec2 getScreenCoordinate(vec2 screenpos)
return sc - vec2(1.0, 1.0);
}
+// See: https://aras-p.info/texts/CompactNormalStorage.html
+// Method #4: Spheremap Transform, Lambert Azimuthal Equal-Area projection
vec3 getNorm(vec2 screenpos)
{
vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
@@ -51,12 +118,108 @@ vec3 getNorm(vec2 screenpos)
return n;
}
+vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags)
+{
+ vec2 enc = packedNormalEnvIntensityFlags.xy;
+ vec2 fenc = enc*4-2;
+ float f = dot(fenc,fenc);
+ float g = sqrt(1-f/4);
+ vec3 n;
+ n.xy = fenc*g;
+ n.z = 1-f/2;
+ return normalize(n); // TODO: Is this normalize redundant?
+}
+
+// return packedNormalEnvIntensityFlags since GBUFFER_FLAG_HAS_PBR needs .w
+// See: C++: addDeferredAttachments(), GLSL: softenLightF
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity)
+{
+ vec4 packedNormalEnvIntensityFlags = texture2DRect(normalMap, screenpos.xy);
+ n = getNormalFromPacked( packedNormalEnvIntensityFlags );
+ envIntensity = packedNormalEnvIntensityFlags.z;
+ return packedNormalEnvIntensityFlags;
+}
+
float getDepth(vec2 pos_screen)
{
float depth = texture2DRect(depthMap, pos_screen).r;
return depth;
}
+vec4 getTexture2DLodDiffuse(vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+ ret.rgb = srgb_to_linear(ret.rgb);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+ float det = min(lod/(proj_lod*0.5), 1.0);
+ float d = min(dist.x, dist.y);
+ float edge = 0.25*det;
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+// Returns projected light in Linear
+// Uses:
+// color
+// NOTE: projected.a will be pre-multiplied with projected.rgb
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv)
+{
+ float diff = clamp((light_distance - proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 plcol = getTexture2DLodDiffuse(projected_uv.xy, lod);
+
+ return color.rgb * plcol.rgb * plcol.a;
+}
+
+vec4 texture2DLodSpecular(vec2 tc, float lod)
+{
+ vec4 ret = texture2DLod(projectionMap, tc, lod);
+ ret.rgb = srgb_to_linear(ret.rgb);
+
+ vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+ float det = min(lod/(proj_lod*0.5), 1.0);
+ float d = min(dist.x, dist.y);
+ d *= min(1, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats
+ float edge = 0.25*det;
+ ret *= clamp(d/edge, 0.0, 1.0);
+
+ return ret;
+}
+
+// See: clipProjectedLightVars()
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n )
+{
+ vec3 slit = vec3(0);
+ vec3 ref = reflect(normalize(pos), n);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float l_dist = length(pdelta);
+ float ds = dot(ref, proj_n);
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ if (stc.z > 0.0)
+ {
+ stc /= stc.w;
+ slit = getProjectedLightDiffuseColor( l_dist, stc.xy ); // NOTE: Using diffuse due to texture2DLodSpecular() has extra: d *= min(1, d * (proj_lod - lod));
+ }
+ }
+ return slit; // specular light
+}
+
+vec3 getProjectedLightSpecularColor(float light_distance, vec2 projected_uv)
+{
+ float diff = clamp((light_distance - proj_focus)/proj_range, 0.0, 1.0);
+ float lod = diff * proj_lod;
+ vec4 plcol = getTexture2DLodDiffuse(projected_uv.xy, lod); // NOTE: Using diffuse due to texture2DLodSpecular() has extra: d *= min(1, d * (proj_lod - lod));
+
+ return color.rgb * plcol.rgb * plcol.a;
+}
+
vec4 getPosition(vec2 pos_screen)
{
float depth = getDepth(pos_screen);
@@ -77,3 +240,132 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth)
pos.w = 1.0;
return pos;
}
+
+vec2 getScreenXY(vec4 clip)
+{
+ vec4 ndc = clip;
+ ndc.xyz /= clip.w;
+ vec2 screen = vec2( ndc.xy * 0.5 );
+ screen += 0.5;
+ screen *= screen_res;
+ return screen;
+}
+
+// PBR Utils
+
+vec3 fresnelSchlick( vec3 reflect0, vec3 reflect90, float vh)
+{
+ return reflect0 + (reflect90 - reflect0) * pow(clamp(1.0 - vh, 0.0, 1.0), 5.0);
+}
+
+// Approximate Environment BRDF
+vec2 getGGXApprox( vec2 uv )
+{
+ // Reference: Physically Based Shading on Mobile
+ // https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
+ // EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
+ float nv = uv.x;
+ float roughness = uv.y;
+
+ const vec4 c0 = vec4( -1, -0.0275, -0.572, 0.022 );
+ const vec4 c1 = vec4( 1, 0.0425, 1.04 , -0.04 );
+ vec4 r = roughness * c0 + c1;
+ float a004 = min( r.x * r.x, exp2( -9.28 * nv ) ) * r.x + r.y;
+ vec2 ScaleBias = vec2( -1.04, 1.04 ) * a004 + r.zw;
+ return ScaleBias;
+}
+
+#define PBR_USE_GGX_APPROX 1
+vec2 getGGX( vec2 brdfPoint )
+{
+#if PBR_USE_GGX_APPROX
+ return getGGXApprox( brdfPoint);
+#else
+ return texture2D(GGXLUT, brdfPoint).rg; // TODO: use GGXLUT
+#endif
+}
+
+
+// Reference: float getRangeAttenuation(float range, float distance)
+float getLightAttenuationPointSpot(float range, float distance)
+{
+#if 1
+ return distance;
+#else
+ float range2 = pow(range, 2.0);
+
+ // support negative range as unlimited
+ if (range <= 0.0)
+ {
+ return 1.0 / range2;
+ }
+
+ return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / range2;
+#endif
+}
+
+vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance)
+{
+ float rangeAttenuation = getLightAttenuationPointSpot(lightRange, lightDistance);
+ return rangeAttenuation * lightColor;
+}
+
+float getLightAttenuationSpot(vec3 spotDirection)
+{
+ return 1.0;
+}
+
+vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v)
+{
+ float spotAttenuation = getLightAttenuationSpot(-v);
+ return spotAttenuation * getLightIntensityPoint( lightColor, lightRange, lightDistance );
+}
+
+// NOTE: This is different from the GGX texture
+float D_GGX( float nh, float alphaRough )
+{
+ float rough2 = alphaRough * alphaRough;
+ float f = (nh * nh) * (rough2 - 1.0) + 1.0;
+ return rough2 / (M_PI * f * f);
+}
+
+// NOTE: This is different from the GGX texture
+float V_GGX( float nl, float nv, float alphaRough )
+{
+ float rough2 = alphaRough * alphaRough;
+ float ggxv = nl * sqrt(nv * nv * (1.0 - rough2) + rough2);
+ float ggxl = nv * sqrt(nl * nl * (1.0 - rough2) + rough2);
+ float ggx = ggxv + ggxl;
+ if (ggx > 0.0)
+ {
+ return 0.5 / ggx;
+ }
+ return 0.0;
+}
+
+void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight )
+{
+ float metal = packedORM.b;
+ c_diff = mix(diffuse.rgb, vec3(0), metal);
+ float IOR = 1.5; // default Index Of Refraction 1.5 (dielectrics)
+ reflect0 = vec3(0.04); // -> incidence reflectance 0.04
+ reflect0 = mix( reflect0, diffuse.rgb, metal); // reflect at 0 degrees
+ reflect90 = vec3(1); // reflect at 90 degrees
+ specWeight = 1.0;
+
+ float perceptualRough = packedORM.g;
+ alphaRough = perceptualRough * perceptualRough;
+}
+
+vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh )
+{
+ return (1.0 - specWeight * fresnelSchlick( reflect0, reflect90, vh)) * (c_diff / M_PI);
+}
+
+vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRough, float specWeight, float vh, float nl, float nv, float nh )
+{
+ vec3 fresnel = fresnelSchlick( reflect0, reflect90, vh );
+ float vis = V_GGX( nl, nv, alphaRough );
+ float d = D_GGX( nh, alphaRough );
+ return specWeight * fresnel * vis * d;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
index b328ee9483..3bf148502c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
@@ -53,6 +53,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
index fc5c86b4d6..e15239b59d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
@@ -52,5 +52,5 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
index 1bb8eb8bd0..b0ff233414 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
@@ -52,6 +52,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 8319e61242..b2d2e2fa71 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -46,6 +46,6 @@ void main()
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index ccd1df84f9..b4bc114dd5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -48,5 +48,5 @@ void main()
frag_data[0] = vec4(col, 0.0);
frag_data[1] = vec4(spec, vertex_color.a); // spec
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index 9fcee04c32..f693323d45 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -38,7 +38,7 @@ uniform sampler2D diffuseMap;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
-VARYING vec4 vary_position;
+VARYING vec3 vary_position;
uniform samplerCube environmentMap;
@@ -74,7 +74,7 @@ void main()
vec3 amblit;
vec3 additive;
vec3 atten;
- vec3 pos = vary_position.xyz/vary_position.w;
+ vec3 pos = vary_position.xyz;
calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
index 3bd6b693fa..5264b3b716 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
@@ -45,7 +45,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();
@@ -62,17 +62,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_position = pos.xyz;
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1 * vec4(ref,1.0)).xyz;
+
+#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/highlightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
index 90566393d2..75f914cb02 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/highlightF.glsl
@@ -38,5 +38,5 @@ void main()
{
frag_data[0] = color*texture2D(diffuseMap, vary_texcoord0.xy);
frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index a58cc3d12d..67f4c59c3f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -56,5 +56,5 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = spec;
- frag_data[2] = norm;
+ frag_data[2] = norm; // TODO: Should .w be set?
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 02d83925ea..6f087632a5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -277,10 +277,10 @@ void main()
vec4 final_specular = spec;
#ifdef HAS_SPECULAR_MAP
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS);
final_specular.a = specular_color.a * norm.a;
#else
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS);
final_specular.a = specular_color.a;
#endif
@@ -444,10 +444,10 @@ void main()
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
- // deferred path
- frag_data[0] = final_color; //gbuffer is sRGB
+ // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
+ frag_data[0] = final_color; // gbuffer is sRGB
frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
+ frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
#endif
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
index 35068899ee..a513d60388 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
@@ -66,7 +66,7 @@ void main()
frag_data[0] = vec4(c.rgb, c.a);
frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0f);
+ frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS);
gl_FragDepth = 0.999985f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 09c47165dd..0ae4bbfc5d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -36,7 +36,6 @@ out vec4 frag_color;
uniform sampler2DRect depthMap;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
-uniform samplerCube environmentMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index ec3fb9c543..8dcc18080d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -42,7 +42,6 @@ uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
-uniform samplerCube environmentMap;
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
new file mode 100644
index 0000000000..e6f2c9d02b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl
@@ -0,0 +1,151 @@
+/**
+ * @file pbropaqueF.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 DEBUG_PBR_LIGHT_TYPE 0 // Output Diffuse=0.75, Emissive=0, ORM=0,0,0
+
+#define DEBUG_BASIC 0
+#define DEBUG_VERTEX 0
+#define DEBUG_NORMAL_MAP 0 // Output packed normal map "as is" to diffuse
+#define DEBUG_NORMAL_OUT 0 // Output unpacked normal to diffuse
+#define DEBUG_POSITION 0
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+uniform float metallicFactor;
+uniform float roughnessFactor;
+uniform vec3 emissiveColor;
+
+#ifdef HAS_NORMAL_MAP
+ uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_EMISSIVE_MAP
+ uniform sampler2D emissiveMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ uniform sampler2D specularMap; // Packed: Occlusion, Metal, Roughness
+#endif
+
+uniform samplerCube environmentMap;
+uniform mat3 env_mat;
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[4];
+#else
+#define frag_data gl_FragData
+#endif
+
+VARYING vec3 vary_position;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_normal;
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ VARYING vec2 vary_texcoord2;
+#endif
+
+vec2 encode_normal(vec3 n);
+vec3 linear_to_srgb(vec3 c);
+
+const float M_PI = 3.141592653589793;
+
+void main()
+{
+// IF .mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+// vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
+// else
+ vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb;
+
+#ifdef HAS_NORMAL_MAP
+ vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+ norm.xyz = norm.xyz * 2 - 1;
+
+ vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+ dot(norm.xyz,vary_mat1),
+ dot(norm.xyz,vary_mat2));
+#else
+ vec4 norm = vec4(0,0,0,1.0);
+// vec3 tnorm = vary_normal;
+ vec3 tnorm = vec3(0,0,1);
+#endif
+
+ tnorm = normalize(tnorm.xyz);
+
+ norm.xyz = normalize(tnorm.xyz);
+ // RGB = Occlusion, Roughness, Metal
+ // default values
+ // occlusion ?
+ // roughness 1.0
+ // metal 1.0
+#ifdef HAS_SPECULAR_MAP
+ vec3 spec = texture2D(specularMap, vary_texcoord2.xy).rgb;
+#else
+ vec3 spec = vec3(1,1,1);
+#endif
+
+ spec.g *= roughnessFactor;
+ spec.b *= metallicFactor;
+
+ vec3 emissive = emissiveColor;
+#ifdef HAS_EMISSIVE_MAP
+ emissive *= texture2D(emissiveMap, vary_texcoord0.xy).rgb;
+#endif
+
+#if DEBUG_PBR_LIGHT_TYPE
+ col.rgb = vec3(0.75);
+ emissive = vec3(0);
+ spec.rgb = vec3(0);
+#endif
+#if DEBUG_BASIC
+ col.rgb = vec3( 1, 0, 1 );
+#endif
+#if DEBUG_VERTEX
+ col.rgb = vertex_color.rgb;
+#endif
+#if DEBUG_NORMAL_MAP
+ col.rgb = texture2D(bumpMap, vary_texcoord1.xy).rgb;
+#endif
+#if DEBUG_NORMAL_OUT
+ col.rgb = vary_normal;
+#endif
+#if DEBUG_POSITION
+ col.rgb = vary_position.xyz;
+#endif
+
+ // See: C++: addDeferredAttachments(), GLSL: softenLightF
+ frag_data[0] = vec4(col, 0.0); // Diffuse
+ frag_data[1] = vec4(emissive, vertex_color.a); // PBR sRGB Emissive
+ frag_data[2] = vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags
+ frag_data[3] = vec4(spec.rgb,0); // PBR linear packed Occlusion, Roughness, Metal.
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
new file mode 100644
index 0000000000..82338069a8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl
@@ -0,0 +1,145 @@
+/**
+ * @file pbropaqueV.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$
+ */
+
+#define DIFFUSE_ALPHA_MODE_IGNORE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+#ifdef HAS_SKIN
+uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+mat4 getObjectSkinnedTransform();
+#else
+uniform mat3 normal_matrix;
+uniform mat4 modelview_projection_matrix;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#if !defined(HAS_SKIN)
+uniform mat4 modelview_matrix;
+#endif
+
+VARYING vec3 vary_position;
+
+#endif
+
+uniform mat4 texture_matrix0;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+
+#ifdef HAS_NORMAL_MAP
+ATTRIBUTE vec4 tangent;
+ATTRIBUTE vec2 texcoord1;
+
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ATTRIBUTE vec2 texcoord2;
+VARYING vec2 vary_texcoord2;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+ vec4 pos4 = vec4(position,1.0);
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+
+ mat = modelview_matrix * mat;
+
+ vec3 pos = (mat*pos4).xyz;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ vary_position = pos;
+#endif
+
+ gl_Position = projection_matrix*pos4;
+
+#else
+ //transform vertex
+
+ gl_Position = modelview_projection_matrix * pos4;
+#endif
+
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+#ifdef HAS_NORMAL_MAP
+ vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy;
+#endif
+
+#ifdef HAS_SKIN
+ vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#ifdef HAS_NORMAL_MAP
+ vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz);
+ vec3 b = cross(n, t)*tangent.w;
+
+ vary_mat0 = vec3(t.x, b.x, n.x);
+ vary_mat1 = vec3(t.y, b.y, n.y);
+ vary_mat2 = vec3(t.z, b.z, n.z);
+#else //HAS_NORMAL_MAP
+vary_normal = n;
+#endif //HAS_NORMAL_MAP
+#else //HAS_SKIN
+ vec3 n = normalize(normal_matrix * normal);
+#ifdef HAS_NORMAL_MAP
+ vec3 t = normalize(normal_matrix * tangent.xyz);
+ vec3 b = cross(n,t)*tangent.w;
+ //vec3 t = cross(b,n) * binormal.w;
+
+ vary_mat0 = vec3(t.x, b.x, n.x);
+ vary_mat1 = vec3(t.y, b.y, n.y);
+ vary_mat2 = vec3(t.z, b.z, n.z);
+#else //HAS_NORMAL_MAP
+ vary_normal = n;
+#endif //HAS_NORMAL_MAP
+#endif //HAS_SKIN
+
+ vertex_color = diffuse_color;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+#if !defined(HAS_SKIN)
+ vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
+#endif
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 18616a9bb3..5bb034d5c1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -1,5 +1,5 @@
/**
- * @file pointLightF.glsl
+ * @file class1\deferred\pointLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -36,7 +36,6 @@ out vec4 frag_color;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
-uniform samplerCube environmentMap;
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform sampler2DRect depthMap;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
index 345c07a354..8f3e38b08b 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/reflectionProbeF.glsl
@@ -1,58 +1,44 @@
-/**
- * @file shadowAlphaMaskF.glsl
+/**
+ * @file class1/deferred/reflectionProbeF.glsl
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
+ * 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 sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-VARYING vec3 pos;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
+// 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)
{
- float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
+ ambenv = vec3(1,0,1);
+ glossenv = vec3(1,0,1);
+ legacyenv = vec3(1,0,1);
+}
- frag_color = computeMoments(length(pos), float a);
+void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm)
+{
+ color = vec3(1,0,1);
+}
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
-#endif
+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/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index 331249dc33..ecb0c43518 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -57,7 +57,7 @@ void main()
/// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 0.0);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
- frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog
+ frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog
gl_FragDepth = 0.99999f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 7f2c603f87..918e119c31 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -142,7 +142,7 @@ void main()
color = mix(color.rgb, reflected_color, envIntensity);
}
- if (norm.w < 0.5)
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
{
color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
index bac79a9fdc..ef9cee3fa0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
@@ -60,7 +60,7 @@ void main()
frag_data[0] = col;
frag_data[1] = vec4(0.0f);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
gl_FragDepth = 0.99995f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
index b2fa5d8a25..4ab8747629 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
@@ -57,7 +57,7 @@ void main()
frag_data[0] = c;
frag_data[1] = vec4(0.0f);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+ frag_data[2] = vec4(0.0, 1.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
gl_FragDepth = 0.999988f;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 6b6eed9db8..d6c14c48c9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -63,6 +63,6 @@ void main()
frag_data[0] = outColor;
frag_data[1] = vec4(0.0,0.0,0.0,-1.0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index 89e354558a..dc0e5b0ce3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -52,5 +52,5 @@ void main()
frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal);
- frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+ frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
index 9a5debb3c1..14c337e608 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
@@ -78,5 +78,5 @@ void main()
frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
- frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, env intens, atmo kill
+ frag_data[2] = vec4(encode_normal(wavef), 0.0, GBUFFER_FLAG_HAS_ATMOS); // normalxyz, env intens, flags (atmo kill)
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index a157e9c017..03896f4c51 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -180,5 +180,5 @@ void main()
frag_data[1] = vec4(0); // speccolor, spec
- frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, 0);// normalxy, 0, 0
+ frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, GBUFFER_FLAG_HAS_ATMOS);// normalxy, env intens, flags (atmo kill)
}
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..4d91395a1b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
@@ -0,0 +1,100 @@
+/**
+ * @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
+
+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));
+ 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), mipLevel).rgb * cos(theta) * sin(theta);
+ sampleCount++;
+ }
+ }
+ frag_color = vec4(PI * color / float(sampleCount), 1.0);
+}
+// =============================================================================================================
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl
index b466883dc7..5190abf17c 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenV.glsl
@@ -1,9 +1,9 @@
/**
- * @file genSkyShV.glsl
+ * @file irradianceGenV.glsl
*
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * 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
@@ -22,16 +22,17 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
+uniform mat4 modelview_matrix;
+
ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-VARYING vec2 vary_frag;
+VARYING vec3 vary_dir;
void main()
{
- // pass through untransformed fullscreen pos
- gl_Position = vec4(position.xyz, 1.0);
- vary_frag = texcoord0;
+ 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
new file mode 100644
index 0000000000..94fedce243
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
@@ -0,0 +1,168 @@
+/**
+ * @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]*/
+
+#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/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 float mipLevel;
+
+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;
+ 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);
+ 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,sourceIdx), 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/class3/deferred/shVisV.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl
index 8f32dfde79..5f5d9396ff 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/shVisV.glsl
+ * @file radianceGenV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -22,12 +22,17 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
+
+uniform mat4 modelview_matrix;
+
ATTRIBUTE vec3 position;
-VARYING vec4 vary_pos;
+
+VARYING vec3 vary_dir;
void main()
{
- // Output
- vary_pos = vec4(position, 1);
- gl_Position = vary_pos;
+ 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/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
new file mode 100644
index 0000000000..ea687aab4f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
@@ -0,0 +1,75 @@
+/**
+ * @file reflectionmipF.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_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect screenMap;
+
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+ float w[9];
+
+ float c = 1.0/16.0; //corner weight
+ float e = 1.0/8.0; //edge weight
+ float m = 1.0/4.0; //middle weight
+
+ //float wsum = c*4+e*4+m;
+
+ w[0] = c; w[1] = e; w[2] = c;
+ w[3] = e; w[4] = m; w[5] = e;
+ w[6] = c; w[7] = e; w[8] = c;
+
+ vec2 tc[9];
+
+ float ed = 1;
+ float cd = 1;
+
+
+ tc[0] = vec2(-cd, cd); tc[1] = vec2(0, ed); tc[2] = vec2(cd, cd);
+ tc[3] = vec2(-ed, 0); tc[4] = vec2(0, 0); tc[5] = vec2(ed, 0);
+ tc[6] = vec2(-cd, -cd); tc[7] = vec2(0, -ed); tc[8] = vec2(cd, -1);
+
+ vec3 color = vec3(0,0,0);
+
+ for (int i = 0; i < 9; ++i)
+ {
+ color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
+ //color += texture2DRect(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
+ }
+
+ //color /= wsum;
+
+ frag_color = vec4(color, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
index ea2690ba09..3831eeaa01 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
@@ -43,6 +43,7 @@ uniform float sun_moon_glow_factor;
float getAmbientClamp() { return 1.0f; }
+// Returns colors in sRGB
void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,
out vec3 atten, bool use_ao)
{
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..ab5badf538
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
@@ -0,0 +1,477 @@
+/**
+ * @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);
+ }
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
index 6841a8194f..4379024680 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
@@ -195,5 +195,5 @@ void main()
// Gamma correct for WL (soft clip effect).
frag_data[0] = vec4(color.rgb, 1.0);
frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
- frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog
+ frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); // 1.0 in norm.w masks off fog
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 7700d16007..677c9c244c 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -88,7 +88,7 @@ void main()
da = pow(da, light_gamma);
vec4 diffuse = texture2DRect(diffuseRect, tc);
- diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14025
+ diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
@@ -139,7 +139,7 @@ void main()
color = mix(color.rgb, reflected_color, envIntensity);
}
- if (norm.w < 0.5)
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
{
color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
deleted file mode 100644
index d973326f93..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file avatarShadowF.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING vec2 vary_texcoord0;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- frag_color = computeMoments(length(pos), 1.0);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl
deleted file mode 100644
index 1a655e6467..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file attachmentShadowV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 projection_matrix;
-uniform mat4 modelview_matrix;
-uniform mat4 texture_matrix0;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-mat4 getObjectSkinnedTransform();
-
-VARYING vec4 pos;
-
-void main()
-{
- //transform vertex
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
- pos = (mat*vec4(position.xyz, 1.0));
- pos = projection_matrix * vec4(pos.xyz, 1.0);
-
-#if !defined(DEPTH_CLAMP)
- pos.z = max(pos.z, -pos.w+0.01);
-#endif
- gl_Position = pos;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
deleted file mode 100644
index 48eefc7a73..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * @file avatarShadowF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-VARYING vec4 pos;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- frag_color = computeMoments(length(pos), 1.0);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
-#endif
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
deleted file mode 100644
index 164b355f20..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file avatarShadowV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 projection_matrix;
-
-mat4 getSkinnedTransform();
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
-
-VARYING vec4 pos;
-
-void main()
-{
- vec3 norm;
-
- vec4 pos_in = vec4(position.xyz, 1.0);
- mat4 trans = getSkinnedTransform();
-
- pos.x = dot(trans[0], pos_in);
- pos.y = dot(trans[1], pos_in);
- pos.z = dot(trans[2], pos_in);
- pos.w = 1.0;
-
- norm.x = dot(trans[0].xyz, normal);
- norm.y = dot(trans[1].xyz, normal);
- norm.z = dot(trans[2].xyz, normal);
- norm = normalize(norm);
-
- pos = projection_matrix * pos;
-
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
-}
-
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
deleted file mode 100644
index 32210f60dc..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * @file class3/deferred/cloudsF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return normalize(cloud_noise_sample);
-}
-
-vec4 computeMoments(float depth, float alpha);
-
-void main()
-{
- if (cloud_scale >= 0.001)
- {
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
- vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- frag_color = computeMoments(length(pos), alpha1);
- }
- else
- {
- frag_color = vec4(0);
- }
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
deleted file mode 100644
index effb070f93..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @file cloudShadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&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 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
deleted file mode 100644
index e40d7e7c75..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * @file class3/deferred/cloudsF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-/////////////////////////////////////////////////////////////////////////
-// The fragment shader for the sky
-/////////////////////////////////////////////////////////////////////////
-
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
-VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-VARYING vec3 vary_pos;
-
-uniform sampler2D cloud_noise_texture;
-uniform sampler2D cloud_noise_texture_next;
-uniform float blend_factor;
-uniform vec4 cloud_pos_density1;
-uniform vec4 cloud_pos_density2;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
-uniform float cloud_scale;
-uniform float cloud_variance;
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-
-/// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light);
-
-vec4 cloudNoise(vec2 uv)
-{
- vec4 a = texture2D(cloud_noise_texture, uv);
- vec4 b = texture2D(cloud_noise_texture_next, uv);
- vec4 cloud_noise_sample = mix(a, b, blend_factor);
- return cloud_noise_sample;
-}
-
-void main()
-{
- // Set variables
- vec2 uv1 = vary_texcoord0.xy;
- vec2 uv2 = vary_texcoord1.xy;
- vec2 uv3 = vary_texcoord2.xy;
- float cloudDensity = 2.0 * (cloud_shadow - 0.25);
-
- if (cloud_scale < 0.001)
- {
- discard;
- }
-
- vec2 uv4 = vary_texcoord3.xy;
-
- vec2 disturbance = vec2(cloudNoise(uv1 / 16.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
-
- // Offset texture coords
- uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
- uv2 += cloud_pos_density1.xy; //large texture, self shadow
- uv3 += cloud_pos_density2.xy; //small texture, visible density
- uv4 += cloud_pos_density2.xy; //small texture, self shadow
-
- float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0) * 4.0);
-
- cloudDensity *= 1.0 - (density_variance * density_variance);
-
- // Compute alpha1, the main cloud opacity
- float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
- alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha1 = 1. - alpha1 * alpha1;
- alpha1 = 1. - alpha1 * alpha1;
-
- if (alpha1 < 0.001f)
- {
- discard;
- }
-
- // Compute alpha2, for self shadowing effect
- // (1 - alpha2) will later be used as percentage of incoming sunlight
- float alpha2 = (cloudNoise(uv2).x - 0.5);
- alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
- // And smooth
- alpha2 = 1. - alpha2;
- alpha2 = 1. - alpha2 * alpha2;
-
- vec3 view_ray = vary_pos.xyz + camPosLocal;
-
- vec3 view_direction = normalize(view_ray);
- vec3 sun_direction = normalize(sun_dir);
- vec3 earth_center = vec3(0, 0, -6360.0f);
- vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
-
- vec3 transmittance;
- vec3 radiance_sun = GetSkyLuminance(camPos, view_direction, 1.0 - alpha1, sun_direction, transmittance);
-
- vec3 sun_color = vec3(1.0) - exp(-radiance_sun * 0.0001);
-
- // Combine
- vec4 color;
-
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
-
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
-
- vec3 sun_indir = vec3(-view_direction.xy, view_direction.z);
- vec3 amb = vec3(dot(l1r, l1tap * vec4(1, sun_indir)),
- dot(l1g, l1tap * vec4(1, sun_indir)),
- dot(l1b, l1tap * vec4(1, sun_indir)));
-
-
- amb = max(vec3(0), amb);
-
- color.rgb = sun_color * cloud_color.rgb * (1. - alpha2);
- color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
- color.rgb += amb;
-
- frag_data[0] = vec4(color.rgb, alpha1);
- frag_data[1] = vec4(0);
- frag_data[2] = vec4(0,1,0,1);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
deleted file mode 100644
index 71e422ddf0..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * @file WLCloudsV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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_projection_matrix;
-uniform mat4 modelview_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-//////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-// Output parameters
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
-VARYING vec3 vary_pos;
-
-// Inputs
-uniform float cloud_scale;
-uniform vec4 lightnorm;
-uniform vec3 camPosLocal;
-
-void main()
-{
- vary_pos = position;
-
- // World / view / projection
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
- // Texture coords
- vary_texcoord0 = texcoord0;
- vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= max(0.001, cloud_scale);
- vary_texcoord0.xy += 0.5;
-
- vary_texcoord1 = vary_texcoord0;
- vary_texcoord1.x += lightnorm.x * 0.0125;
- vary_texcoord1.y += lightnorm.z * 0.0125;
-
- vary_texcoord2 = vary_texcoord0 * 16.;
- vary_texcoord3 = vary_texcoord1 * 16.;
-
- // END CLOUDS
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
deleted file mode 100644
index e27bbce094..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file class1/deferred/deferredUtil.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2DRect normalMap;
-uniform sampler2DRect depthMap;
-
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec2 getScreenCoordinate(vec2 screenpos)
-{
- vec2 sc = screenpos.xy * 2.0;
- if (screen_res.x > 0 && screen_res.y > 0)
- {
- sc /= screen_res;
- }
- return sc - vec2(1.0, 1.0);
-}
-
-vec3 getNorm(vec2 screenpos)
-{
- vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
- vec2 fenc = enc*4-2;
- float f = dot(fenc,fenc);
- float g = sqrt(1-f/4);
- vec3 n;
- n.xy = fenc*g;
- n.z = 1-f/2;
- return n;
-}
-
-float getDepth(vec2 pos_screen)
-{
- float depth = texture2DRect(depthMap, pos_screen).r;
- return depth;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
- float depth = getDepth(pos_screen);
- vec2 sc = getScreenCoordinate(pos_screen);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
-
-vec4 getPositionWithDepth(vec2 pos_screen, float depth)
-{
- vec2 sc = getScreenCoordinate(pos_screen);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl b/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
deleted file mode 100644
index cdaff4b09f..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * @file depthToShadowVolumeG.glsl
- *
- * $LicenseInfo:firstyear=2011&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$
- */
-#extension GL_ARB_geometry_shader4 : enable
-#extension GL_ARB_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-layout (triangles) in;
-layout (triangle_strip, max_vertices = 128) out;
-
-uniform sampler2DRect depthMap;
-uniform mat4 shadowMatrix[6];
-uniform vec4 lightpos;
-
-VARYING vec2 vary_texcoord0;
-
-out vec3 to_vec;
-
-void cross_products(out vec4 ns[3], int a, int b, int c)
-{
- ns[0] = cross(gl_PositionIn[b].xyz - gl_PositionIn[a].xyz, gl_PositionIn[c].xyz - gl_PositionIn[a].xyz);
- ns[1] = cross(gl_PositionIn[c].xyz - gl_PositionIn[b].xyz, gl_PositionIn[a].xyz - gl_PositionIn[b].xyz);
- ns[2] = cross(gl_PositionIn[a].xyz - gl_PositionIn[c].xyz, gl_PositionIn[b].xyz - gl_PositionIn[c].xyz);
-}
-
-vec3 getLightDirection(vec4 lightpos, vec3 pos)
-{
-
- vec3 lightdir = lightpos.xyz - lightpos.w * pos;
- return lightdir;
-}
-
-void emitTri(vec4 v[3])
-{
- gl_Position = proj_matrix * v[0];
- EmitVertex();
-
- gl_Position = proj_matrix * v[1];
- EmitVertex();
-
- gl_Position = proj_matrix * v[2];
- EmitVertex();
-
- EndPrimitive();
-}
-
-void emitQuad(vec4 v[4]
-{
- // Emit a quad as a triangle strip.
- gl_Position = proj_matrix*v[0];
- EmitVertex();
-
- gl_Position = proj_matrix*v[1];
- EmitVertex();
-
- gl_Position = proj_matrix*v[2];
- EmitVertex();
-
- gl_Position = proj_matrix*v[3];
- EmitVertex();
-
- EndPrimitive();
-}
-
-void emitPrimitives(int layer)
-{
- int i = layer;
- gl_Layer = i;
-
- vec4 depth1 = vec4(texture2DRect(depthMap, tc0).rg, texture2DRect(depthMap, tc1).rg));
- vec3 depth2 = vec4(texture2DRect(depthMap, tc2).rg, texture2DRect(depthMap, tc3).rg));
- vec3 depth3 = vec4(texture2DRect(depthMap, tc4).rg, texture2DRect(depthMap, tc5).rg));
- vec3 depth4 = vec4(texture2DRect(depthMap, tc6).rg, texture2DRect(depthMap, tc7).rg));
-
- depth1 = min(depth1, depth2);
- depth1 = min(depth1, depth3);
- depth1 = min(depth1, depth4);
-
- vec2 depth = min(depth1.xy, depth1.zw);
-
- int side = sqrt(gl_VerticesIn);
-
- for (int j = 0; j < side; j++)
- {
- for (int k = 0; k < side; ++k)
- {
- vec3 pos = gl_PositionIn[(j * side) + k].xyz;
- vec4 v = shadowMatrix[i] * vec4(pos, 1.0);
- gl_Position = v;
- to_vec = pos - light_position.xyz * depth;
- EmitVertex();
- }
-
- EndPrimitive();
- }
-
- vec3 norms[3]; // Normals
- vec3 lightdir3]; // Directions toward light
-
- vec4 v[4]; // Temporary vertices
-
- vec4 or_pos[3] =
- { // Triangle oriented toward light source
- gl_PositionIn[0],
- gl_PositionIn[2],
- gl_PositionIn[4]
- };
-
- // Compute normal at each vertex.
- cross_products(n, 0, 2, 4);
-
- // Compute direction from vertices to light.
- lightdir[0] = getLightDirection(lightpos, gl_PositionIn[0].xyz);
- lightdir[1] = getLightDirection(lightpos, gl_PositionIn[2].xyz);
- lightdir[2] = getLightDirection(lightpos, gl_PositionIn[4].xyz);
-
- // Check if the main triangle faces the light.
- bool faces_light = true;
- if (!(dot(ns[0],d[0]) > 0
- |dot(ns[1],d[1]) > 0
- |dot(ns[2],d[2]) > 0))
- {
- // Flip vertex winding order in or_pos.
- or_pos[1] = gl_PositionIn[4];
- or_pos[2] = gl_PositionIn[2];
- faces_light = false;
- }
-
- // Near cap: simply render triangle.
- emitTri(or_pos);
-
- // Far cap: extrude positions to infinity.
- v[0] =vec4(lightpos.w * or_pos[0].xyz - lightpos.xyz,0);
- v[1] =vec4(lightpos.w * or_pos[2].xyz - lightpos.xyz,0);
- v[2] =vec4(lightpos.w * or_pos[1].xyz - lightpos.xyz,0);
-
- emitTri(v);
-
- // Loop over all edges and extrude if needed.
- for ( int i=0; i<3; i++ )
- {
- // Compute indices of neighbor triangle.
- int v0 = i*2;
- int nb = (i*2+1);
- int v1 = (i*2+2) % 6;
- cross_products(n, v0, nb, v1);
-
- // Compute direction to light, again as above.
- d[0] =lightpos.xyz-lightpos.w*gl_PositionIn[v0].xyz;
- d[1] =lightpos.xyz-lightpos.w*gl_PositionIn[nb].xyz;
- d[2] =lightpos.xyz-lightpos.w*gl_PositionIn[v1].xyz;
-
- bool is_parallel = gl_PositionIn[nb].w < 1e-5;
-
- // Extrude the edge if it does not have a
- // neighbor, or if it's a possible silhouette.
- if (is_parallel ||
- ( faces_light != (dot(ns[0],d[0])>0 ||
- dot(ns[1],d[1])>0 ||
- dot(ns[2],d[2])>0) ))
- {
- // Make sure sides are oriented correctly.
- int i0 = faces_light ? v0 : v1;
- int i1 = faces_light ? v1 : v0;
-
- v[0] = gl_PositionIn[i0];
- v[1] = vec4(lightpos.w*gl_PositionIn[i0].xyz - lightpos.xyz, 0);
- v[2] = gl_PositionIn[i1];
- v[3] = vec4(lightpos.w*gl_PositionIn[i1].xyz - lightpos.xyz, 0);
-
- emitQuad(v);
- }
- }
-}
-
-void main()
-{
- // Output
- emitPrimitives(0);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
new file mode 100644
index 0000000000..a04f611440
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl
@@ -0,0 +1,122 @@
+/**
+ * @file fullbrightShinyF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, 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
+
+#ifndef HAS_DIFFUSE_LOOKUP
+uniform sampler2D diffuseMap;
+#endif
+
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+VARYING vec3 vary_texcoord1;
+VARYING vec3 vary_position;
+
+uniform samplerCube environmentMap;
+
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
+vec3 fullbrightShinyAtmosTransport(vec3 light);
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+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
+void main()
+{
+#ifdef HAS_DIFFUSE_LOOKUP
+ vec4 color = diffuseLookup(vary_texcoord0.xy);
+#else
+ vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
+#endif
+
+ color.rgb *= vertex_color.rgb;
+
+ // SL-9632 HUDs are affected by Atmosphere
+ if (no_atmo == 0)
+ {
+ 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);
+ }
+
+/*
+ // NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
+ else
+ {
+ vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+ float env_intensity = vertex_color.a;
+ color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+ }
+*/
+
+ color.a = 1.0;
+ //color.rgb = linear_to_srgb(color.rgb);
+
+ frag_color = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
deleted file mode 100644
index 34d26cddea..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * @file class3/deferred/gatherSkyShF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec2 screen_res;
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-void main()
-{
- vec2 offset = vec2(2.0) / screen_res;
-
- vec4 r = vec4(0);
- vec4 g = vec4(0);
- vec4 b = vec4(0);
-
- vec2 tc = vary_frag * 2.0;
-
- r += texture2D(sh_input_r, tc + vec2(0, 0));
- r += texture2D(sh_input_r, tc + vec2(offset.x, 0));
- r += texture2D(sh_input_r, tc + vec2(0, offset.y));
- r += texture2D(sh_input_r, tc + vec2(offset.x, offset.y));
- r /= 4.0f;
-
- g += texture2D(sh_input_g, tc + vec2(0, 0));
- g += texture2D(sh_input_g, tc + vec2(offset.x, 0));
- g += texture2D(sh_input_g, tc + vec2(0, offset.y));
- g += texture2D(sh_input_g, tc + vec2(offset.x, offset.y));
- g /= 4.0f;
-
- b += texture2D(sh_input_b, tc + vec2(0, 0));
- b += texture2D(sh_input_b, tc + vec2(offset.x, 0));
- b += texture2D(sh_input_b, tc + vec2(0, offset.y));
- b += texture2D(sh_input_b, tc + vec2(offset.x, offset.y));
- b /= 4.0f;
-
- frag_data[0] = r;
- frag_data[1] = g;
- frag_data[2] = b;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
deleted file mode 100644
index 337c8a50fe..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file gatherSkyShV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec2 vary_frag;
-uniform vec2 screen_res;
-
-void main()
-{
- // pass through untransformed fullscreen pos
- float oo_divisor = screen_res.x / 64.0;
- vec3 pos = (position.xyz * oo_divisor) + vec3(oo_divisor - 1, oo_divisor - 1, 0);
- gl_Position = vec4(pos.xyz, 1.0);
- vary_frag = texcoord0 * oo_divisor;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
deleted file mode 100644
index d5d91c88f0..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * @file class3/deferred/genSkyShF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec3 sun_dir;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-
-vec3 calcDirection(vec2 tc)
-{
- float phi = tc.y * 2.0 * 3.14159265;
- float cosTheta = sqrt(1.0 - tc.x);
- float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
- return vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
-}
-
-// reverse mapping above to convert a hemisphere direction into phi/theta values
-void getPhiAndThetaFromDirection(vec3 dir, out float phi, out float theta)
-{
- float sin_theta;
- float cos_theta;
- cos_theta = dir.z;
- theta = acos(cos_theta);
- sin_theta = sin(theta);
- phi = abs(sin_theta) > 0.0001 ? acos(dir.x / sin_theta) : 1.0;
-}
-
-// reverse mapping above to convert a hemisphere direction into an SH texture sample pos
-vec2 calcShUvFromDirection(vec3 dir)
-{
- vec2 uv;
- float phi;
- float theta;
- getPhiAndThetaFromDirection(dir, phi, theta);
- uv.y = phi / 2.0 * 3.14159265;
- uv.x = theta / 2.0 * 3.14159265;
- return uv;
-}
-
-void projectToL1(vec3 n, vec3 c, vec4 basis, out vec4 coeffs[3])
-{
- coeffs[0] = vec4(basis.x, n * basis.yzw * c.r);
- coeffs[1] = vec4(basis.x, n * basis.yzw * c.g);
- coeffs[2] = vec4(basis.x, n * basis.yzw * c.b);
-}
-
-void main()
-{
- float Y00 = sqrt(1.0 / 3.14159265) * 0.5;
- float Y1x = sqrt(3.0 / 3.14159265) * 0.5;
- float Y1y = Y1x;
- float Y1z = Y1x;
-
- vec4 L1 = vec4(Y00, Y1x, Y1y, Y1z);
-
- vec3 view_direction = calcDirection(vary_frag);
- vec3 sun_direction = normalize(sun_dir);
- vec3 cam_pos = vec3(0, 0, 6360);
-
- vec3 transmittance;
- vec3 radiance = GetSkyLuminance(cam_pos, view_direction, 0.0f, sun_direction, transmittance);
-
- vec3 color = vec3(1.0) - exp(-radiance * 0.0001);
-
- color = pow(color, vec3(1.0/2.2));
-
- vec4 coeffs[3];
- coeffs[0] = vec4(0);
- coeffs[1] = vec4(0);
- coeffs[2] = vec4(0);
-
- projectToL1(view_direction, color.rgb, L1, coeffs);
-
- frag_data[0] = coeffs[0];
- frag_data[1] = coeffs[1];
- frag_data[2] = coeffs[2];
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl b/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
deleted file mode 100644
index 33c5667cae..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file class3/deferred/indirect.glsl
- *
- * $LicenseInfo:firstyear=2011&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$
- */
-
-/*[EXTRA_CODE_HERE]*/
-
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-vec3 GetIndirect(vec3 norm)
-{
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
- vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
- dot(l1g, l1tap * vec4(1, norm.xyz)),
- dot(l1b, l1tap * vec4(1, norm.xyz)));
- indirect = clamp(indirect, vec3(0), vec3(1.0));
- return indirect;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
new file mode 100644
index 0000000000..7f8536cdab
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -0,0 +1,455 @@
+/**
+* @file materialF.glsl
+*
+* $LicenseInfo:firstyear=2007&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2007, 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]*/
+
+//class1/deferred/materialF.glsl
+
+// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+
+#define DIFFUSE_ALPHA_MODE_NONE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
+uniform int sun_up_factor;
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cs);
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+#ifdef HAS_SUN_SHADOW
+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;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform mat3 env_mat;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+VARYING vec2 vary_fragcoord;
+
+VARYING vec3 vary_position;
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+float getAmbientClamp();
+
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
+{
+ // SL-14895 inverted attenuation work-around
+ // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
+ // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
+ // to recover the `adjusted_radius` value previously being sent as la.
+ float falloff_factor = (12.0 * fa) - 9.0;
+ float inverted_la = falloff_factor / la;
+ // Yes, it makes me want to cry as well. DJH
+
+ vec3 col = vec3(0);
+
+ //get light vector
+ vec3 lv = lp.xyz - v;
+
+ //get distance
+ float dist = length(lv);
+ float da = 1.0;
+
+ dist /= inverted_la;
+
+ if (dist > 0.0 && inverted_la > 0.0)
+ {
+ //normalize light vector
+ lv = normalize(lv);
+
+ //distance attenuation
+ float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0f;
+
+ if (dist_atten <= 0.0)
+ {
+ return col;
+ }
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= dot(n, lv);
+
+ float lit = 0.0f;
+
+ float amb_da = ambiance;
+ if (da >= 0)
+ {
+ lit = max(da * dist_atten, 0.0);
+ col = lit * light_col * diffuse;
+ amb_da += (da*0.5 + 0.5) * ambiance;
+ }
+ amb_da += (da*da*0.5 + 0.5) * ambiance;
+ amb_da *= dist_atten;
+ amb_da = min(amb_da, 1.0f - lit);
+
+ // SL-10969 need to see why these are blown out
+ //col.rgb += amb_da * light_col * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(lv + npos);
+ float nh = dot(n, h);
+ float nv = dot(n, 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 speccol = lit*scol*light_col.rgb*spec.rgb;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ col += speccol;
+
+ float cur_glare = max(speccol.r, speccol.g);
+ cur_glare = max(cur_glare, speccol.b);
+ glare = max(glare, speccol.r);
+ glare += max(cur_glare, 0.0);
+ }
+ }
+ }
+
+ return max(col, vec3(0.0, 0.0, 0.0));
+}
+
+#else
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+#endif
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+#ifdef HAS_NORMAL_MAP
+uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+
+VARYING vec2 vary_texcoord2;
+#endif
+
+uniform float env_intensity;
+uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+uniform float minimum_alpha;
+#endif
+
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec2 encode_normal(vec3 n);
+
+void main()
+{
+ vec2 pos_screen = vary_texcoord0.xy;
+
+ vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+ diffcol.rgb *= vertex_color.rgb;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+ // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+ float bias = 0.001953125; // 1/512, or half an 8-bit quantization
+ if (diffcol.a < minimum_alpha-bias)
+ {
+ discard;
+ }
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ vec3 gamma_diff = diffcol.rgb;
+ diffcol.rgb = srgb_to_linear(diffcol.rgb);
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+ spec.rgb *= specular_color.rgb;
+#else
+ vec4 spec = vec4(specular_color.rgb, 1.0);
+#endif
+
+#ifdef HAS_NORMAL_MAP
+ vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+
+ norm.xyz = norm.xyz * 2 - 1;
+
+ vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+ dot(norm.xyz,vary_mat1),
+ dot(norm.xyz,vary_mat2));
+#else
+ vec4 norm = vec4(0,0,0,1.0);
+ vec3 tnorm = vary_normal;
+#endif
+
+ norm.xyz = normalize(tnorm.xyz);
+
+ vec2 abnormal = encode_normal(norm.xyz);
+
+ vec4 final_color = diffcol;
+
+#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
+ final_color.a = emissive_brightness;
+#else
+ final_color.a = max(final_color.a, emissive_brightness);
+#endif
+
+ vec4 final_specular = spec;
+
+#ifdef HAS_SPECULAR_MAP
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, GBUFFER_FLAG_HAS_ATMOS);
+ final_specular.a = specular_color.a * norm.a;
+#else
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, GBUFFER_FLAG_HAS_ATMOS);
+ final_specular.a = specular_color.a;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+ //forward rendering, output just lit sRGBA
+ vec3 pos = vary_position;
+
+ float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+ shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
+#endif
+
+ spec = final_specular;
+ vec4 diffuse = final_color;
+ float envIntensity = final_normal.z;
+
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+ float bloom = 0.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
+
+ // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
+ // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
+ // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
+ //color = fullbrightScaleSoftClip(color);
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+ //we're in sRGB space, so gamma correct this dot product so
+ // 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;
+
+ //darken ambient for normals perpendicular to light vector so surfaces in shadow
+ // and facing away from light still have some definition to them.
+ // do NOT gamma correct this dot product so ambient lighting stays soft
+ float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ ambient *= 0.5;
+ ambient *= ambient;
+ ambient = (1.0 - ambient);
+
+ color *= ambient;
+#endif
+
+ color += sun_contrib;
+
+ color *= gamma_diff.rgb;
+
+ float glare = 0.0;
+
+ if (spec.a > 0.0) // specular reflection
+ {
+ float sa = dot(refnormpersp, sun_dir.xyz);
+ vec3 dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+
+ glare = max(spec_contrib.r, spec_contrib.g);
+ 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
+ vec3 env_vec = env_mat * refnormpersp;
+
+ vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+
+ color = mix(color, reflected_color, envIntensity);
+
+ float cur_glare = max(reflected_color.r, reflected_color.g);
+ cur_glare = max(cur_glare, reflected_color.b);
+ cur_glare *= envIntensity*4.0;
+ glare += cur_glare;
+ }
+#endif
+
+ color = atmosFragLighting(color, additive, atten);
+ color = scaleSoftClipFrag(color);
+
+ //convert to linear before adding local lights
+ color = srgb_to_linear(color);
+
+ vec3 npos = normalize(-pos.xyz);
+
+ vec3 light = vec3(0, 0, 0);
+
+ final_specular.rgb = srgb_to_linear(final_specular.rgb); // SL-14035
+
+#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color += light;
+
+ glare = min(glare, 1.0);
+ float al = max(diffcol.a, glare)*vertex_color.a;
+
+ //convert to srgb as this color is being written post gamma correction
+ color = linear_to_srgb(color);
+
+#ifdef WATER_FOG
+ vec4 temp = applyWaterFogView(pos, vec4(color, al));
+ color = temp.rgb;
+ al = temp.a;
+#endif
+
+ frag_color = vec4(color, al);
+
+#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
+
+ // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
+ frag_data[0] = final_color; // gbuffer is sRGB
+ frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+ frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
new file mode 100644
index 0000000000..699a9c0276
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl
@@ -0,0 +1,190 @@
+/**
+ * @file class3\deferred\multiPointLightF.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_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#define DEBUG_PBR_LIGHT_TYPE 0
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect depthMap;
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+uniform int light_count;
+uniform vec4 light[LIGHT_COUNT]; // .w = size; see C++ fullscreen_lights.push_back()
+uniform vec4 light_col[LIGHT_COUNT]; // .a = falloff
+
+uniform vec2 screen_res;
+uniform float far_z;
+uniform mat4 inv_proj;
+
+VARYING vec4 vary_fragcoord;
+
+vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
+vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);
+vec4 getPosition(vec2 pos_screen);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec2 getScreenXY(vec4 clip);
+void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
+vec3 srgb_to_linear(vec3 c);
+
+void main()
+{
+#if defined(LOCAL_LIGHT_KILL)
+ discard; // Bail immediately
+#else
+ vec3 final_color = vec3(0, 0, 0);
+ vec2 tc = getScreenXY(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ float envIntensity; // not used for this shader
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ vec4 spec = texture2DRect(specularRect, tc);
+ vec3 diffuse = texture2DRect(diffuseRect, tc).rgb;
+
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorDiffuse = vec3(0);
+ vec3 colorSpec = vec3(0);
+ vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
+ vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+
+ vec3 c_diff, reflect0, reflect90;
+ float alphaRough, specWeight;
+ initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
+
+ for (int light_idx = 0; light_idx < LIGHT_COUNT; ++light_idx)
+ {
+ vec3 lightColor = light_col[ light_idx ].rgb;
+ float falloff = light_col[ light_idx ].a;
+ float lightSize = light [ light_idx ].w;
+ vec3 lv =(light [ light_idx ].xyz - pos);
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ if (nl > 0.0 || nv > 0.0)
+ {
+ float dist = lightDist / lightSize;
+ float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff);
+ vec3 intensity = dist_atten * getLightIntensityPoint(lightColor, lightSize, lightDist);
+ colorDiffuse += intensity * nl * BRDFLambertian (reflect0, reflect90, c_diff , specWeight, vh);
+ colorSpec += intensity * nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
+ }
+ }
+
+ #if DEBUG_PBR_LIGHT_TYPE
+ colorDiffuse = vec3(0,0.5,0); colorSpec = vec3(0);
+ #endif
+ final_color = colorDiffuse + colorSpec;
+ }
+ else
+ {
+ if (pos.z < far_z)
+ {
+ discard;
+ }
+
+ float noise = texture2D(noiseMap, tc/128.0).b;
+
+ // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+ for (int i = 0; i < LIGHT_COUNT; ++i)
+ {
+ vec3 lv = light[i].xyz - pos;
+ float dist = length(lv);
+ dist /= light[i].w;
+ if (dist <= 1.0)
+ {
+ float nl = dot(n, lv);
+ if (nl > 0.0)
+ {
+ float lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ float fa = light_col[i].a + 1.0;
+ float dist_atten = clamp(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+
+ // Tweak falloff slightly to match pre-EEP attenuation
+ // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit
+ dist_atten *= 2.0;
+
+ dist_atten *= noise;
+
+ float lit = nl * dist_atten;
+
+ vec3 col = light_col[i].rgb * lit * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ lit = min(nl * 6.0, 1.0) * dist_atten;
+ float fres = pow(1 - vh, 5) * 0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres * texture2D(lightFunc, vec2(nh, spec.a)).r * gt / (nh * nl);
+ col += lit * scol * light_col[i].rgb * spec.rgb;
+ }
+ }
+
+ final_color += col;
+ }
+ }
+ }
+ }
+
+ frag_color.rgb = final_color;
+ frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
+
+#ifdef IS_AMD_CARD
+ // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage
+ // away which leads to unfun crashes and artifacts.
+ vec4 dummy1 = light[0];
+ vec4 dummy2 = light_col[0];
+ vec4 dummy3 = light[LIGHT_COUNT - 1];
+ vec4 dummy4 = light_col[LIGHT_COUNT - 1];
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl
index bc5eb5181d..ad6a0fa752 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightV.glsl
@@ -1,9 +1,9 @@
/**
- * @file sunLightV.glsl
+ * @file class3\deferred\multiPointLightV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -27,15 +27,13 @@ uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
-VARYING vec2 vary_fragcoord;
-
-uniform vec2 screen_res;
+VARYING vec4 vary_fragcoord;
void main()
{
//transform vertex
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- gl_Position = pos;
-
- vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;
+ vary_fragcoord = pos;
+
+ gl_Position = pos;
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
index 9d62b9d180..20309d9673 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
@@ -1,9 +1,9 @@
/**
- * @file multiSpotLightF.glsl
+ * @file class3\deferred\multiSpotLightF.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -28,6 +28,16 @@
/*[EXTRA_CODE_HERE]*/
+#define DEBUG_PBR_LIGHT_TYPE 0 // Ouput gray if PBR multiSpot lights object
+#define DEBUG_PBR_SPOT 0
+#define DEBUG_PBR_SPOT_DIFFUSE 0 // PBR diffuse lit
+#define DEBUG_PBR_SPOT_SPECULAR 0 // PBR spec lit
+
+#define DEBUG_SPOT_DIFFUSE 0
+#define DEBUG_SPOT_NL 0 // monochome area effected by light
+#define DEBUG_SPOT_SPEC_POS 0
+#define DEBUG_SPOT_REFLECTION 0
+
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
@@ -38,10 +48,11 @@ uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
+uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform samplerCube environmentMap;
uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
-uniform sampler2D projectionMap;
+uniform sampler2D projectionMap; // rgba
uniform sampler2D lightFunc;
uniform mat4 proj_mat; //screen space to light space
@@ -61,6 +72,7 @@ uniform float sun_wash;
uniform int proj_shadow_idx;
uniform float shadow_fade;
+// Light params
uniform vec3 center;
uniform float size;
uniform vec3 color;
@@ -71,221 +83,246 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
-vec3 getNorm(vec2 pos_screen);
-
-vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- d *= min(1, d * (proj_lod - lod));
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
-
-vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
+vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
+vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
+vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
+vec2 getScreenXY(vec4 clip);
+void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
+vec3 srgb_to_linear(vec3 cs);
+vec4 texture2DLodSpecular(vec2 tc, float lod);
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
+ ret.rgb = srgb_to_linear(ret.rgb);
vec2 dist = tc-vec2(0.5);
-
+
float d = dot(dist,dist);
-
+
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
-
+
return ret;
}
-
vec4 getPosition(vec2 pos_screen);
-void main()
+void main()
{
- vec4 frag = vary_fragcoord;
- frag.xyz /= frag.w;
- frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
-
- vec3 pos = getPosition(frag.xy).xyz;
- vec3 lv = center.xyz-pos.xyz;
- float dist = length(lv);
- dist /= size;
- if (dist > 1.0)
+#if defined(LOCAL_LIGHT_KILL)
+ discard;
+#else
+ vec3 final_color = vec3(0,0,0);
+ vec2 tc = getScreenXY(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ vec3 lv;
+ vec4 proj_tc;
+ float dist, l_dist;
+ if (clipProjectedLightVars(center, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
-
+
float shadow = 1.0;
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
- shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
+ vec4 shd = texture2DRect(lightMap, tc);
+ shadow = (proj_shadow_idx==0)?shd.b:shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
-
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-
- float envIntensity = norm.z;
- norm = getNorm(frag.xy);
-
- norm = normalize(norm);
- float l_dist = -dot(lv, proj_n);
-
- vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
- if (proj_tc.z < 0.0)
- {
- discard;
- }
-
- proj_tc.xyz /= proj_tc.w;
-
- float fa = (falloff*0.5)+1.0;
- float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0;
- if (dist_atten <= 0.0)
- {
- discard;
- }
-
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity);
+
+ float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff);
+
lv = proj_origin-pos.xyz;
- lv = normalize(lv);
- float da = dot(norm, lv);
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
- vec3 col = vec3(0,0,0);
-
- vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
+ vec3 diffuse = texture2DRect(diffuseRect, tc).rgb;
+ vec4 spec = texture2DRect(specularRect, tc);
+ vec3 dlit = vec3(0, 0, 0);
+ vec3 slit = vec3(0, 0, 0);
- vec3 dlit = vec3(0, 0, 0);
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorDiffuse = vec3(0);
+ vec3 colorSpec = vec3(0);
+ vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
+ vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+ float metal = packedORM.b;
+
+// if (proj_tc.x > 0.0 && proj_tc.x < 1.0
+// && proj_tc.y > 0.0 && proj_tc.y < 1.0)
+ if (nl > 0.0)
+ {
+ vec3 c_diff, reflect0, reflect90;
+ float alphaRough, specWeight;
+ initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
- if (proj_tc.z > 0.0 &&
- proj_tc.x < 1.0 &&
- proj_tc.y < 1.0 &&
- proj_tc.x > 0.0 &&
- proj_tc.y > 0.0)
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+ slit = getProjectedLightSpecularColor( pos, n );
+
+// vec3 intensity = getLightIntensitySpot( color, size, lightDist, v );
+ colorDiffuse = shadow * dlit * nl * dist_atten;
+ colorSpec = shadow * slit * nl * dist_atten;
+
+// colorDiffuse *= BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
+// colorSpec *= BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
+
+ #if DEBUG_PBR_SPOT_DIFFUSE
+ colorDiffuse = dlit.rgb; colorSpec = vec3(0);
+ #endif
+ #if DEBUG_PBR_SPOT_SPECULAR
+ colorDiffuse = vec3(0); colorSpec = slit.rgb;
+ #endif
+ #if DEBUG_PBR_SPOT
+ colorDiffuse = dlit; colorSpec = vec3(0);
+ colorDiffuse *= nl;
+ colorDiffuse *= shadow;
+ #endif
+
+ #if DEBUG_SPOT_SPEC_POS
+ colorDiffuse = pos + ref * dot(pdelta, proj_n)/ds; colorSpec = vec3(0);
+ #endif
+ #if DEBUG_SPOT_REFLECTION
+ colorDiffuse = ref; colorSpec = vec3(0);
+ #endif
+
+ }
+
+ #if DEBUG_SPOT_DIFFUSE
+ colorDiffuse = vec3(nl * dist_atten);
+ #endif
+ #if DEBUG_SPOT_NL
+ colorDiffuse = vec3(nl); colorSpec = vec3(0);
+ #endif
+ #if DEBUG_PBR_LIGHT_TYPE
+ colorDiffuse = vec3(0.5); colorSpec = vec3(0);
+ #endif
+
+ final_color = colorDiffuse + colorSpec;
+ }
+ else
{
- float amb_da = proj_ambiance;
- float lit = 0.0;
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0;
+ if (dist_atten <= 0.0)
+ {
+ discard;
+ }
- if (da > 0.0)
+ float noise = texture2D(noiseMap, tc/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
{
- lit = da * dist_atten * noise;
+ float amb_da = proj_ambiance;
+ float lit = 0.0;
- float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
- float lod = diff * proj_lod;
-
- vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+ if (nl > 0.0)
+ {
+ lit = nl * dist_atten * noise;
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+
+ final_color = dlit*lit*diffuse*shadow;
+
+ // unshadowed for consistency between forward and deferred?
+ amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ }
- dlit = color.rgb * plcol.rgb * plcol.a;
-
- col = dlit*lit*diff_tex*shadow;
- amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ // use unshadowed for consistency between forward and deferred?
+ amb_da += (nl*nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ amb_da *= dist_atten * noise;
+ amb_da = min(amb_da, 1.0-lit);
+
+ final_color += amb_da*color.rgb*diffuse.rgb*amb_plcol.rgb*amb_plcol.a;
}
-
- //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
- vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
-
- amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
-
- amb_da *= dist_atten * noise;
-
- amb_da = min(amb_da, 1.0-lit);
-
- col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
- }
+ if (spec.a > 0.0)
+ {
+ dlit *= min(nl*6.0, 1.0) * dist_atten;
- if (spec.a > 0.0)
- {
- vec3 npos = -normalize(pos);
- dlit *= min(da*6.0, 1.0) * dist_atten;
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv+npos);
- float nh = dot(norm, h);
- float nv = dot(norm, 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));
+ float fres = pow(1 - vh, 5)*0.4+0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- col += dlit*scol*spec.rgb*shadow;
- //col += spec.rgb;
- }
- }
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ vec3 speccol = dlit*scol*spec.rgb*shadow;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ final_color += speccol;
+ }
+ }
- if (envIntensity > 0.0)
- {
- vec3 ref = reflect(normalize(pos), norm);
+ if (envIntensity > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), n);
- //project from point pos in direction ref to plane proj_p, proj_n
- vec3 pdelta = proj_p-pos;
- float ds = dot(ref, proj_n);
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
- if (ds < 0.0)
- {
- vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
- vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
- if (stc.z > 0.0)
- {
- stc /= stc.w;
-
- if (stc.x < 1.0 &&
- stc.y < 1.0 &&
- stc.x > 0.0 &&
- stc.y > 0.0)
+ if (stc.z > 0.0)
{
- col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ stc /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ }
}
}
+ #if DEBUG_SPOT_SPEC_POS
+ final_color = pos + ref * dot(pdelta, proj_n)/ds;
+ #endif
+ #if DEBUG_SPOT_REFLECTION
+ final_color = ref;
+ #endif
}
+
+#if DEBUG_SPOT_NL
+ final_color =vec3(nl);
+#endif
+#if DEBUG_SPOT_DIFFUSE
+ final_color = vec3(nl * dist_atten * noise);
+#endif
+
}
//not sure why, but this line prevents MATBUG-194
- col = max(col, vec3(0.0));
-
- col = scaleDownLight(col);
+ final_color = max(final_color, vec3(0.0));
- //output linear space color as gamma correction happens down stream
- frag_color.rgb = col;
+ //output linear
+ frag_color.rgb = final_color;
frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
new file mode 100644
index 0000000000..defd577266
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl
@@ -0,0 +1,164 @@
+/**
+ * @file class3\deferred\pointLightF.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_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#define DEBUG_PBR_LIGHT_TYPE 0
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+uniform sampler2D noiseMap;
+uniform sampler2D lightFunc;
+uniform sampler2DRect depthMap;
+
+uniform vec3 env_mat[3];
+uniform float sun_wash;
+
+// light params
+uniform vec3 color;
+uniform float falloff;
+uniform float size;
+
+VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
+
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+uniform vec4 viewport;
+
+vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
+vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+vec3 getLightIntensityPoint(vec3 lightColor, float lightRange, float lightDistance);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec4 getPosition(vec2 pos_screen);
+vec2 getScreenXY(vec4 clip);
+void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
+vec3 srgb_to_linear(vec3 c);
+
+void main()
+{
+ vec3 final_color = vec3(0);
+ vec2 tc = getScreenXY(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ vec3 diffuse = texture2DRect(diffuseRect, tc).rgb;
+ vec4 spec = texture2DRect(specularRect, tc);
+
+ // Common half vectors calcs
+ vec3 lv = trans_center.xyz-pos;
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ float dist = lightDist / size;
+ float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff);
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
+ {
+ vec3 colorDiffuse = vec3(0);
+ vec3 colorSpec = vec3(0);
+ vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
+ vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+
+ vec3 c_diff, reflect0, reflect90;
+ float alphaRough, specWeight;
+ initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
+
+ if (nl > 0.0 || nv > 0.0)
+ {
+ vec3 intensity = dist_atten * getLightIntensityPoint(color, size, lightDist);
+ colorDiffuse += intensity * nl * BRDFLambertian (reflect0, reflect90, c_diff , specWeight, vh);
+ colorSpec += intensity * nl * BRDFSpecularGGX(reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh);
+ }
+
+#if DEBUG_PBR_LIGHT_TYPE
+ colorDiffuse = vec3(0,0,0.5); colorSpec = vec3(0);
+#endif
+
+ final_color = colorDiffuse + colorSpec;
+ }
+ else
+ {
+ float dist = lightDist;
+ if (dist >= size)
+ {
+ discard;
+ }
+ dist /= size;
+
+ if (nl < 0.0)
+ {
+ discard;
+ }
+
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0;
+
+ float noise = texture2D(noiseMap, tc/128.0).b;
+ float lit = nl * dist_atten * noise;
+
+ final_color = color.rgb*lit*diffuse;
+
+ if (spec.a > 0.0)
+ {
+ lit = min(nl*6.0, 1.0) * dist_atten;
+
+ float sa = nh;
+ float fres = pow(1 - vh, 5) * 0.4+0.5;
+ float gtdenom = 2 * nh;
+ float gt = max(0,(min(gtdenom * nv / vh, gtdenom * nl / vh)));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ final_color += lit*scol*color.rgb*spec.rgb;
+ }
+ }
+
+ if (dot(final_color, final_color) <= 0.0)
+ {
+ discard;
+ }
+ }
+
+ frag_color.rgb = final_color;
+ frag_color.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl
index db8c75fb8a..d42c8f6cf6 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightV.glsl
@@ -1,9 +1,9 @@
/**
- * @file class3/deferred/shadowCubeV.glsl
+ * @file class3\deferred\pointLightV.glsl
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -24,27 +24,22 @@
*/
uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
ATTRIBUTE vec3 position;
-#if !defined(DEPTH_CLAMP)
-VARYING vec4 post_pos;
-#endif
+uniform vec3 center;
+uniform float size;
-uniform vec3 box_center;
-uniform vec3 box_size;
+VARYING vec4 vary_fragcoord;
+VARYING vec3 trans_center;
void main()
{
//transform vertex
- vec3 p = position*box_size+box_center;
- vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
-
-#if !defined(DEPTH_CLAMP)
- post_pos = pos;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
+ vec3 p = position*size+center;
+ vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0);
+ vary_fragcoord = pos;
+ trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz;
gl_Position = pos;
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
new file mode 100644
index 0000000000..83348077d7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -0,0 +1,566 @@
+/**
+ * @file class3/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;
+uniform samplerCubeArray irradianceProbes;
+
+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];
+ // extra parameters (currently only .x used for probe ambiance)
+ vec4 refParams[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;
+};
+
+// 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;
+}
+
+int max_priority = 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;
+ }
+
+ max_priority = max(max_priority, -refIndex[i].w);
+ }
+ 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;
+ }
+
+ max_priority = max(max_priority, refIndex[i].w);
+ }
+
+ 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 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;
+ {
+ return textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod).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;
+ }
+}
+
+vec3 sampleProbes(vec3 pos, vec3 dir, float lod, float minweight)
+{
+ 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];
+ 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 = 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)
+{
+ // 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
+
+ float minweight = 1.0;
+
+ 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
+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);
+
+ if (glossiness > 0.0)
+ {
+ float lod = (1.0-glossiness)*reflection_lods;
+ glossenv = sampleProbes(pos, normalize(refnormpersp), lod, 1.f);
+ }
+
+ if (envIntensity > 0.0)
+ {
+ legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, 1.f);
+ }
+}
+
+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);
+ }
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
deleted file mode 100644
index c8991f7a18..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file class3/deferred/shVisF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
- out vec4 frag_color;
-#else
- #define frag_color gl_FragColor
-#endif
-
-/////////////////////////////////////////////////////////////////////////
-// Fragment shader for L1 SH debug rendering
-/////////////////////////////////////////////////////////////////////////
-
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
-
-uniform mat3 inv_modelviewprojection;
-
-VARYING vec4 vary_pos;
-
-void main(void)
-{
- vec2 coord = vary_pos.xy + vec2(0.5,0.5);
-
- coord.x *= (1.6/0.9);
-
- if (dot(coord, coord) > 0.25)
- {
- discard;
- }
-
- vec4 n = vec4(coord*2.0, 0.0, 1);
- //n.y = -n.y;
- n.z = sqrt(max(1.0-n.x*n.x-n.y*n.y, 0.0));
- //n.xyz = inv_modelviewprojection * n.xyz;
-
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
- vec3 indirect = vec3(
- dot(l1r, l1tap * n),
- dot(l1g, l1tap * n),
- dot(l1b, l1tap * n));
-
- //indirect = pow(indirect, vec3(0.45));
- indirect *= 3.0;
-
- frag_color = vec4(indirect, 1.0);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
deleted file mode 100644
index af1461c297..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file shadowAlphaMaskV.glsl
- *
- * $LicenseInfo:firstyear=2011&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 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float target_pos_x;
-VARYING vec4 pos;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
- vec4 pos = modelview_projection_matrix * pre_pos;
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
- pos_w = pos.w;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
deleted file mode 100644
index 50f1ffd626..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * @file class3/deferred/shadowAlphaMaskF.glsl
- *
- * $LicenseInfo:firstyear=2011&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$
- */
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec4 getPosition(vec2 screen_coord);
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- vec4 pos = getPosition(vary_texcoord0.xy);
-
- float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
-
- if (alpha < 0.05) // treat as totally transparent
- {
- discard;
- }
-
- if (alpha < 0.88) // treat as semi-transparent
- {
- if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
- {
- discard;
- }
- }
-
- frag_color = computeMoments(length(pos.xyz), alpha);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
-#endif
-
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
deleted file mode 100644
index 6a646f5e9e..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * @file class3/deferred/shadowAlphaMaskV.glsl
- *
- * $LicenseInfo:firstyear=2011&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 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-uniform float shadow_target_width;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
-
- pos = modelview_projection_matrix * pre_pos;
-
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- passTextureIndex();
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl
deleted file mode 100644
index 3350267130..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * @file class3/deferred/shadowF.glsl
- *
- * $LicenseInfo:firstyear=2011&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$
- */
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-
-vec4 computeMoments(float depth, float a);
-
-void main()
-{
- frag_color = computeMoments(length(pos), 1.0);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
deleted file mode 100644
index 2f69a353e8..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * @file class3/deferred/shadowUtil.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 sampler2D shadowMap0;
-uniform sampler2D shadowMap1;
-uniform sampler2D shadowMap2;
-uniform sampler2D shadowMap3;
-uniform sampler2D shadowMap4;
-uniform sampler2D shadowMap5;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-uniform vec2 shadow_res;
-uniform vec2 proj_shadow_res;
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float shadow_bias;
-
-uniform float spot_shadow_bias;
-uniform float spot_shadow_offset;
-
-float getDepth(vec2 screenpos);
-vec3 getNorm(vec2 screenpos);
-vec4 getPosition(vec2 pos_screen);
-
-float ReduceLightBleeding(float p_max, float Amount)
-{
- return smoothstep(Amount, 1, p_max);
-}
-
-float ChebyshevUpperBound(vec2 m, float t, float min_v, float Amount)
-{
- float p = (t <= m.x) ? 1.0 : 0.0;
-
- float v = m.y - (m.x*m.x);
- v = max(v, min_v);
-
- float d = t - m.x;
-
- float p_max = v / (v + d*d);
-
- p_max = ReduceLightBleeding(p_max, Amount);
-
- return max(p, p_max);
-}
-
-vec4 computeMoments(float depth, float a)
-{
- float m1 = depth;
- float dx = dFdx(depth);
- float dy = dFdy(depth);
- float m2 = m1*m1 + 0.25 * a * (dx*dx + dy*dy);
- return vec4(m1, m2, a, max(dx, dy));
-}
-
-float vsmDirectionalSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
-{
- vec4 lpos = shadowMatrix * stc;
- vec4 moments = texture2D(shadowMap, lpos.xy);
- return ChebyshevUpperBound(moments.rg, depth - shadow_bias * 256.0f, 0.125, 0.9);
-}
-
-float vsmSpotSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
-{
- vec4 lpos = shadowMatrix * stc;
- vec4 moments = texture2D(shadowMap, lpos.xy);
- lpos.xyz /= lpos.w;
- lpos.xy *= 0.5;
- lpos.xy += 0.5;
- return ChebyshevUpperBound(moments.rg, depth - spot_shadow_bias * 16.0f, 0.125, 0.9);
-}
-
-#if VSM_POINT_SHADOWS
-float vsmPointSample(float lightDistance, vec3 lightDirection, samplerCube shadow_cube_map)
-{
- vec4 moments = textureCube(shadow_cube_map, light_direction);
- return ChebyshevUpperBound(moments.rg, light_distance, 0.01, 0.25);
-}
-#endif
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
-{
- if (pos.z < -shadow_clip.w)
- {
- discard;
- }
-
- float depth = getDepth(pos_screen);
-
- vec4 spos = vec4(pos,1.0);
- vec4 near_split = shadow_clip*-0.75;
- vec4 far_split = shadow_clip*-1.25;
-
- float shadow = 0.0f;
- float weight = 1.0;
-
- if (spos.z < near_split.z)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap3, shadow_matrix[3]);
- weight += 1.0f;
- }
- if (spos.z < near_split.y)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap2, shadow_matrix[2]);
- weight += 1.0f;
- }
- if (spos.z < near_split.x)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap1, shadow_matrix[1]);
- weight += 1.0f;
- }
- if (spos.z > far_split.x)
- {
- shadow += vsmDirectionalSample(spos, depth, shadowMap0, shadow_matrix[0]);
- weight += 1.0f;
- }
-
- shadow /= weight;
-
- return shadow;
-}
-
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
-{
- if (pos.z < -shadow_clip.w)
- {
- discard;
- }
-
- float depth = getDepth(pos_screen);
-
- pos += norm * spot_shadow_offset;
- return vsmSpotSample(vec4(pos, 1.0), depth, (index == 0) ? shadowMap4 : shadowMap5, shadow_matrix[4 + index]);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
deleted file mode 100644
index 6577fe0ecf..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * @file class3/deferred/shadowV.glsl
- *
- * $LicenseInfo:firstyear=2011&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_projection_matrix;
-uniform float shadow_target_width;
-uniform mat4 texture_matrix0;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-#if !defined(DEPTH_CLAMP)
-VARYING float pos_zd2;
-#endif
-
-VARYING vec4 pos;
-VARYING float target_pos_x;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-void passTextureIndex();
-
-void main()
-{
- //transform vertex
- vec4 pre_pos = vec4(position.xyz, 1.0);
-
- pos = modelview_projection_matrix * pre_pos;
-
- target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
-
-#if !defined(DEPTH_CLAMP)
- pos_zd2 = pos.z * 0.5;
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-#else
- gl_Position = pos;
-#endif
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
deleted file mode 100644
index a0b082ed7c..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * @file class3/deferred/skyF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec2 vary_frag;
-
-uniform vec3 camPosLocal;
-uniform vec3 sun_dir;
-uniform float sun_size;
-uniform float far_z;
-uniform mat4 inv_proj;
-uniform mat4 inv_modelview;
-
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
-uniform sampler2D rainbow_map;
-uniform sampler2D halo_map;
-
-uniform float moisture_level;
-uniform float droplet_radius;
-uniform float ice_level;
-
-vec3 GetSolarLuminance();
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
-
-vec3 ColorFromRadiance(vec3 radiance);
-vec3 rainbow(float d)
-{
- // d is the dot product of view and sun directions, so ranging -1.0..1.0
- // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
- // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
-
- // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
- // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
- // interesting range, but in reversed order: i.e. d = (1 - d) - 1.575
- d = clamp(-0.575 - d, 0.0, 1.0);
-
- // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
- // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
- // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
- float interior_coord = max(0.0, d - 0.25) * 4.2857;
- d = clamp(d, 0.0, 0.25) + interior_coord;
-
- float rad = (droplet_radius - 5.0f) / 1024.0f;
- return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
-}
-
-vec3 halo22(float d)
-{
- float v = sqrt(max(0, 1 - (d*d)));
- return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
-}
-
-void main()
-{
- vec3 pos = vec3((vary_frag * 2.0) - vec2(1.0, 1.0f), 1.0);
- vec4 view_pos = (inv_proj * vec4(pos, 1.0f));
-
- view_pos /= view_pos.w;
-
- vec3 view_ray = (inv_modelview * vec4(view_pos.xyz, 0.0f)).xyz + camPosLocal;
-
- vec3 view_direction = normalize(view_ray);
- vec3 sun_direction = normalize(sun_dir);
- vec3 earth_center = vec3(0, 0, -6360.0f);
- vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
-
- vec3 transmittance;
- vec3 radiance_sun = GetSkyLuminance(camPos, view_direction, 0.0f, sun_direction, transmittance);
- vec3 solar_luminance = GetSolarLuminance();
-
- // If the view ray intersects the Sun, add the Sun radiance.
- float s = dot(view_direction, sun_direction);
-
- // cheesy solar disc...
- if (s >= (sun_size * 0.999))
- {
- radiance_sun += pow(smoothstep(0.0, 1.3, (s - (sun_size * 0.9))), 2.0) * solar_luminance * transmittance;
- }
- s = smoothstep(0.9, 1.0, s) * 16.0f;
-
- vec3 color = ColorFromRadiance(radiance_sun);
-
- float optic_d = dot(view_direction, sun_direction);
- vec3 halo_22 = halo22(optic_d);
-
- color.rgb += rainbow(optic_d) * optic_d;
- color.rgb += halo_22;
-
- color = pow(color, vec3(1.0/2.2));
-
- frag_data[0] = vec4(color, 1.0 + s);
- frag_data[1] = vec4(0.0);
- frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
deleted file mode 100644
index 2eb222ada4..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * @file class3/deferred/skyV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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$
- */
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec2 vary_frag;
-
-void main()
-{
- // pass through untransformed fullscreen pos at back of frustum for proper sky depth testing
- gl_Position = vec4(position.xy, 1.0f, 1.0);
- vary_frag = texcoord0;
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 7ed9e7b4fc..c2a3e472d0 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -1,31 +1,103 @@
-/**
+/**
* @file class3/deferred/softenLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, 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$
*/
-
+
+#define PBR_USE_ATMOS 0
+#define PBR_USE_GGX_EMS_HACK 0
+#define PBR_USE_IRRADIANCE_HACK 1
+
+#define DEBUG_PBR_LIGHT_TYPE 0 // Output no global light to make it easier to see pointLight and spotLight
+#define DEBUG_PBR_PACKORM0 0 // Rough=0, Metal=0
+#define DEBUG_PBR_PACKORM1 0 // Rough=1, Metal=1
+#define DEBUG_PBR_TANGENT1 1 // Tangent = 1,0,0
+#define DEBUG_PBR_VERT2CAM1 0 // vertex2camera = 0,0,1
+#define DEBUG_PBR_SPECLIGHT051 0 // Force specLigh to be 0,0.5,1
+
+// Pass input through "as is"
+#define DEBUG_PBR_DIFFUSE_MAP 0 // Output: use diffuse in G-Buffer
+#define DEBUG_PBR_EMISSIVE 0 // Output: Emissive
+#define DEBUG_PBR_METAL 0 // Output: grayscale Metal map
+#define DEBUG_PBR_NORMAL_MAP 0 // Output: Normal -- also need to set DEBUG_NORMAL_MAP in pbropaqueF
+#define DEBUG_PBR_OCCLUSION 0 // Output: grayscale Occlusion map
+#define DEBUG_PBR_ORM 0 // Output: Packed Occlusion Roughness Metal
+#define DEBUG_PBR_ROUGH_PERCEPTUAL 0 // Output: grayscale Perceptual Roughness map
+#define DEBUG_PBR_ROUGH_ALPHA 0 // Output: grayscale Alpha Roughness
+
+#define DEBUG_PBR_TANGENT 0 // Output: Tangent
+#define DEBUG_PBR_BITANGENT 0 // Output: Bitangent
+#define DEBUG_PBR_DOT_BV 0 // Output: graysacle dot(Bitangent,Vertex2Camera)
+#define DEBUG_PBR_DOT_TV 0 // Output: grayscale dot(Tangent ,Vertex2Camera)
+
+// IBL Spec
+#define DEBUG_PBR_NORMAL 0 // Output: passed in normal
+#define DEBUG_PBR_V2C_RAW 0 // Output: vertex2camera
+#define DEBUG_PBR_DOT_NV 0 // Output: grayscale dot(Normal ,Vertex2Camera)
+#define DEBUG_PBR_BRDF_UV 0 // Output: red green BRDF UV (GGX input)
+#define DEBUG_PBR_BRDF_SCALE_BIAS 0 // Output: red green BRDF Scale Bias (GGX output)
+#define DEBUG_PBR_BRDF_SCALE_ONLY 0 // Output: grayscale BRDF Scale
+#define DEBUG_PBR_BRDF_BIAS_ONLY 0 // Output: grayscale BRDER Bias
+#define DEBUG_PBR_FRESNEL 0 // Output: roughness dependent fresnel
+#define DEBUG_PBR_KSPEC 0 // Output: K spec
+#define DEBUG_PBR_REFLECTION_DIR 0 // Output: reflection dir
+#define DEBUG_PBR_SPEC_REFLECTION 0 // Output: environment reflection
+#define DEBUG_PBR_FSS_ESS_GGX 0 // Output: FssEssGGX
+#define DEBUG_PBR_SPEC 0 // Output: Final spec
+
+// IBL Diffuse
+#define DEBUG_PBR_DIFFUSE_C 0 // Output: diffuse non metal mix
+#define DEBUG_PBR_IRRADIANCE_RAW 0 // Output: Diffuse Irradiance pre-mix
+#define DEBUG_PBR_IRRADIANCE 0 // Output: Diffuse Irradiance
+#define DEBUG_PBR_FSS_ESS_LAMBERT 0 // Output: FssEssLambert
+#define DEBUG_PBR_EMS 0 // Output: Ems = (1 - BRDF Scale + BRDF Bias)
+#define DEBUG_PBR_AVG 0 // Output: Avg
+#define DEBUG_PBR_FMS_EMS 0 // Output: FmsEms
+#define DEBUG_PBR_DIFFUSE_K 0 // Output: diffuse FssEssLambert + FmsEms
+#define DEBUG_PBR_DIFFUSE_PRE_AO 0 // Output: diffuse pre AO
+#define DEBUG_PBR_DIFFUSE 0 // Output: diffuse post AO
+
+// Atmospheric Lighting
+#define DEBUG_PBR_AMBOCC 0 // Output: ambient occlusion
+#define DEBUG_PBR_DA_RAW 0 // Output: da pre pow()
+#define DEBUG_PBR_DA_POW 0 // Output: da post pow()
+#define DEBUG_PBR_SUN_LIT 0 // Ouput: sunlit
+#define DEBUG_PBR_SUN_CONTRIB 0 // Output: sun_contrib
+#define DEBUG_PBR_SKY_ADDITIVE 0 // Output: additive
+#define DEBUG_PBR_SKY_ATTEN 0 // Output: greyscale atten.r
+
+#define DEBUG_PBR_IOR 0 // Output: grayscale IOR
+#define DEBUG_PBR_REFLECT0_BASE 0 // Output: black reflect0 default from ior
+#define DEBUG_PBR_REFLECT0_MIX 0 // Output: diffuse reflect0 calculated from ior
+#define DEBUG_PBR_REFLECTANCE 0 // Output: diffuse reflectance -- NOT USED
+#define DEBUG_PBR_SPEC_WEIGHT 0 // Output: specWeight
+#define DEBUG_PBR_V2C_REMAP 0 // Output: vertex2camera (remap [-1,1] -> [0,1])
#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
+
+#define FLT_MAX 3.402823466e+38
-/*[EXTRA_CODE_HERE]*/
+#define REFMAP_COUNT 256
+#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
@@ -36,142 +108,448 @@ out vec4 frag_color;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
+uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+
+#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
uniform sampler2DRect lightMap;
+#endif
+
uniform sampler2DRect depthMap;
uniform sampler2D lightFunc;
-uniform samplerCube environmentMap;
uniform float blur_size;
uniform float blur_fidelity;
// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform float cloud_shadow;
-uniform float max_y;
-uniform vec4 glow;
uniform mat3 env_mat;
-uniform vec4 shadow_clip;
uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform int sun_up_factor;
VARYING vec2 vary_fragcoord;
uniform mat4 inv_proj;
-uniform mat4 inv_modelview;
-
uniform vec2 screen_res;
-uniform sampler2D transmittance_texture;
-uniform sampler3D scattering_texture;
-uniform sampler3D single_mie_scattering_texture;
-uniform sampler2D irradiance_texture;
+vec3 getNorm(vec2 pos_screen);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-uniform sampler2D sh_input_r;
-uniform sampler2D sh_input_g;
-uniform sampler2D sh_input_b;
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+float getAmbientClamp();
+vec2 getGGX( vec2 brdfPoint );
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
-vec3 GetSunAndSkyIrradiance(vec3 camPos, vec3 norm, vec3 dir, out vec3 sky_irradiance);
-vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
-vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
+// 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 ColorFromRadiance(vec3 radiance);
-vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+vec3 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
#ifdef WATER_FOG
vec4 applyWaterFogView(vec3 pos, vec4 color);
#endif
-void main()
+uniform vec3 view_dir; // PBR
+
+vec3 calcBaseReflect0(float ior)
{
- vec2 tc = vary_fragcoord.xy;
- float depth = texture2DRect(depthMap, tc.xy).r;
- vec3 pos = getPositionWithDepth(tc, depth).xyz;
- vec4 norm = texture2DRect(normalMap, tc);
+ vec3 reflect0 = vec3(pow((ior - 1.0) / (ior + 1.0), 2.0));
+ return reflect0;
+}
+
+void main()
+{
+ vec2 tc = vary_fragcoord.xy;
+ float depth = texture2DRect(depthMap, tc.xy).r;
+ vec4 pos = getPositionWithDepth(tc, depth);
+ vec4 norm = texture2DRect(normalMap, tc);
float envIntensity = norm.z;
- norm.xyz = getNorm(tc);
+ norm.xyz = getNorm(tc);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+ float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
+#if DEBUG_PBR_DA_RAW
+ float debug_da = da;
+#endif
+ float light_gamma = 1.0 / 1.3;
+ da = pow(da, light_gamma);
- float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
+ vec4 diffuse = texture2DRect(diffuseRect, tc);
+ vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); // NOTE: PBR sRGB Emissive
- vec4 diffuse = texture2DRect(diffuseRect, tc); // sRGB
- diffuse.rgb = srgb_to_linear(diffuse.rgb);
+#if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO)
+ vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+ scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+ float scol = max(scol_ambocc.r, diffuse.a);
+ float ambocc = scol_ambocc.g;
+#else
+ float scol = 1.0;
+ float ambocc = 1.0;
+#endif
- vec3 col;
+ vec3 color = vec3(0);
float bloom = 0.0;
+
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
+
+ //vec3 amb_vec = env_mat * norm.xyz;
+
+ vec3 ambenv;
+ vec3 glossenv;
+ vec3 legacyenv;
+
+ bool hasPBR = GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR);
+ if (hasPBR)
+ {
+ // 5.22.2. material.pbrMetallicRoughness.baseColorTexture
+ // The first three components (RGB) MUST be encoded with the sRGB transfer function.
+ //
+ // 5.19.7. material.emissiveTexture
+ // This texture contains RGB components encoded with the sRGB transfer function.
+ //
+ // 5.22.5. material.pbrMetallicRoughness.metallicRoughnessTexture
+ // These values MUST be encoded with a linear transfer function.
+
+ vec3 colorDiffuse = vec3(0);
+ vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
+ vec3 colorSpec = vec3(0);
+// vec3 colorClearCoat = vec3(0);
+// vec3 colorSheen = vec3(0);
+// vec3 colorTransmission = vec3(0);
+
+ vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+#if DEBUG_PBR_PACK_ORM0
+ packedORM = vec3(0,0,0);
+#endif
+#if DEBUG_PBR_PACK_ORM1
+ packedORM = vec3(1,1,1);
+#endif
+ float IOR = 1.5; // default Index Of Refraction 1.5 (dielectrics)
+ vec3 reflect0 = vec3(0.04); // -> incidence reflectance 0.04
+#if HAS_IOR
+ reflect0 = calcBaseReflect0(IOR);
+#endif
+#if DEBUG_PBR_REFLECT0_BASE
+ vec3 debug_reflect0 = reflect0;
+#endif
+
+ float metal = packedORM.b;
+ vec3 c_diff = mix(diffuse.rgb,vec3(0),metal);
+ vec3 reflect90 = vec3(0);
+ vec3 v = -normalize(pos.xyz);
+#if DEBUG_PBR_VERT2CAM1
+ v = vec3(0,0,1);
+#endif
+ vec3 n = norm.xyz;
+// vec3 t = texture2DRect(tangentMap, tc).rgb;
+#if DEBUG_PBR_TANGENT1
+ vec3 t = vec3(1,0,0);
+#endif
+ vec3 b = cross( n,t);
+ vec3 reflectVN = normalize(reflect(-v,n));
+
+ float dotNV = clamp(dot(n,v),0,1);
+ float dotTV = clamp(dot(t,v),0,1);
+ float dotBV = clamp(dot(b,v),0,1);
+
+ // Reference: getMetallicRoughnessInfo
+ float perceptualRough = packedORM.g;
+ float alphaRough = perceptualRough * perceptualRough;
+ vec3 colorDiff = mix( diffuse.rgb, vec3(0) , metal);
+ reflect0 = mix( reflect0 , diffuse.rgb, metal); // reflect at 0 degrees
+ reflect90 = vec3(1); // reflect at 90 degrees
+#if DEBUG_PBR_REFLECTANCE
+ float reflectance = max( max( reflect0.r, reflect0.g ), reflect0.b );
+#endif
+
+ // Common to RadianceGGX and RadianceLambertian
+ float specWeight = 1.0;
+ vec2 brdfPoint = clamp(vec2(dotNV, perceptualRough), vec2(0,0), vec2(1,1));
+ vec2 vScaleBias = getGGX( brdfPoint); // Environment BRDF: scale and bias applied to reflect0
+ vec3 fresnelR = max(vec3(1.0 - perceptualRough), reflect0) - reflect0; // roughness dependent fresnel
+ vec3 kSpec = reflect0 + fresnelR*pow(1.0 - dotNV, 5.0);
+
+ // Reference: getIBLRadianceGGX
+ // https://forum.substance3d.com/index.php?topic=3243.0
+ // Glossiness
+ // This map is the inverse of the roughness map.
+ vec3 irradiance = vec3(0);
+ vec3 specLight = vec3(0);
+ float gloss = 1.0 - perceptualRough;
+ sampleReflectionProbes(irradiance, specLight, legacyenv, pos.xyz, norm.xyz, gloss, 0.0);
+#if DEBUG_PBR_IRRADIANCE_RAW
+ vec3 debug_irradiance = irradiance;
+#endif
+ irradiance = max(amblit,irradiance);
+#if PBR_USE_IRRADIANCE_HACK
+ irradiance += amblit*0.5*vec3(dot(n, light_dir));
+#endif
+ specLight = srgb_to_linear(specLight);
+#if DEBUG_PBR_SPECLIGHT051
+ specLight = vec3(0,0.5,1.0);
+ irradiance = specLight;
+#endif
+#if HAS_IBL
+ kSpec = mix( kSpec, iridescenceFresnel, iridescenceFactor);
+#endif
+ vec3 FssEssGGX = kSpec*vScaleBias.x + vScaleBias.y;
+ colorSpec += specWeight * specLight * FssEssGGX;
+
+ // Reference: getIBLRadianceLambertian
+ vec3 FssEssLambert = specWeight * kSpec * vScaleBias.x + vScaleBias.y; // NOTE: Very similar to FssEssRadiance but with extra specWeight term
+ float Ems = 1.0 - (vScaleBias.x + vScaleBias.y);
+ vec3 avg = specWeight * (reflect0 + (1.0 - reflect0) / 21.0);
+ vec3 AvgEms = avg * Ems;
+ vec3 FmsEms = AvgEms * FssEssLambert / (1.0 - AvgEms);
+ vec3 kDiffuse = c_diff * (1.0 - FssEssLambert + FmsEms);
+ colorDiffuse += (FmsEms + kDiffuse) * irradiance;
+ #if DEBUG_PBR_DIFFUSE_PRE_AO
+ vec3 debug_diffuse = colorDiffuse;
+ #endif
+ colorDiffuse *= packedORM.r; // Occlusion -- NOTE: pbropaque will need occlusion_strength pre-multiplied into spec.r
+
+ color.rgb = colorDiffuse + colorEmissive + colorSpec;
+
+ vec3 sun_contrib = min(da, scol) * sunlit;
+#if PBR_USE_ATMOS
+ color = linear_to_srgb(color);
+ color += 2.0*sun_contrib; // 2x = Undo legacy hack of calcAtmosphericVars() returning sunlight.rgb * 0.5;
+ color *= atten.r;
+ color += 2.0*additive;
+ color = scaleSoftClipFrag(color);
+ color = srgb_to_linear(color);
+#endif // PBR_USE_ATMOS
+
+ #if DEBUG_PBR_DIFFUSE
+ color.rgb = colorDiffuse;
+ #endif
+ #if DEBUG_PBR_EMISSIVE
+ color.rgb = colorEmissive;
+ #endif
+ #if DEBUG_PBR_METAL
+ color.rgb = vec3(metal);
+ #endif
+ #if DEBUG_PBR_NORMAL_MAP
+ color.rgb = diffuse.rgb;
+ #endif
+ #if DEBUG_PBR_OCCLUSION
+ color.rgb = vec3(packedORM.r);
+ #endif
+ #if DEBUG_PBR_ORM
+ color.rgb = packedORM;
+ #endif
+ #if DEBUG_PBR_ROUGH_PERCEPTUAL
+ color.rgb = vec3(perceptualRough);
+ #endif
+ #if DEBUG_PBR_ROUGH_ALPHA
+ color.rgb = vec3(alphaRough);
+ #endif
+
+ #if DEBUG_PBR_NORMAL
+ color.rgb = norm.xyz*0.5 + vec3(0.5);
+ color.rgb = srgb_to_linear(color.rgb);
+ #endif
+ #if DEBUG_PBR_TANGENT
+ color.rgb = t;
+ #endif
+ #if DEBUG_PBR_BITANGENT
+ color.rgb = b;
+ #endif
+ #if DEBUG_PBR_DOT_NV
+ color.rgb = vec3(dotNV);
+ #endif
+ #if DEBUG_PBR_DOT_TV
+ color.rgb = vec3(dotTV);
+ #endif
+ #if DEBUG_PBR_DOT_BV
+ color.rgb = vec3(dotBV);
+ #endif
+
+ #if DEBUG_PBR_AVG
+ color.rgb = avg;
+ #endif
+ #if DEBUG_PBR_BRDF_UV
+ color.rgb = vec3(brdfPoint,0.0);
+ color.rgb = linear_to_srgb(color.rgb);
+ #endif
+ #if DEBUG_PBR_BRDF_SCALE_BIAS
+ color.rgb = vec3(vScaleBias,0.0);
+ #endif
+ #if DEBUG_PBR_DIFFUSE_C
+ color.rgb = c_diff;
+ #endif
+ #if DEBUG_PBR_BRDF_SCALE_ONLY
+ color.rgb = vec3(vScaleBias.x);
+ #endif
+ #if DEBUG_PBR_BRDF_BIAS_ONLY
+ color.rgb = vec3(vScaleBias.y);
+ #endif
+ #if DEBUG_PBR_DIFFUSE_K
+ color.rgb = kDiffuse;
+ #endif
+ #if DEBUG_PBR_DIFFUSE_MAP
+ color.rgb = diffuse.rgb;
+ #endif
+ #if DEBUG_PBR_DIFFUSE_PRE_AO
+ color.rgb = debug_diffuse;
+ #endif
+ #if DEBUG_PBR_EMS
+ color.rgb = vec3(Ems);
+ #endif
+ #if DEBUG_PBR_EMS_AVG
+ color.rgb = AvgEms;
+ #endif
+ #if DEBUG_PBR_FMS_EMS
+ color.rgb = FmsEms;
+ #endif
+ #if DEBUG_PBR_FSS_ESS_GGX
+ color.rgb = FssEssGGX; // spec
+ #endif
+ #if DEBUG_PBR_FSS_ESS_LAMBERT
+ color.rgb = FssEssLambert; // diffuse
+ #endif
+ #if DEBUG_PBR_FRESNEL
+ color.rgb = fresnelR;
+ #endif
+ #if DEBUG_PBR_IOR
+ color.rgb = vec3(IOR);
+ #endif
+ #if DEBUG_PBR_IRRADIANCE_RAW
+ color.rgb = debug_irradiance;
+ #endif
+ #if DEBUG_PBR_IRRADIANCE
+ color.rgb = irradiance;
+ #endif
+ #if DEBUG_PBR_KSPEC
+ color.rgb = kSpec;
+ #endif
+ #if DEBUG_PBR_REFLECT0_BASE
+ color.rgb = vec3(debug_reflect0);
+ #endif
+ #if DEBUG_PBR_REFLECT0_MIX
+ color.rgb = vec3(reflect0);
+ #endif
+ #if DEBUG_PBR_REFLECTANCE
+ color.rgb = vec3(reflectance);
+ #endif
+ #if DEBUG_PBR_REFLECTION_DIR
+ color.rgb = reflect(-v, n); // NOTE: equivalent to normalize(reflect(pos.xyz, norm.xyz));
+ #endif
+ #if DEBUG_PBR_SPEC
+ color.rgb = colorSpec;
+ #endif
+ #if DEBUG_PBR_SPEC_REFLECTION
+ color.rgb = specLight;
+ #endif
+ #if DEBUG_PBR_SPEC_WEIGHT
+ color.rgb = vec3(specWeight);
+ #endif
+ #if DEBUG_PBR_V2C_RAW
+ color.rgb = v;
+ #endif
+ #if DEBUG_PBR_V2C_REMAP
+ color.rgb = v*0.5 + vec3(0.5);
+ #endif
+
+ #if DEBUG_PBR_AMBOCC
+ color.rgb = vec3(ambocc);
+ #endif
+ #if DEBUG_PBR_DA_RAW
+ color.rgb = vec3(debug_da);
+ #endif
+ #if DEBUG_PBR_DA_POW
+ color.rgb = vec3(da);
+ #endif
+ #if DEBUG_PBR_SKY_ADDITIVE
+ color.rgb = additive;
+ #endif
+ #if DEBUG_PBR_SKY_ATTEN
+ color.rgb = vec3(atten.r);
+ #endif
+ #if DEBUG_PBR_SUN_LIT
+ color.rgb = sunlit;
+ #endif
+ #if DEBUG_PBR_SUN_CONTRIB
+ color.rgb = sun_contrib;
+ #endif
+ #if DEBUG_PBR_LIGHT_TYPE
+ color.rgb = vec3(0);
+ #endif
+ frag_color.rgb = color.rgb; // PBR is done in linear
+ }
+else
+{
+ diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035
+
+ sampleReflectionProbes(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity);
+
+ amblit = max(ambenv, amblit);
+ color.rgb = amblit*ambocc;
+
+ //float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ //ambient *= 0.5;
+ //ambient *= ambient;
+ //ambient = (1.0 - ambient);
+ //color.rgb *= ambient;
+
+ vec3 sun_contrib = min(da, scol) * sunlit;
+ color.rgb += sun_contrib;
+ color.rgb = min(color.rgb, vec3(1,1,1));
+ color.rgb *= diffuse.rgb;
+
+ vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
+
+ if (spec.a > 0.0) // specular reflection
{
- vec3 camPos = (camPosLocal / 1000.0f) + vec3(0, 0, 6360.0f);
-
- vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
-
- float scol = max(scol_ambocc.r, diffuse.a);
-
- float ambocc = scol_ambocc.g;
-
- vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
- vec4 l1r = texture2D(sh_input_r, vec2(0,0));
- vec4 l1g = texture2D(sh_input_g, vec2(0,0));
- vec4 l1b = texture2D(sh_input_b, vec2(0,0));
-
- vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
- dot(l1g, l1tap * vec4(1, norm.xyz)),
- dot(l1b, l1tap * vec4(1, norm.xyz)));
-
- indirect = clamp(indirect, vec3(0), vec3(1.0));
-
- vec3 transmittance;
- vec3 sky_irradiance;
- vec3 sun_irradiance = GetSunAndSkyIrradiance(camPos, norm.xyz, sun_dir, sky_irradiance);
- vec3 inscatter = GetSkyLuminanceToPoint(camPos, (pos / 1000.f) + vec3(0, 0, 6360.0f), scol, sun_dir, transmittance);
-
- vec3 radiance = scol * (sun_irradiance + sky_irradiance) + inscatter;
- vec3 atmo_color = ColorFromRadiance(radiance);
-
- col = atmo_color + indirect;
- col *= transmittance;
- col *= diffuse.rgb;
-
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
- if (spec.a > 0.0) // specular reflection
- {
- // the old infinite-sky shiny reflection
- //
- float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = scol * texture2D(lightFunc, vec2(sa, spec.a)).r * atmo_color;
-
- // add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb * 0.25;
- bloom = dot(spec_contrib, spec_contrib);
- col += spec_contrib;
- }
-
- col = mix(col, diffuse.rgb, diffuse.a);
-
- if (envIntensity > 0.0)
- { //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
- vec3 sun_direction = (inv_modelview * vec4(sun_dir, 1.0)).xyz;
- vec3 radiance_sun = GetSkyLuminance(camPos, env_vec, 0.0f, sun_direction, transmittance);
- vec3 refcol = ColorFromRadiance(radiance_sun);
- col = mix(col.rgb, refcol, envIntensity);
- }
-
- /*if (norm.w < 0.5)
- {
- col = scaleSoftClipFrag(col);
- }*/
-
- #ifdef WATER_FOG
- vec4 fogged = applyWaterFogView(pos,vec4(col, bloom));
- col = fogged.rgb;
- bloom = fogged.a;
- #endif
+ float sa = dot(normalize(refnormpersp), light_dir.xyz);
+ vec3 dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+ color.rgb += spec_contrib;
+
+ // add reflection map - EXPERIMENTAL WORK IN PROGRESS
+ applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz);
}
- //output linear since gamma correction happens down stream
- frag_color.rgb = col;
+ color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
+
+ if (envIntensity > 0.0)
+ { // add environmentmap
+ //fudge darker
+ legacyenv *= 0.5*diffuse.a+0.5;;
+ applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
+ }
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
+ {
+ color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
+ color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
+ }
+
+#ifdef WATER_FOG
+ vec4 fogged = applyWaterFogView(pos.xyz, vec4(color, bloom));
+ color = fogged.rgb;
+ bloom = fogged.a;
+#endif
+ // 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.b = diffuse.a;
+ frag_color.rgb = srgb_to_linear(color.rgb);
+}
frag_color.a = bloom;
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
deleted file mode 100644
index 9d872b8df8..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @file class3/deferred/softenLightV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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$
- */
-ATTRIBUTE vec3 position;
-
-VARYING vec2 vary_fragcoord;
-
-uniform mat4 modelview_projection_matrix;
-uniform vec2 screen_res;
-
-void main()
-{
- //transform vertex
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- gl_Position = pos;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
index 56b0f4e5ce..a82581d1a1 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -1,9 +1,9 @@
/**
- * @file spotLightF.glsl
+ * @file class3\deferred\spotLightF.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -28,6 +28,12 @@
/*[EXTRA_CODE_HERE]*/
+#define DEBUG_PBR_LIGHT_TYPE 0
+#define DEBUG_PBR_SPOT 0
+#define DEBUG_PBR_NL 0 // monochome area effected by light
+#define DEBUG_PBR_SPOT_DIFFUSE 0
+#define DEBUG_PBR_SPOT_SPECULAR 0
+
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
@@ -38,10 +44,11 @@ uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
+uniform sampler2DRect emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
uniform samplerCube environmentMap;
uniform sampler2DRect lightMap;
uniform sampler2D noiseMap;
-uniform sampler2D projectionMap;
+uniform sampler2D projectionMap; // rgba
uniform sampler2D lightFunc;
uniform mat4 proj_mat; //screen space to light space
@@ -71,217 +78,224 @@ uniform vec2 screen_res;
uniform mat4 inv_proj;
-vec3 getNorm(vec2 pos_screen);
-
-vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- d *= min(1, d * (proj_lod - lod));
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
-
-vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
-{
- vec4 ret = texture2DLod(projectionMap, tc, lod);
-
- vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-
- float det = min(lod/(proj_lod*0.5), 1.0);
-
- float d = min(dist.x, dist.y);
-
- float edge = 0.25*det;
-
- ret *= clamp(d/edge, 0.0, 1.0);
-
- return ret;
-}
+vec3 BRDFLambertian( vec3 reflect0, vec3 reflect90, vec3 c_diff, float specWeight, float vh );
+vec3 BRDFSpecularGGX( vec3 reflect0, vec3 reflect90, float alphaRoughness, float specWeight, float vh, float nl, float nv, float nh );
+void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
+bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc );
+vec3 getLightIntensitySpot(vec3 lightColor, float lightRange, float lightDistance, vec3 v);
+vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
+vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv );
+vec3 getProjectedLightSpecularColor(vec3 pos, vec3 n);
+vec2 getScreenXY(vec4 clip_point);
+void initMaterial( vec3 diffuse, vec3 packedORM, out float alphaRough, out vec3 c_diff, out vec3 reflect0, out vec3 reflect90, out float specWeight );
+vec3 srgb_to_linear(vec3 c);
+vec4 texture2DLodSpecular(vec2 tc, float lod);
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
{
vec4 ret = texture2DLod(projectionMap, tc, lod);
-
+ ret.rgb = srgb_to_linear(ret.rgb);
+
vec2 dist = tc-vec2(0.5);
-
float d = dot(dist,dist);
-
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
-
+
return ret;
}
-
vec4 getPosition(vec2 pos_screen);
-void main()
+void main()
{
- vec4 frag = vary_fragcoord;
- frag.xyz /= frag.w;
- frag.xyz = frag.xyz*0.5+0.5;
- frag.xy *= screen_res;
-
- vec3 pos = getPosition(frag.xy).xyz;
- vec3 lv = trans_center.xyz-pos.xyz;
- float dist = length(lv);
- dist /= size;
- if (dist > 1.0)
+#if defined(LOCAL_LIGHT_KILL)
+ discard;
+#else
+ vec3 final_color = vec3(0,0,0);
+ vec2 tc = getScreenXY(vary_fragcoord);
+ vec3 pos = getPosition(tc).xyz;
+
+ vec3 lv;
+ vec4 proj_tc;
+ float dist, l_dist;
+ if (clipProjectedLightVars(trans_center, pos, dist, l_dist, lv, proj_tc))
{
discard;
}
-
+
float shadow = 1.0;
-
+
if (proj_shadow_idx >= 0)
{
- vec4 shd = texture2DRect(lightMap, frag.xy);
+ vec4 shd = texture2DRect(lightMap, tc);
shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
shadow += shadow_fade;
shadow = clamp(shadow, 0.0, 1.0);
}
-
- vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
- float envIntensity = norm.z;
- norm = getNorm(frag.xy);
-
- norm = normalize(norm);
- float l_dist = -dot(lv, proj_n);
-
- vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
- if (proj_tc.z < 0.0)
- {
- discard;
- }
-
- proj_tc.xyz /= proj_tc.w;
-
- float fa = (falloff*0.5) + 1.0;
- float dist_atten = min(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0;
-
- if (dist_atten <= 0.0)
+
+ float envIntensity;
+ vec3 n;
+ vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
+
+ float dist_atten = 1.0 - (dist + falloff)/(1.0 + falloff);
+
+ lv = proj_origin-pos.xyz; // NOTE: Re-using lv
+ vec3 h, l, v = -normalize(pos);
+ float nh, nl, nv, vh, lightDist;
+ calcHalfVectors(lv, n, v, h, l, nh, nl, nv, vh, lightDist);
+
+ vec3 diffuse = texture2DRect(diffuseRect, tc).rgb;
+ vec4 spec = texture2DRect(specularRect, tc);
+ vec3 dlit = vec3(0, 0, 0);
+ vec3 slit = vec3(0, 0, 0);
+
+ if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
{
- discard;
+ vec3 colorDiffuse = vec3(0);
+ vec3 colorSpec = vec3(0);
+ vec3 colorEmissive = spec.rgb; // PBR sRGB Emissive. See: pbropaqueF.glsl
+ vec3 packedORM = texture2DRect(emissiveRect, tc).rgb; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+ float metal = packedORM.b;
+
+// if (proj_tc.x > 0.0 && proj_tc.x < 1.0
+// && proj_tc.y > 0.0 && proj_tc.y < 1.0)
+ if (nl > 0.0)
+ {
+ vec3 c_diff, reflect0, reflect90;
+ float alphaRough, specWeight;
+ initMaterial( diffuse, packedORM, alphaRough, c_diff, reflect0, reflect90, specWeight );
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+ slit = getProjectedLightSpecularColor( pos, n );
+
+// vec3 intensity = getLightIntensitySpot( color, size, lightDist, v );
+// colorDiffuse = shadow * dlit * nl;
+// colorSpec = shadow * slit * nl;
+
+// colorDiffuse *= BRDFLambertian ( reflect0, reflect90, c_diff , specWeight, vh );
+// colorSpec *= BRDFSpecularGGX( reflect0, reflect90, alphaRough, specWeight, vh, nl, nv, nh );
+
+ colorDiffuse = shadow * dlit * nl * dist_atten;
+ colorSpec = shadow * slit * nl * dist_atten;
+
+ #if DEBUG_PBR_SPOT_DIFFUSE
+ colorDiffuse = dlit.rgb; colorSpec = vec3(0);
+ #endif
+ #if DEBUG_PBR_SPOT_SPECULAR
+ colorDiffuse = vec3(0); colorSpec = slit.rgb;
+ #endif
+ #if DEBUG_PBR_SPOT
+ colorDiffuse = dlit; colorSpec = vec3(0);
+ colorDiffuse *= nl;
+ colorDiffuse *= shadow;
+ #endif
+
+ }
+
+ #if DEBUG_SPOT_DIFFUSE
+ colorDiffuse = vec3(nl * dist_atten);
+ #endif
+ #if DEBUG_PBR_NL
+ colorDiffuse = vec3(nl); colorSpec = vec3(0);
+ #endif
+ #if DEBUG_PBR_LIGHT_TYPE
+ colorDiffuse = vec3(0.5,0,0); colorSpec = vec3(0.0);
+ #endif
+
+ final_color = colorDiffuse + colorSpec;
}
-
- lv = proj_origin-pos.xyz;
- lv = normalize(lv);
- float da = dot(norm, lv);
-
- vec3 col = vec3(0,0,0);
-
- vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
-
- vec4 spec = texture2DRect(specularRect, frag.xy);
-
- vec3 dlit = vec3(0, 0, 0);
-
- float noise = texture2D(noiseMap, frag.xy/128.0).b;
- if (proj_tc.z > 0.0 &&
- proj_tc.x < 1.0 &&
- proj_tc.y < 1.0 &&
- proj_tc.x > 0.0 &&
- proj_tc.y > 0.0)
+ else
{
- float amb_da = proj_ambiance;
- float lit = 0.0;
-
- if (da > 0.0)
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0;
+
+ if (dist_atten <= 0.0)
{
- lit = da * dist_atten * noise;
-
- float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
- float lod = diff * proj_lod;
-
- vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
-
- dlit = color.rgb * plcol.rgb * plcol.a;
-
- col = dlit*lit*diff_tex*shadow;
- amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+ discard;
}
-
- //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
- vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
-
- amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
-
- amb_da *= dist_atten * noise;
-
- amb_da = min(amb_da, 1.0-lit);
-
- col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
- }
-
- if (spec.a > 0.0)
- {
- dlit *= min(da*6.0, 1.0) * dist_atten;
- vec3 npos = -normalize(pos);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv+npos);
- float nh = dot(norm, h);
- float nv = dot(norm, 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 noise = texture2D(noiseMap, tc/128.0).b;
+ if (proj_tc.z > 0.0 &&
+ proj_tc.x < 1.0 &&
+ proj_tc.y < 1.0 &&
+ proj_tc.x > 0.0 &&
+ proj_tc.y > 0.0)
{
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
- col += dlit*scol*spec.rgb*shadow;
+ float amb_da = proj_ambiance;
+ float lit = 0.0;
+
+ if (nl > 0.0)
+ {
+ lit = nl * dist_atten * noise;
+
+ dlit = getProjectedLightDiffuseColor( l_dist, proj_tc.xy );
+
+ final_color = dlit*lit*diffuse*shadow;
+
+ amb_da += (nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ }
+
+ //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+ vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+ amb_da += (nl*nl*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+ amb_da *= dist_atten * noise;
+ amb_da = min(amb_da, 1.0-lit);
+
+ final_color += amb_da*color.rgb*diffuse.rgb*amb_plcol.rgb*amb_plcol.a;
}
- }
-
- if (envIntensity > 0.0)
- {
- vec3 ref = reflect(normalize(pos), norm);
-
- //project from point pos in direction ref to plane proj_p, proj_n
- vec3 pdelta = proj_p-pos;
- float ds = dot(ref, proj_n);
-
- if (ds < 0.0)
+ if (spec.a > 0.0)
{
- vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
-
- vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+ dlit *= min(nl*6.0, 1.0) * dist_atten;
+ float fres = pow(1 - dot(h, v), 5)*0.4+0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * nl / vh));
- if (stc.z > 0.0)
+ if (nh > 0.0)
{
- stc /= stc.w;
-
- if (stc.x < 1.0 &&
- stc.y < 1.0 &&
- stc.x > 0.0 &&
- stc.y > 0.0)
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*nl);
+ vec3 speccol = dlit*scol*spec.rgb*shadow;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ final_color += speccol;
+ }
+ }
+
+ if (envIntensity > 0.0)
+ {
+ vec3 ref = reflect(normalize(pos), n);
+
+ //project from point pos in direction ref to plane proj_p, proj_n
+ vec3 pdelta = proj_p-pos;
+ float ds = dot(ref, proj_n);
+
+ if (ds < 0.0)
+ {
+ vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+
+ vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+ if (stc.z > 0.0)
{
- col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ stc /= stc.w;
+
+ if (stc.x < 1.0 &&
+ stc.y < 1.0 &&
+ stc.x > 0.0 &&
+ stc.y > 0.0)
+ {
+ final_color += color.rgb * texture2DLodSpecular(stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+ }
}
}
}
}
-
+
//not sure why, but this line prevents MATBUG-194
- col = max(col, vec3(0.0));
+ final_color = max(final_color, vec3(0.0));
- frag_color.rgb = col;
+ //output linear colors as gamma correction happens down stream
+ frag_color.rgb = final_color;
frag_color.a = 0.0;
+#endif // LOCAL_LIGHT_KILL
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
deleted file mode 100644
index 112b498c90..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * @file class3\deferred\sunLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-//class 2, shadows, no SSAO
-
-// Inputs
-VARYING vec2 vary_fragcoord;
-
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
-
-void main()
-{
- vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = getPosition(pos_screen);
- vec3 norm = getNorm(pos_screen);
-
- frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
- frag_color.g = 1.0f;
- frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
- frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
deleted file mode 100644
index 342a2ff3ed..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * @file class3\deferred\sunLightSSAOF.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-//class 2 -- shadows and SSAO
-
-// Inputs
-VARYING vec2 vary_fragcoord;
-
-uniform vec3 sun_dir;
-
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
-
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
-
-void main()
-{
- vec2 pos_screen = vary_fragcoord.xy;
- vec4 pos = getPosition(pos_screen);
- vec3 norm = getNorm(pos_screen);
-
- frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
- frag_color.b = calcAmbientOcclusion(pos, norm, pos_screen);
- frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
- frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl
deleted file mode 100644
index 41673d1669..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * @file treeShadowF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, 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 float minimum_alpha;
-
-uniform sampler2D diffuseMap;
-
-VARYING vec4 pos;
-VARYING vec2 vary_texcoord0;
-
-vec4 computeMoments(float d, float a);
-
-void main()
-{
- float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
-
- if (alpha < minimum_alpha)
- {
- discard;
- }
-
- frag_color = computeMoments(length(pos), 1.0);
-
-#if !defined(DEPTH_CLAMP)
- gl_FragDepth = max(pos.z/pos.w*0.5+0.5, 0.0);
-#endif
-
-}
-
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
deleted file mode 100644
index 15e769ac10..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * @file treeShadowV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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 texture_matrix0;
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec4 pos;
-VARYING vec2 vary_texcoord0;
-
-void main()
-{
- //transform vertex
- pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
- gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl
deleted file mode 100644
index 540226e672..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * @file underWaterF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-uniform sampler2D diffuseMap;
-uniform sampler2D bumpMap;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-uniform sampler2D screenDepth;
-
-uniform vec4 fogCol;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform vec2 fbScale;
-uniform float refScale;
-uniform float znear;
-uniform float zfar;
-uniform float kd;
-uniform vec4 waterPlane;
-uniform vec3 eyeVec;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-uniform vec2 screenRes;
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-vec2 encode_normal(vec3 n);
-
-vec4 applyWaterFog(vec4 color, vec3 viewVec)
-{
- //normalize view vector
- vec3 view = normalize(viewVec);
- float es = -view.z;
-
- //find intersection point with water plane and eye vector
-
- //get eye depth
- float e0 = max(-waterPlane.w, 0.0);
-
- //get object depth
- float depth = length(viewVec);
-
- //get "thickness" of water
- float l = max(depth, 0.1);
-
- float kd = waterFogDensity;
- float ks = waterFogKS;
- vec4 kc = waterFogColor;
-
- float F = 0.98;
-
- float t1 = -kd * pow(F, ks * e0);
- float t2 = kd + ks * es;
- float t3 = pow(F, t2*l) - 1.0;
-
- float L = min(t1/t2*t3, 1.0);
-
- float D = pow(0.98, l*kd);
- return color * D + kc * L;
-}
-
-void main()
-{
- vec4 color;
-
- //get detail normals
- vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
- vec3 wavef = normalize(wave1+wave2+wave3);
-
- //figure out distortion vector (ripply)
- vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
- distort = distort+wavef.xy*refScale;
-
- vec4 fb = texture2D(screenTex, distort);
-
- frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
- frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
- frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl
deleted file mode 100644
index c65cf48c67..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl
+++ /dev/null
@@ -1,174 +0,0 @@
-/**
- * @file waterF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-uniform sampler2D bumpMap;
-uniform sampler2D bumpMap2;
-uniform float blend_factor;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-
-uniform float sunAngle;
-uniform float sunAngle2;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform float refScale;
-uniform float kd;
-uniform vec2 screenRes;
-uniform vec3 normScale;
-uniform float fresnelScale;
-uniform float fresnelOffset;
-uniform float blurMultiplier;
-uniform vec2 screen_res;
-uniform mat4 norm_mat; //region space to screen space
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-VARYING vec4 vary_position;
-
-vec3 scaleSoftClip(vec3 c);
-vec2 encode_normal(vec3 n);
-
-vec3 BlendNormal(vec3 bump1, vec3 bump2)
-{
- //vec3 normal = bump1.xyz * vec3( 2.0, 2.0, 2.0) - vec3(1.0, 1.0, 0.0);
- //vec3 normal2 = bump2.xyz * vec3(-2.0, -2.0, 2.0) + vec3(1.0, 1.0, -1.0);
- //vec3 n = normalize(normal * dot(normal, normal2) - (normal2 * normal.z));
- vec3 n = normalize(mix(bump1, bump2, blend_factor));
- return n;
-}
-
-void main()
-{
- vec4 color;
- float dist = length(view.xy);
-
- //normalize view vector
- vec3 viewVec = normalize(view.xyz);
-
- //get wave normals
- vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-
-
- vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
- vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
- vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
-
- vec3 wave1 = BlendNormal(wave1_a, wave1_b);
- vec3 wave2 = BlendNormal(wave2_a, wave2_b);
- vec3 wave3 = BlendNormal(wave3_a, wave3_b);
-
- //get base fresnel components
-
- vec3 df = vec3(
- dot(viewVec, wave1),
- dot(viewVec, (wave2 + wave3) * 0.5),
- dot(viewVec, wave3)
- ) * fresnelScale + fresnelOffset;
- df *= df;
-
- vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-
- float dist2 = dist;
- dist = max(dist, 5.0);
-
- float dmod = sqrt(dist);
-
- vec2 dmod_scale = vec2(dmod*dmod, dmod);
-
- //get reflected color
- vec2 refdistort1 = wave1.xy*normScale.x;
- vec2 refvec1 = distort+refdistort1/dmod_scale;
- vec4 refcol1 = texture2D(refTex, refvec1);
-
- vec2 refdistort2 = wave2.xy*normScale.y;
- vec2 refvec2 = distort+refdistort2/dmod_scale;
- vec4 refcol2 = texture2D(refTex, refvec2);
-
- vec2 refdistort3 = wave3.xy*normScale.z;
- vec2 refvec3 = distort+refdistort3/dmod_scale;
- vec4 refcol3 = texture2D(refTex, refvec3);
-
- vec4 refcol = refcol1 + refcol2 + refcol3;
- float df1 = df.x + df.y + df.z;
- refcol *= df1 * 0.333;
-
- vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
- wavef.z *= max(-viewVec.z, 0.1);
- wavef = normalize(wavef);
-
- float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-
- vec2 refdistort4 = wavef.xy*0.125;
- refdistort4.y -= abs(refdistort4.y);
- vec2 refvec4 = distort+refdistort4/dmod;
- float dweight = min(dist2*blurMultiplier, 1.0);
- vec4 baseCol = texture2D(refTex, refvec4);
-
- refcol = mix(baseCol*df2, refcol, dweight);
-
- //get specular component
- float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
-
- //harden specular
- spec = pow(spec, 128.0);
-
- //figure out distortion vector (ripply)
- vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
-
- vec4 fb = texture2D(screenTex, distort2);
-
- //mix with reflection
- // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
- color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
-
- color.rgb *= 2.0f;
- color.rgb = scaleSoftClip(color.rgb);
-
- vec4 pos = vary_position;
-
- color.rgb += spec * specular;
- color.a = spec * sunAngle2;
-
- vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
-
- frag_data[0] = vec4(color.rgb, color); // diffuse
- frag_data[1] = vec4(spec * specular, spec); // speccolor, spec
- frag_data[2] = vec4(encode_normal(wavef.xyz), 0.05, 0);// normalxy, 0, 0
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
deleted file mode 100644
index 02000d90ca..0000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * @file waterV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, 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;
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-
-
-uniform vec2 d1;
-uniform vec2 d2;
-uniform float time;
-uniform vec3 eyeVec;
-uniform float waterHeight;
-
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-VARYING vec4 vary_position;
-
-float wave(vec2 v, float t, float f, vec2 d, float s)
-{
- return (dot(d, v)*f + t*s)*f;
-}
-
-void main()
-{
- //transform vertex
- vec4 pos = vec4(position.xyz, 1.0);
- mat4 modelViewProj = modelview_projection_matrix;
-
- vec4 oPosition;
-
- //get view vector
- vec3 oEyeVec;
- oEyeVec.xyz = pos.xyz-eyeVec;
-
- float d = length(oEyeVec.xy);
- float ld = min(d, 2560.0);
-
- pos.xy = eyeVec.xy + oEyeVec.xy/d*ld;
- view.xyz = oEyeVec;
-
- d = clamp(ld/1536.0-0.5, 0.0, 1.0);
- d *= d;
-
- oPosition = vec4(position, 1.0);
- oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
- vary_position = modelview_matrix * oPosition;
- oPosition = modelViewProj * oPosition;
-
- refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
-
- //get wave position parameter (create sweeping horizontal waves)
- vec3 v = pos.xyz;
- v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0;
-
- //push position for further horizon effect.
- pos.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z);
- pos.w = 1.0;
- pos = modelview_matrix*pos;
-
- //pass wave parameters to pixel shader
- vec2 bigWave = (v.xy) * vec2(0.04,0.04) + d1 * time * 0.055;
- //get two normal map (detail map) texture coordinates
- littleWave.xy = (v.xy) * vec2(0.45, 0.9) + d2 * time * 0.13;
- littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
- view.w = bigWave.y;
- refCoord.w = bigWave.x;
-
- gl_Position = oPosition;
-}
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 1ccde98283..58500cc7af 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 34
+version 35
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -28,7 +28,7 @@ version 34
//
list all
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
+RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
@@ -44,7 +44,6 @@ RenderGamma 1 0
RenderGlowResolutionPow 1 9
RenderGround 1 1
RenderMaxPartCount 1 8192
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
@@ -63,6 +62,7 @@ Disregard96DefaultDrawDistance 1 1
RenderTextureMemoryMultiple 1 1.0
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
+RenderPBR 1 1
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
@@ -79,7 +79,6 @@ RenderGLMultiThreaded 1 1
//
list Low
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0
RenderAvatarPhysicsLODFactor 1 0
RenderAvatarMaxNonImpostors 1 3
@@ -89,15 +88,13 @@ RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderMaxPartCount 1 0
-RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
+RenderPBR 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -109,7 +106,6 @@ RenderFSAASamples 1 0
//
list LowMid
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0.5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
@@ -117,7 +113,6 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -125,8 +120,7 @@ RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
+RenderPBR 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -138,7 +132,6 @@ RenderFSAASamples 1 0
//
list Mid
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -146,7 +139,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -154,8 +146,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -167,7 +157,6 @@ RenderFSAASamples 1 2
//
list MidHigh
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -175,7 +164,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -183,8 +171,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -196,7 +182,6 @@ RenderFSAASamples 1 2
//
list High
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -204,7 +189,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -212,8 +196,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -225,7 +207,6 @@ RenderFSAASamples 1 2
//
list HighUltra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 350000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -233,7 +214,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -241,8 +221,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
@@ -254,7 +232,6 @@ RenderFSAASamples 1 2
//
list Ultra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderFarClip 1 256
@@ -262,7 +239,6 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@@ -271,7 +247,6 @@ RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
@@ -282,8 +257,8 @@ RenderFSAASamples 1 2
//
list Unknown
RenderShadowDetail 1 0
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
+RenderPBR 1 0
RenderUseAdvancedAtmospherics 1 0
//
@@ -297,18 +272,15 @@ RenderCompressTextures 1 0
//
list safe
RenderAnisotropic 1 0
-RenderAvatarCloth 0 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
-RenderObjectBump 0 0
RenderLocalLights 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
RenderReflectionDetail 0 0
-WindLightUseAtmosShaders 0 0
-RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
+RenderPBR 1 0
list Intel
RenderAnisotropic 1 0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index c9efd89cc8..7bad9b56f1 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 38
+version 39
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -28,7 +28,7 @@ version 38
//
list all
RenderAnisotropic 1 0
-RenderAvatarCloth 1 1
+RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderAvatarMaxNonImpostors 1 16
@@ -64,6 +64,7 @@ RenderTextureMemoryMultiple 1 1.0
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
+RenderPBR 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
@@ -78,7 +79,6 @@ RenderGLMultiThreaded 1 0
//
list Low
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0
RenderAvatarPhysicsLODFactor 1 0
RenderAvatarMaxNonImpostors 1 3
@@ -88,15 +88,13 @@ RenderFlexTimeFactor 1 0
RenderGlowResolutionPow 1 8
RenderLocalLights 1 0
RenderMaxPartCount 1 0
-RenderObjectBump 1 0
RenderReflectionDetail 1 0
RenderTerrainDetail 1 0
RenderTerrainLODFactor 1 1
RenderTransparentWater 1 0
RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 0.5
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
+RenderPBR 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -108,7 +106,6 @@ RenderFSAASamples 1 0
//
list LowMid
RenderAnisotropic 1 0
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 0.5
RenderAvatarMaxComplexity 1 100000
RenderAvatarPhysicsLODFactor 1 0.75
@@ -116,7 +113,6 @@ RenderFarClip 1 96
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 8
RenderMaxPartCount 1 2048
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -124,8 +120,7 @@ RenderTerrainLODFactor 1 1.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 0
-RenderDeferred 1 0
+RenderPBR 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -137,7 +132,6 @@ RenderFSAASamples 1 0
//
list Mid
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 200000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -145,7 +139,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -153,8 +146,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -166,7 +157,6 @@ RenderFSAASamples 1 2
//
list MidHigh
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 250000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -174,7 +164,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -182,8 +171,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -195,7 +182,6 @@ RenderFSAASamples 1 2
//
list High
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 300000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -203,7 +189,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -211,8 +196,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 0
@@ -224,7 +207,6 @@ RenderFSAASamples 1 2
//
list HighUltra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 0
RenderAvatarLODFactor 1 1.0
RenderAvatarMaxComplexity 1 350000
RenderAvatarPhysicsLODFactor 1 1.0
@@ -232,7 +214,6 @@ RenderFarClip 1 128
RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderMaxPartCount 1 4096
-RenderObjectBump 1 1
RenderLocalLights 1 1
RenderReflectionDetail 1 0
RenderTerrainDetail 1 1
@@ -240,8 +221,6 @@ RenderTerrainLODFactor 1 2.0
RenderTransparentWater 1 1
RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
-WindLightUseAtmosShaders 1 1
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderUseAdvancedAtmospherics 1 0
@@ -253,7 +232,6 @@ RenderFSAASamples 1 2
//
list Ultra
RenderAnisotropic 1 1
-RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarPhysicsLODFactor 1 1.0
RenderFarClip 1 256
@@ -261,7 +239,6 @@ RenderFlexTimeFactor 1 1.0
RenderGlowResolutionPow 1 9
RenderLocalLights 1 1
RenderMaxPartCount 1 8192
-RenderObjectBump 1 1
RenderReflectionDetail 1 4
RenderTerrainDetail 1 1
RenderTerrainLODFactor 1 2.0
@@ -270,7 +247,6 @@ RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
-RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderUseAdvancedAtmospherics 1 0
RenderShadowDetail 1 2
@@ -281,7 +257,7 @@ RenderFSAASamples 1 2
//
list Unknown
RenderShadowDetail 1 0
-RenderDeferred 1 0
+RenderPBR 1 0
RenderDeferredSSAO 1 0
RenderUseAdvancedAtmospherics 1 0
@@ -297,16 +273,13 @@ RenderCompressTextures 1 0
//
list safe
RenderAnisotropic 1 0
-RenderAvatarCloth 0 0
RenderAvatarMaxNonImpostors 1 16
RenderAvatarMaxComplexity 1 80000
-RenderObjectBump 0 0
RenderLocalLights 1 0
RenderMaxPartCount 1 1024
RenderTerrainDetail 1 0
RenderReflectionDetail 0 0
-WindLightUseAtmosShaders 0 0
-RenderDeferred 0 0
+RenderPBR 1 0
RenderDeferredSSAO 0 0
RenderUseAdvancedAtmospherics 0 0
RenderShadowDetail 0 0
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index fba6a55da3..29b5a919bd 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -719,3 +719,55 @@ 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.
+
+
+============
+tinygltf
+============
+MIT License
+
+Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
+
+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.
+
+==============
+Vulkan GLTF
+==============
+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.
+
diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt
index 837d92139d..eddc9a4475 100644
--- a/indra/newview/licenses-win32.txt
+++ b/indra/newview/licenses-win32.txt
@@ -796,3 +796,52 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+============
+tinygltf
+============
+MIT License
+
+Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors
+
+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.
+
+==============
+Vulkan GLTF
+==============
+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.
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 8d2e3905d1..57a59d81c4 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1186,12 +1186,18 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y)
static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Camera");
+extern BOOL gCubeSnapshot;
+
//-----------------------------------------------------------------------------
// updateCamera()
//-----------------------------------------------------------------------------
void LLAgentCamera::updateCamera()
{
LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
// - changed camera_skyward to the new global "mCameraUpVector"
mCameraUpVector = LLVector3::z_axis;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 60797c87d9..bf67807aea 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -1507,22 +1507,23 @@ bool LLAppViewer::doFrame()
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
- if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Display" )
- pingMainloopTimeout("Main:Display");
- gGLActive = TRUE;
+ if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display");
+ pingMainloopTimeout("Main:Display");
+ gGLActive = TRUE;
- display();
+ display();
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" )
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
- LLFloaterOutfitSnapshot::update();
- gGLActive = FALSE;
- }
- }
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot");
+ pingMainloopTimeout("Main:Snapshot");
+ gPipeline.mReflectionMapManager.update();
+ LLFloaterSnapshot::update(); // take snapshots
+ LLFloaterOutfitSnapshot::update();
+ gGLActive = FALSE;
+ }
+ }
}
{
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 4a87273372..d4d4f641cf 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -610,6 +610,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -627,7 +628,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
{
LLVector4a local_end = end;
LLVector4a local_intersection;
- if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
@@ -644,7 +645,7 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
for (std::vector<LLVOVolume*>::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it)
{
LLVOVolume *volp = *vol_it;
- if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index 8e87299f3e..ea91d70e69 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -68,6 +68,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 4a0c9d399f..bfb79f3a4c 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -249,12 +249,9 @@ void LLDrawable::cleanupReferences()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
mFaces.clear();
- gObjectList.removeDrawable(this);
-
gPipeline.unlinkDrawable(this);
removeFromOctree();
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index a3837fe10c..1e548141c8 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -37,6 +37,7 @@
#include "lldrawpoolbump.h"
#include "lldrawpoolmaterials.h"
#include "lldrawpoolground.h"
+#include "lldrawpoolpbropaque.h"
#include "lldrawpoolsimple.h"
#include "lldrawpoolsky.h"
#include "lldrawpooltree.h"
@@ -117,6 +118,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
case POOL_WL_SKY:
poolp = new LLDrawPoolWLSky();
break;
+ case POOL_PBR_OPAQUE:
+ poolp = new LLDrawPoolPBROpaque();
+ break;
default:
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
return NULL;
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index fd1b022e5b..f7fc2d2061 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -48,6 +48,7 @@ public:
enum
{
// Correspond to LLPipeline render type
+ // NOTE: Keep in sync with gPoolNames
POOL_SIMPLE = 1,
POOL_GROUND,
POOL_FULLBRIGHT,
@@ -67,6 +68,7 @@ public:
POOL_WATER,
POOL_GLOW,
POOL_ALPHA,
+ POOL_PBR_OPAQUE,
NUM_POOL_TYPES,
// * invisiprims work by rendering to the depth buffer but not the color buffer, occluding anything rendered after them
// - and the LLDrawPool types enum controls what order things are rendered in
@@ -129,6 +131,7 @@ class LLRenderPass : public LLDrawPool
public:
// list of possible LLRenderPass types to assign a render batch to
// NOTE: "rigged" variant MUST be non-rigged variant + 1
+ // see LLVolumeGeometryManager::registerFace()
enum
{
PASS_SIMPLE = NUM_POOL_TYPES,
@@ -190,6 +193,8 @@ public:
PASS_FULLBRIGHT_ALPHA_MASK_RIGGED,
PASS_ALPHA_INVISIBLE,
PASS_ALPHA_INVISIBLE_RIGGED,
+ PASS_PBR_OPAQUE,
+ PASS_PBR_OPAQUE_RIGGED,
NUM_RENDER_TYPES,
};
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index e674707c01..89b8ec1ba2 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -129,6 +129,8 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
}
}
+extern BOOL gCubeSnapshot;
+
void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
@@ -155,13 +157,13 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
forwardRender();
// final pass, render to depth for depth of field effects
- if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField"))
+ if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField") && !gCubeSnapshot)
{
//update depth buffer sampler
- gPipeline.mScreen.flush();
- gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
- 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- gPipeline.mDeferredDepth.bindTarget();
+ gPipeline.mRT->screen.flush();
+ gPipeline.mRT->deferredDepth.copyContents(gPipeline.mRT->deferredScreen, 0, 0, gPipeline.mRT->deferredScreen.getWidth(), gPipeline.mRT->deferredScreen.getHeight(),
+ 0, 0, gPipeline.mRT->deferredDepth.getWidth(), gPipeline.mRT->deferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ gPipeline.mRT->deferredDepth.bindTarget();
simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
simple_shader->bind();
@@ -175,8 +177,8 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2,
true); // <--- discard mostly transparent faces
- gPipeline.mDeferredDepth.flush();
- gPipeline.mScreen.bindTarget();
+ gPipeline.mRT->deferredDepth.flush();
+ gPipeline.mRT->screen.bindTarget();
gGL.setColorMask(true, false);
}
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 8db6a10e26..288ba8f536 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -465,6 +465,11 @@ void LLDrawPoolBump::beginFullbrightShiny()
shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
cube_map->setMatrix(1);
+ 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();
@@ -526,6 +531,10 @@ void LLDrawPoolBump::endFullbrightShiny()
{
cube_map->disable();
cube_map->restoreMatrix();
+ if (shader->mFeatures.hasReflectionProbes)
+ {
+ gPipeline.unbindReflectionProbes(*shader);
+ }
shader->unbind();
}
@@ -741,6 +750,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
void LLDrawPoolBump::renderPostDeferred(S32 pass)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL
for (int i = 0; i < 2; ++i)
{ // two passes -- static and rigged
mRigged = (i == 1);
diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp
new file mode 100644
index 0000000000..b59bffea1a
--- /dev/null
+++ b/indra/newview/lldrawpoolpbropaque.cpp
@@ -0,0 +1,146 @@
+/**
+ * @file lldrawpoolpbropaque.cpp
+ * @brief LLDrawPoolPBROpaque class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldrawpool.h"
+#include "lldrawpoolpbropaque.h"
+#include "llviewershadermgr.h"
+#include "pipeline.h"
+
+LLDrawPoolPBROpaque::LLDrawPoolPBROpaque() :
+ LLRenderPass(POOL_PBR_OPAQUE)
+{
+}
+
+void LLDrawPoolPBROpaque::prerender()
+{
+ mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+}
+
+// Forward
+void LLDrawPoolPBROpaque::beginRenderPass(S32 pass)
+{
+}
+
+void LLDrawPoolPBROpaque::endRenderPass( S32 pass )
+{
+}
+
+void LLDrawPoolPBROpaque::render(S32 pass)
+{
+}
+
+// Deferred
+void LLDrawPoolPBROpaque::beginDeferredPass(S32 pass)
+{
+ gDeferredPBROpaqueProgram.bind();
+}
+
+void LLDrawPoolPBROpaque::endDeferredPass(S32 pass)
+{
+ gDeferredPBROpaqueProgram.unbind();
+ LLRenderPass::endRenderPass(pass);
+}
+
+void LLDrawPoolPBROpaque::renderDeferred(S32 pass)
+{
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_MATERIALS))
+ {
+ return;
+ }
+
+ const U32 type = LLPipeline::RENDER_TYPE_PASS_PBR_OPAQUE;
+ if (!gPipeline.hasRenderType(type))
+ {
+ return;
+ }
+
+ gGL.flush();
+
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable alpha_test(GL_ALPHA_TEST);
+
+ // TODO: handle HUDs?
+ //if (LLPipeline::sRenderingHUDs)
+ // mShader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ //else
+ // mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+
+ // TODO: handle under water?
+ // if (LLPipeline::sUnderWaterRender)
+ LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+ LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
+
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
+ {
+ LLDrawInfo& params = **i;
+
+ //gGL.getTexUnit(0)->activate();
+
+ if (params.mTexture.notNull())
+ {
+ gGL.getTexUnit(0)->bindFast(params.mTexture); // diffuse
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ if (params.mNormalMap)
+ {
+ gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap);
+ }
+ else
+ {
+ // TODO: bind default normal map (???? WTF is it ??? )
+ }
+
+ if (params.mSpecularMap)
+ {
+ gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap); // PBR linear packed Occlusion, Roughness, Metal.
+ }
+ else
+ {
+ gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ if (params.mEmissiveMap)
+ {
+ gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, params.mEmissiveMap); // PBR sRGB Emissive
+ }
+ else
+ {
+ gDeferredPBROpaqueProgram.bindTexture(LLShaderMgr::EMISSIVE_MAP, LLViewerFetchedTexture::sWhiteImagep);
+ }
+
+ gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, params.mGLTFMaterial->mRoughnessFactor);
+ gDeferredPBROpaqueProgram.uniform1f(LLShaderMgr::METALLIC_FACTOR, params.mGLTFMaterial->mMetallicFactor);
+ gDeferredPBROpaqueProgram.uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, params.mGLTFMaterial->mEmissiveColor.mV);
+
+ LLRenderPass::pushBatch(params, getVertexDataMask(), FALSE, FALSE);
+ }
+}
diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h
new file mode 100644
index 0000000000..478d4e1bd4
--- /dev/null
+++ b/indra/newview/lldrawpoolpbropaque.h
@@ -0,0 +1,65 @@
+/**
+ * @file lldrawpoolpbropaque.h
+ * @brief LLDrawPoolPBrOpaque class definition
+ *
+ * $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$
+ */
+
+#ifndef LL_LLDRAWPOOLPBROPAQUE_H
+#define LL_LLDRAWPOOLPBROPAQUE_H
+
+#include "lldrawpool.h"
+
+class LLDrawPoolPBROpaque : public LLRenderPass
+{
+public:
+ enum
+ {
+ // See: DEFERRED_VB_MASK
+ VERTEX_DATA_MASK = 0
+ | LLVertexBuffer::MAP_VERTEX
+ | LLVertexBuffer::MAP_NORMAL
+ | LLVertexBuffer::MAP_TEXCOORD0 // Diffuse
+ | LLVertexBuffer::MAP_TEXCOORD1 // Normal
+ | LLVertexBuffer::MAP_TEXCOORD2 // Spec <-- ORM Occlusion Roughness Metal
+ | LLVertexBuffer::MAP_TANGENT
+ | LLVertexBuffer::MAP_COLOR
+ };
+ virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+ LLDrawPoolPBROpaque();
+
+ /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ void beginDeferredPass(S32 pass);
+ /*virtual*/ void endDeferredPass(S32 pass);
+ /*virtual*/ void renderDeferred(S32 pass);
+
+ // Non ALM isn't supported
+ /*virtual*/ void beginRenderPass(S32 pass);
+ /*virtual*/ void endRenderPass(S32 pass);
+ /*virtual*/ S32 getNumPasses() { return 0; }
+ /*virtual*/ void render(S32 pass = 0);
+ /*virtual*/ void prerender();
+
+};
+
+#endif // LL_LLDRAWPOOLPBROPAQUE_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index c3b3ccabb4..499d8d161d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -586,7 +586,6 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
}
gGL.syncMatrices();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x00FF00 );
glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
@@ -1384,6 +1383,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLColor4U color = tep->getColor();
+ if (tep->getGLTFMaterial())
+ {
+ color = tep->getGLTFMaterial()->mAlbedoColor;
+ }
+
if (rebuild_color)
{ //decide if shiny goes in alpha channel of color
if (tep &&
@@ -1793,10 +1797,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
scalea.load3(scale.mV);
LLMaterial* mat = tep->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = tep->getGLTFMaterial();
bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
- if (mat && !do_bump)
+ if ((mat || gltf_mat) && !do_bump)
{
do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)
|| mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
@@ -2022,10 +2027,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBuffer->flush();
}
- if (!mat && do_bump)
+ if ((!mat && !gltf_mat) && do_bump)
{
mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range);
+ mVObjp->getVolume()->genTangents(f);
+
for (S32 i = 0; i < num_vertices; i++)
{
LLVector4a tangent = vf.mTangents[i];
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 3669fb1eeb..3c5ac963f6 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -55,13 +55,12 @@ LLFilePicker LLFilePicker::sInstance;
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
-#ifdef _CORY_TESTING
-#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
-#endif
+#define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0"
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
+#define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0"
#define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
#endif
@@ -193,16 +192,14 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = ANIM_FILTER \
L"\0";
break;
- case FFLOAD_COLLADA:
+ case FFLOAD_GLTF:
+ mOFN.lpstrFilter = GLTF_FILTER \
+ L"\0";
+ break;
+ case FFLOAD_COLLADA:
mOFN.lpstrFilter = COLLADA_FILTER \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- mOFN.lpstrFilter = GEOMETRY_FILTER \
- L"\0";
- break;
-#endif
case FFLOAD_XML:
mOFN.lpstrFilter = XML_FILTER \
L"\0";
@@ -219,6 +216,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = MODEL_FILTER \
L"\0";
break;
+ case FFLOAD_MATERIAL:
+ mOFN.lpstrFilter = MATERIAL_FILTER \
+ L"\0";
+ break;
case FFLOAD_SCRIPT:
mOFN.lpstrFilter = SCRIPT_FILTER \
L"\0";
@@ -480,18 +481,16 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
L"XAF Anim File (*.xaf)\0*.xaf\0" \
L"\0";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
if (filename.empty())
{
- wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
+ wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/
}
- mOFN.lpstrDefExt = L"slg";
+ mOFN.lpstrDefExt = L"glb";
mOFN.lpstrFilter =
- L"SLG SL Geometry File (*.slg)\0*.slg\0" \
+ L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \
L"\0";
break;
-#endif
case FFSAVE_XML:
if (filename.empty())
{
@@ -621,14 +620,13 @@ std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //
allowedv->push_back("bvh");
allowedv->push_back("anim");
break;
+ case FFLOAD_GLTF:
+ allowedv->push_back("gltf");
+ allowedv->push_back("glb");
+ break;
case FFLOAD_COLLADA:
allowedv->push_back("dae");
break;
-#ifdef _CORY_TESTING
- case FFLOAD_GEOMETRY:
- allowedv->push_back("slg");
- break;
-#endif
case FFLOAD_XML:
allowedv->push_back("xml");
break;
@@ -728,13 +726,11 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
extension = "xaf";
break;
-#ifdef _CORY_TESTING
- case FFSAVE_GEOMETRY:
+ case FFSAVE_GLTF:
type = "\?\?\?\?";
creator = "\?\?\?\?";
- extension = "slg";
+ extension = "glb";
break;
-#endif
case FFSAVE_XML:
type = "\?\?\?\?";
@@ -1354,10 +1350,13 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
case FFLOAD_XML:
filtername = add_xml_filter_to_gtkchooser(picker);
break;
- case FFLOAD_COLLADA:
- filtername = add_collada_filter_to_gtkchooser(picker);
- break;
- case FFLOAD_IMAGE:
+ case FFLOAD_GLTF:
+ filtername = dead_code_should_blow_up_here(picker);
+ break;
+ case FFLOAD_COLLADA:
+ filtername = add_collada_filter_to_gtkchooser(picker);
+ break;
+ case FFLOAD_IMAGE:
filtername = add_imageload_filter_to_gtkchooser(picker);
break;
case FFLOAD_SCRIPT:
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 04ba4416d7..cb57c8437d 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -77,9 +77,7 @@ public:
FFLOAD_WAV = 2,
FFLOAD_IMAGE = 3,
FFLOAD_ANIM = 4,
-#ifdef _CORY_TESTING
- FFLOAD_GEOMETRY = 5,
-#endif
+ FFLOAD_GLTF = 5,
FFLOAD_XML = 6,
FFLOAD_SLOBJECT = 7,
FFLOAD_RAW = 8,
@@ -88,7 +86,8 @@ public:
FFLOAD_SCRIPT = 11,
FFLOAD_DICTIONARY = 12,
FFLOAD_DIRECTORY = 13, // To call from lldirpicker.
- FFLOAD_EXE = 14 // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
+ FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
+ FFLOAD_MATERIAL = 15
};
enum ESaveFilter
@@ -99,9 +98,7 @@ public:
FFSAVE_BMP = 5,
FFSAVE_AVI = 6,
FFSAVE_ANIM = 7,
-#ifdef _CORY_TESTING
- FFSAVE_GEOMETRY = 8,
-#endif
+ FFSAVE_GLTF = 8,
FFSAVE_XML = 9,
FFSAVE_COLLADA = 10,
FFSAVE_RAW = 11,
diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index a1a06706bc..a3cc939f85 100644
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -306,6 +306,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve
( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) ||
( asstype == LLAssetType::AT_SOUND && gSavedSettings.getBOOL("BulkChangeIncludeSounds" )) ||
( asstype == LLAssetType::AT_SETTINGS && gSavedSettings.getBOOL("BulkChangeIncludeSettings" )) ||
+ ( asstype == LLAssetType::AT_MATERIAL && gSavedSettings.getBOOL("BulkChangeIncludeMaterials")) ||
( asstype == LLAssetType::AT_TEXTURE && gSavedSettings.getBOOL("BulkChangeIncludeTextures" )))
{
LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 58fbdba315..b7c98c915c 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -97,7 +97,7 @@ private:
};
LLMeshFilePicker::LLMeshFilePicker(LLModelPreview* mp, S32 lod)
-: LLFilePickerThread(LLFilePicker::FFLOAD_COLLADA)
+: LLFilePickerThread(LLFilePicker::FFLOAD_MODEL)
{
mMP = mp;
mLOD = lod;
@@ -330,8 +330,8 @@ void LLFloaterModelPreview::initModelPreview()
S32 tex_width = 512;
S32 tex_height = 512;
- S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenWidth);
- S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mScreenHeight);
+ S32 max_width = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->width);
+ S32 max_height = llmin(PREVIEW_RENDER_SIZE, (S32)gPipeline.mRT->height);
while ((tex_width << 1) < max_width)
{
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 8d19aa36bb..20749b67b2 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1182,6 +1182,7 @@ void LLFloaterPreference::refreshEnabledState()
{
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
+ LLCheckBoxCtrl* ctrl_pbr = getChild<LLCheckBoxCtrl>("UsePBRShaders");
// if vertex shaders off, disable all shader related products
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
@@ -1205,6 +1206,11 @@ void LLFloaterPreference::refreshEnabledState()
ctrl_deferred->setEnabled(enabled);
+ //PBR
+ BOOL deferred = gSavedSettings.getBOOL("RenderDeferred");
+ // TODO: add "RenderPBR" to LLFeatureManager
+ ctrl_pbr->setEnabled(deferred);
+
// Cannot have floater active until caps have been received
getChild<LLButton>("default_creation_permissions")->setEnabled(LLStartUp::getStartupState() < STATE_STARTED ? false : true);
@@ -1221,51 +1227,21 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
ctrl_reflections->setEnabled(reflections);
reflections_text->setEnabled(reflections);
- // Bump & Shiny
- LLCheckBoxCtrl* bumpshiny_ctrl = getChild<LLCheckBoxCtrl>("BumpShiny");
- bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
- bumpshiny_ctrl->setEnabled(bumpshiny ? TRUE : FALSE);
-
- // Avatar Mode
- // Avatar Render Mode
- getChild<LLCheckBoxCtrl>("AvatarCloth")->setEnabled(TRUE);
-
- // Vertex Shaders, Global Shader Enable
- // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code
- LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail"); // can be linked with control var
- LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
-
- terrain_detail->setEnabled(FALSE);
- terrain_text->setEnabled(FALSE);
-
// WindLight
- LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
- ctrl_wind_light->setEnabled(TRUE);
sky->setEnabled(TRUE);
sky_text->setEnabled(TRUE);
- //Deferred/SSAO/Shadows
- LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
-
- BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
- ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
- gGLManager.mHasFramebufferObject &&
- (ctrl_wind_light->get()) ? TRUE : FALSE;
- ctrl_deferred->setEnabled(enabled);
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
LLTextBox* shadow_text = getChild<LLTextBox>("RenderShadowDetailText");
- // note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it
- enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);
+ BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO");
- ctrl_deferred->set(gSavedSettings.getBOOL("RenderDeferred"));
-
ctrl_ssao->setEnabled(enabled);
ctrl_dof->setEnabled(enabled);
@@ -1293,11 +1269,6 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
getChildView("texture compression")->setEnabled(FALSE);
}
- // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance
- LLUICtrl* gamma_ctrl = getChild<LLUICtrl>("gamma");
- gamma_ctrl->setEnabled(!gPipeline.canUseWindLightShaders());
- getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders());
- getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders());
getChildView("antialiasing restart")->setVisible(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"));
// now turn off any features that are unavailable
@@ -1350,7 +1321,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
{
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
- LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
@@ -1424,13 +1394,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
ctrl_reflections->setValue(FALSE);
reflections_text->setEnabled(FALSE);
}
-
- // disabled cloth
- if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
- {
- ctrl_avatar_cloth->setEnabled(FALSE);
- ctrl_avatar_cloth->setValue(FALSE);
- }
}
void LLFloaterPreference::refresh()
diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp
new file mode 100644
index 0000000000..7ecbc6eeac
--- /dev/null
+++ b/indra/newview/llgltfmateriallist.cpp
@@ -0,0 +1,186 @@
+/**
+ * @file llgltfmateriallist.cpp
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llgltfmateriallist.h"
+
+#include "llassetstorage.h"
+#include "llfilesystem.h"
+#include "llsdserialize.h"
+
+#include "tinygltf/tiny_gltf.h"
+#include <strstream>
+
+LLGLTFMaterialList gGLTFMaterialList;
+
+static LLColor4 get_color(const std::vector<double>& in)
+{
+ LLColor4 out;
+ for (S32 i = 0; i < llmin((S32)in.size(), 4); ++i)
+ {
+ out.mV[i] = in[i];
+ }
+
+ return out;
+}
+
+static void set_from_model(LLGLTFMaterial* mat, tinygltf::Model& model)
+{
+
+ S32 index;
+
+ auto& material_in = model.materials[0];
+
+ // get albedo texture
+ index = material_in.pbrMetallicRoughness.baseColorTexture.index;
+ if (index >= 0)
+ {
+ mat->mAlbedoId.set(model.images[index].uri);
+ }
+ else
+ {
+ mat->mAlbedoId.setNull();
+ }
+
+ // get normal map
+ index = material_in.normalTexture.index;
+ if (index >= 0)
+ {
+ mat->mNormalId.set(model.images[index].uri);
+ }
+ else
+ {
+ mat->mNormalId.setNull();
+ }
+
+ // get metallic-roughness texture
+ index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (index >= 0)
+ {
+ mat->mMetallicRoughnessId.set(model.images[index].uri);
+ }
+ else
+ {
+ mat->mMetallicRoughnessId.setNull();
+ }
+
+ // get emissive texture
+ index = material_in.emissiveTexture.index;
+ if (index >= 0)
+ {
+ mat->mEmissiveId.set(model.images[index].uri);
+ }
+ else
+ {
+ mat->mEmissiveId.setNull();
+ }
+
+ mat->setAlphaMode(material_in.alphaMode);
+ mat->mAlphaCutoff = material_in.alphaCutoff;
+
+ mat->mAlbedoColor = get_color(material_in.pbrMetallicRoughness.baseColorFactor);
+ mat->mEmissiveColor = get_color(material_in.emissiveFactor);
+
+ mat->mMetallicFactor = material_in.pbrMetallicRoughness.metallicFactor;
+ mat->mRoughnessFactor = material_in.pbrMetallicRoughness.roughnessFactor;
+
+ mat->mDoubleSided = material_in.doubleSided;
+}
+
+LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id)
+{
+ List::iterator iter = mList.find(id);
+ if (iter == mList.end())
+ {
+ LLGLTFMaterial* mat = new LLGLTFMaterial();
+ mList[id] = mat;
+
+ mat->ref();
+
+ gAssetStorage->getAssetData(id, LLAssetType::AT_MATERIAL,
+ [=](const LLUUID& id, LLAssetType::EType asset_type, void* user_data, S32 status, LLExtStat ext_status)
+ {
+ if (status)
+ {
+ LL_WARNS() << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL;
+ }
+
+ LLFileSystem file(id, asset_type, LLFileSystem::READ);
+
+ std::vector<char> buffer;
+ buffer.resize(file.getSize());
+ file.read((U8*)&buffer[0], buffer.size());
+
+ LLSD asset;
+
+ // read file into buffer
+ std::istrstream str(&buffer[0], buffer.size());
+
+ if (LLSDSerialize::deserialize(asset, str, buffer.size()))
+ {
+ if (asset.has("version") && asset["version"] == "1.0")
+ {
+ if (asset.has("type") && asset["type"].asString() == "GLTF 2.0")
+ {
+ if (asset.has("data") && asset["data"].isString())
+ {
+ std::string data = asset["data"];
+
+ tinygltf::TinyGLTF gltf;
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ tinygltf::Model model_in;
+
+ if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))
+ {
+ set_from_model(mat, model_in);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to decode material asset: " << LL_ENDL;
+ LL_WARNS() << warn_msg << LL_ENDL;
+ LL_WARNS() << error_msg << LL_ENDL;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL;
+ }
+
+ mat->unref();
+ }, nullptr);
+
+ return mat;
+ }
+
+ return iter->second;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl b/indra/newview/llgltfmateriallist.h
index ca9ce3a2e1..c22134c468 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl
+++ b/indra/newview/llgltfmateriallist.h
@@ -1,37 +1,48 @@
-/**
- * @file pointShadowBlur.glsl
+/**
+ * @file llgltfmateriallist.h
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- *
+ * 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$
*/
-uniform samplerCube cube_map;
-in vec3 to_vec;
+#pragma once
+
+#include "llgltfmaterial.h"
+#include "llpointer.h"
-out vec4 fragColor;
+#include <unordered_map>
-void main()
+class LLGLTFMaterialList
{
- vec4 vcol = texture(cube_map, to_vec);
- fragColor = vec4(vcol.rgb, 1.0);
-}
+public:
+ LLGLTFMaterialList() {}
+
+ typedef std::unordered_map<LLUUID, LLPointer<LLGLTFMaterial > > List;
+ List mList;
+
+ LLGLTFMaterial* getMaterial(const LLUUID& id);
+
+};
+
+extern LLGLTFMaterialList gGLTFMaterialList;
+
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
index 85a878c4a2..60294f6a51 100644
--- a/indra/newview/llhudicon.cpp
+++ b/indra/newview/llhudicon.cpp
@@ -64,7 +64,6 @@ LLHUDIcon::icon_instance_t LLHUDIcon::sIconInstances;
LLHUDIcon::LLHUDIcon(const U8 type) :
LLHUDObject(type),
mImagep(NULL),
- mPickID(0),
mScale(0.1f),
mHidden(FALSE)
{
@@ -76,15 +75,11 @@ LLHUDIcon::~LLHUDIcon()
mImagep = NULL;
}
-void LLHUDIcon::renderIcon(BOOL for_select)
+void LLHUDIcon::render()
{
LLGLSUIDefault texture_state;
LLGLDepthTest gls_depth(GL_TRUE);
LLGLDisable gls_stencil(GL_STENCIL_TEST);
- if (for_select)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
if (mHidden)
return;
@@ -116,7 +111,7 @@ void LLHUDIcon::renderIcon(BOOL for_select)
mDistance = dist_vec(icon_position, camera->getOrigin());
- F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
+ F32 alpha_factor = clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
LLVector3 x_pixel_vec;
LLVector3 y_pixel_vec;
@@ -150,13 +145,6 @@ void LLHUDIcon::renderIcon(BOOL for_select)
LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale;
LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale;
- if (for_select)
- {
- // set color to unique color id for picking
- LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID);
- gGL.color4ubv(coloru.mV);
- }
- else
{
LLColor4 icon_color = LLColor4::white;
icon_color.mV[VALPHA] = alpha_factor;
@@ -198,11 +186,6 @@ void LLHUDIcon::markDead()
LLHUDObject::markDead();
}
-void LLHUDIcon::render()
-{
- renderIcon(FALSE);
-}
-
BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
if (mHidden)
@@ -296,37 +279,6 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
}
//static
-S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size)
-{
- S32 cur_id = start_id;
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- (*icon_it)->mPickID = cur_id;
- cur_id += step_size;
- }
-
- return cur_id;
-}
-
-//static
-LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id)
-{
- icon_instance_t::iterator icon_it;
-
- for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
- {
- if (pick_id == (*icon_it)->mPickID)
- {
- return *icon_it;
- }
- }
-
- return NULL;
-}
-
-//static
LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection)
{
icon_instance_t::iterator icon_it;
diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h
index e00a985ddc..7f452b5c36 100644
--- a/indra/newview/llhudicon.h
+++ b/indra/newview/llhudicon.h
@@ -56,8 +56,6 @@ public:
void restartLifeTimer() { mLifeTimer.reset(); }
- static S32 generatePickIDs(S32 start_id, S32 step_size);
- static LLHUDIcon* handlePick(S32 pick_id);
static LLHUDIcon* lineSegmentIntersectAll(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection);
static void updateAll();
@@ -75,14 +73,11 @@ protected:
LLHUDIcon(const U8 type);
~LLHUDIcon();
- void renderIcon(BOOL for_select); // common render code
-
private:
LLPointer<LLViewerTexture> mImagep;
LLFrameTimer mAnimTimer;
LLFrameTimer mLifeTimer;
F32 mDistance;
- S32 mPickID;
F32 mScale;
BOOL mHidden;
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 884007d2a6..7abe48709b 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -785,7 +785,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (obj)
{
- items.push_back(std::string("Copy Separator"));
+ if (obj->getType() != LLAssetType::AT_CATEGORY)
+ {
+ items.push_back(std::string("Copy Separator"));
+ }
items.push_back(std::string("Copy"));
if (!isItemCopyable())
{
@@ -891,7 +894,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
- items.push_back(std::string("Paste Separator"));
+ if (obj->getType() != LLAssetType::AT_CATEGORY)
+ {
+ items.push_back(std::string("Paste Separator"));
+ }
addDeleteContextMenuOptions(items, disabled_items);
@@ -1433,6 +1439,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
new_listener = new LLSettingsBridge(inventory, root, uuid, LLSettingsType::fromInventoryFlags(flags));
break;
+ case LLAssetType::AT_MATERIAL:
+ if (inv_type != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
+ }
+ new_listener = new LLMaterialBridge(inventory, root, uuid);
+ break;
+
default:
LL_INFOS_ONCE() << "Unhandled asset type (llassetstorage.h): "
<< (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << LL_ENDL;
@@ -4024,6 +4038,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Settings"));
disabled_items.push_back(std::string("New Gesture"));
+ disabled_items.push_back(std::string("New Material"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
@@ -4051,6 +4066,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Script"));
disabled_items.push_back(std::string("New Note"));
disabled_items.push_back(std::string("New Gesture"));
+ disabled_items.push_back(std::string("New Material"));
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
@@ -4105,20 +4121,25 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (!isInboxFolder() // don't allow creation in inbox
&& outfits_id != mUUID)
{
+ bool menu_items_added = false;
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
{
items.push_back(std::string("New Folder"));
+ menu_items_added = true;
}
if (!isMarketplaceListingsFolder())
{
items.push_back(std::string("New Script"));
items.push_back(std::string("New Note"));
items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Material"));
items.push_back(std::string("New Clothes"));
items.push_back(std::string("New Body Parts"));
items.push_back(std::string("New Settings"));
items.push_back(std::string("upload_def"));
+
+ menu_items_added = true;
if (!LLEnvironment::instance().isInventoryEnabled())
{
@@ -4126,6 +4147,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
}
+ if (menu_items_added)
+ {
+ items.push_back(std::string("Create Separator"));
+ }
}
getClipboardEntries(false, items, disabled_items, flags);
}
@@ -4400,6 +4425,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_GESTURE:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
break;
case DAD_LINK:
@@ -6029,6 +6055,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_GESTURE:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
const LLPermissions& perm = inv_item->getPermissions();
@@ -7220,6 +7247,39 @@ bool LLSettingsBridge::canUpdateRegion() const
// +=================================================+
+// | LLMaterialBridge |
+// +=================================================+
+
+void LLMaterialBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+void LLMaterialBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LL_DEBUGS() << "LLMaterialBridge::buildContextMenu()" << LL_ENDL;
+
+ if (isMarketplaceListingsFolder())
+ {
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ addMarketplaceContextMenuOptions(flags, items, disabled_items);
+ items.push_back(std::string("Properties"));
+ getClipboardEntries(false, items, disabled_items, flags);
+ hide_context_entries(menu, items, disabled_items);
+ }
+ else
+ {
+ LLItemBridge::buildContextMenu(menu, flags);
+ }
+}
+
+
+// +=================================================+
// | LLLinkBridge |
// +=================================================+
// For broken folder links.
@@ -7606,6 +7666,24 @@ protected:
LLSettingsBridgeAction(const LLUUID& id, LLInventoryModel* model) : LLInvFVBridgeAction(id, model) {}
};
+class LLMaterialBridgeAction : public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ void doIt() override
+ {
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("material_editor", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+ LLInvFVBridgeAction::doIt();
+ }
+ ~LLMaterialBridgeAction() = default;
+private:
+ LLMaterialBridgeAction(const LLUUID& id,LLInventoryModel* model) : LLInvFVBridgeAction(id,model) {}
+};
+
LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
const LLUUID& uuid,
@@ -7648,6 +7726,9 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
case LLAssetType::AT_SETTINGS:
action = new LLSettingsBridgeAction(uuid, model);
break;
+ case LLAssetType::AT_MATERIAL:
+ action = new LLMaterialBridgeAction(uuid, model);
+ break;
default:
break;
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 0b0ef273e1..6c1ddd716b 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -637,6 +637,17 @@ protected:
};
+class LLMaterialBridge : public LLItemBridge
+{
+public:
+ LLMaterialBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid) :
+ LLItemBridge(inventory, root, uuid) {}
+ virtual void openItem();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction
//
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 707ff2b7b6..f7dc493109 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -1306,6 +1306,18 @@ const std::string& LLInventoryFilter::getFilterText()
filtered_by_all_types = FALSE;
}
+ if (isFilterObjectTypesWith(LLInventoryType::IT_MATERIAL))
+ {
+ filtered_types += LLTrans::getString("Materials");
+ filtered_by_type = TRUE;
+ num_filter_types++;
+ }
+ else
+ {
+ not_filtered_types += LLTrans::getString("Materials");
+ filtered_by_all_types = FALSE;
+ }
+
if (isFilterObjectTypesWith(LLInventoryType::IT_NOTECARD))
{
filtered_types += LLTrans::getString("Notecards");
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 44e493fdf4..e9b0e8404a 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -99,6 +99,8 @@ LLIconDictionary::LLIconDictionary()
addEntry(LLInventoryType::ICONNAME_SETTINGS_DAY, new IconEntry("Inv_SettingsDay"));
addEntry(LLInventoryType::ICONNAME_SETTINGS, new IconEntry("Inv_Settings"));
+ addEntry(LLInventoryType::ICONNAME_MATERIAL, new IconEntry("Inv_Material"));
+
addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid"));
addEntry(LLInventoryType::ICONNAME_UNKNOWN, new IconEntry("Inv_Unknown"));
@@ -177,6 +179,9 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type,
case LLAssetType::AT_SETTINGS:
idx = assignSettingsIcon(misc_flag);
break;
+ case LLAssetType::AT_MATERIAL:
+ idx = LLInventoryType::ICONNAME_MATERIAL;
+ break;
case LLAssetType::AT_UNKNOWN:
idx = LLInventoryType::ICONNAME_UNKNOWN;
default:
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
new file mode 100644
index 0000000000..57cd74e0f2
--- /dev/null
+++ b/indra/newview/llmaterialeditor.cpp
@@ -0,0 +1,1736 @@
+/**
+ * @file llmaterialeditor.cpp
+ * @brief Implementation of the notecard editor
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmaterialeditor.h"
+
+#include "llagent.h"
+#include "llagentbenefits.h"
+#include "llappviewer.h"
+#include "llcombobox.h"
+#include "llinventorymodel.h"
+#include "llnotificationsutil.h"
+#include "lltexturectrl.h"
+#include "lltrans.h"
+#include "llviewermenufile.h"
+#include "llviewertexture.h"
+#include "llsdutil.h"
+#include "llselectmgr.h"
+#include "llstatusbar.h" // can_afford_transaction()
+#include "llviewerinventory.h"
+#include "llviewerregion.h"
+#include "llvovolume.h"
+#include "roles_constants.h"
+#include "llviewerobjectlist.h"
+#include "llfloaterreg.h"
+#include "llfilesystem.h"
+#include "llsdserialize.h"
+#include "llimagej2c.h"
+#include "llviewertexturelist.h"
+#include "llfloaterperms.h"
+
+#include "tinygltf/tiny_gltf.h"
+#include <strstream>
+
+
+const std::string MATERIAL_ALBEDO_DEFAULT_NAME = "Albedo";
+const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal";
+const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness";
+const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
+
+class LLMaterialEditorCopiedCallback : public LLInventoryCallback
+{
+public:
+ LLMaterialEditorCopiedCallback(const std::string &buffer, const LLUUID &old_item_id) : mBuffer(buffer), mOldItemId(old_item_id) {}
+
+ virtual void fire(const LLUUID& inv_item_id)
+ {
+ LLMaterialEditor::finishSaveAs(mOldItemId, inv_item_id, mBuffer);
+ }
+
+private:
+ std::string mBuffer;
+ LLUUID mOldItemId;
+};
+
+///----------------------------------------------------------------------------
+/// Class LLMaterialEditor
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLMaterialEditor::LLMaterialEditor(const LLSD& key)
+ : LLPreview(key)
+ , mHasUnsavedChanges(false)
+ , mExpectedUploadCost(0)
+ , mUploadingTexturesCount(0)
+{
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ mAssetID = item->getAssetUUID();
+ }
+}
+
+BOOL LLMaterialEditor::postBuild()
+{
+ mAlbedoTextureCtrl = getChild<LLTextureCtrl>("albedo_texture");
+ mMetallicTextureCtrl = getChild<LLTextureCtrl>("metallic_roughness_texture");
+ mEmissiveTextureCtrl = getChild<LLTextureCtrl>("emissive_texture");
+ mNormalTextureCtrl = getChild<LLTextureCtrl>("normal_texture");
+
+ mAlbedoTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitAlbedoTexture, this, _1, _2));
+ mMetallicTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitMetallicTexture, this, _1, _2));
+ mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitEmissiveTexture, this, _1, _2));
+ mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitNormalTexture, this, _1, _2));
+
+ childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this));
+ childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this));
+ childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this));
+
+ S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+ getChild<LLUICtrl>("albedo_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+
+ boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void*)
+ {
+ setHasUnsavedChanges(true);
+ // Apply changes to object live
+ applyToSelection();
+ };
+
+ childSetCommitCallback("double sided", changes_callback, NULL);
+
+ // Albedo
+ childSetCommitCallback("albedo color", changes_callback, NULL);
+ childSetCommitCallback("transparency", changes_callback, NULL);
+ childSetCommitCallback("alpha mode", changes_callback, NULL);
+ childSetCommitCallback("alpha cutoff", changes_callback, NULL);
+
+ // Metallic-Roughness
+ childSetCommitCallback("metalness factor", changes_callback, NULL);
+ childSetCommitCallback("roughness factor", changes_callback, NULL);
+
+ // Metallic-Roughness
+ childSetCommitCallback("metalness factor", changes_callback, NULL);
+ childSetCommitCallback("roughness factor", changes_callback, NULL);
+
+ // Emissive
+ childSetCommitCallback("emissive color", changes_callback, NULL);
+
+ childSetVisible("unsaved_changes", mHasUnsavedChanges);
+
+ // Todo:
+ // Disable/enable setCanApplyImmediately() based on
+ // working from inventory, upload or editing inworld
+
+ return LLPreview::postBuild();
+}
+
+void LLMaterialEditor::onClickCloseBtn(bool app_quitting)
+{
+ if (app_quitting)
+ {
+ closeFloater(app_quitting);
+ }
+ else
+ {
+ onClickCancel();
+ }
+}
+
+LLUUID LLMaterialEditor::getAlbedoId()
+{
+ return mAlbedoTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setAlbedoId(const LLUUID& id)
+{
+ mAlbedoTextureCtrl->setValue(id);
+ mAlbedoTextureCtrl->setDefaultImageAssetID(id);
+}
+
+void LLMaterialEditor::setAlbedoUploadId(const LLUUID& id)
+{
+ // Might be better to use local textures and
+ // assign a fee in case of a local texture
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("albedo_upload_fee", getString("upload_fee_string"));
+ // Only set if we will need to upload this texture
+ mAlbedoTextureUploadId = id;
+ }
+ setHasUnsavedChanges(true);
+}
+
+LLColor4 LLMaterialEditor::getAlbedoColor()
+{
+ LLColor4 ret = LLColor4(childGetValue("albedo color"));
+ ret.mV[3] = getTransparency();
+ return ret;
+}
+
+void LLMaterialEditor::setAlbedoColor(const LLColor4& color)
+{
+ childSetValue("albedo color", color.getValue());
+ setTransparency(color.mV[3]);
+}
+
+F32 LLMaterialEditor::getTransparency()
+{
+ return childGetValue("transparency").asReal();
+}
+
+void LLMaterialEditor::setTransparency(F32 transparency)
+{
+ childSetValue("transparency", transparency);
+}
+
+std::string LLMaterialEditor::getAlphaMode()
+{
+ return childGetValue("alpha mode").asString();
+}
+
+void LLMaterialEditor::setAlphaMode(const std::string& alpha_mode)
+{
+ childSetValue("alpha mode", alpha_mode);
+}
+
+F32 LLMaterialEditor::getAlphaCutoff()
+{
+ return childGetValue("alpha cutoff").asReal();
+}
+
+void LLMaterialEditor::setAlphaCutoff(F32 alpha_cutoff)
+{
+ childSetValue("alpha cutoff", alpha_cutoff);
+}
+
+void LLMaterialEditor::setMaterialName(const std::string &name)
+{
+ setTitle(name);
+ mMaterialName = name;
+}
+
+LLUUID LLMaterialEditor::getMetallicRoughnessId()
+{
+ return mMetallicTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setMetallicRoughnessId(const LLUUID& id)
+{
+ mMetallicTextureCtrl->setValue(id);
+ mMetallicTextureCtrl->setDefaultImageAssetID(id);
+}
+
+void LLMaterialEditor::setMetallicRoughnessUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("metallic_upload_fee", getString("upload_fee_string"));
+ mMetallicTextureUploadId = id;
+ }
+ setHasUnsavedChanges(true);
+}
+
+F32 LLMaterialEditor::getMetalnessFactor()
+{
+ return childGetValue("metalness factor").asReal();
+}
+
+void LLMaterialEditor::setMetalnessFactor(F32 factor)
+{
+ childSetValue("metalness factor", factor);
+}
+
+F32 LLMaterialEditor::getRoughnessFactor()
+{
+ return childGetValue("roughness factor").asReal();
+}
+
+void LLMaterialEditor::setRoughnessFactor(F32 factor)
+{
+ childSetValue("roughness factor", factor);
+}
+
+LLUUID LLMaterialEditor::getEmissiveId()
+{
+ return mEmissiveTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setEmissiveId(const LLUUID& id)
+{
+ mEmissiveTextureCtrl->setValue(id);
+ mEmissiveTextureCtrl->setDefaultImageAssetID(id);
+}
+
+void LLMaterialEditor::setEmissiveUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("emissive_upload_fee", getString("upload_fee_string"));
+ mEmissiveTextureUploadId = id;
+ }
+ setHasUnsavedChanges(true);
+}
+
+LLColor4 LLMaterialEditor::getEmissiveColor()
+{
+ return LLColor4(childGetValue("emissive color"));
+}
+
+void LLMaterialEditor::setEmissiveColor(const LLColor4& color)
+{
+ childSetValue("emissive color", color.getValue());
+}
+
+LLUUID LLMaterialEditor::getNormalId()
+{
+ return mNormalTextureCtrl->getValue().asUUID();
+}
+
+void LLMaterialEditor::setNormalId(const LLUUID& id)
+{
+ mNormalTextureCtrl->setValue(id);
+ mNormalTextureCtrl->setDefaultImageAssetID(id);
+}
+
+void LLMaterialEditor::setNormalUploadId(const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ // todo: this does not account for posibility of texture
+ // being from inventory, need to check that
+ childSetValue("normal_upload_fee", getString("upload_fee_string"));
+ mNormalTextureUploadId = id;
+ }
+ setHasUnsavedChanges(true);
+}
+
+bool LLMaterialEditor::getDoubleSided()
+{
+ return childGetValue("double sided").asBoolean();
+}
+
+void LLMaterialEditor::setDoubleSided(bool double_sided)
+{
+ childSetValue("double sided", double_sided);
+}
+
+void LLMaterialEditor::setHasUnsavedChanges(bool value)
+{
+ if (value != mHasUnsavedChanges)
+ {
+ mHasUnsavedChanges = value;
+ childSetVisible("unsaved_changes", value);
+ }
+
+ S32 upload_texture_count = 0;
+ if (mAlbedoTextureUploadId.notNull() && mAlbedoTextureUploadId == getAlbedoId())
+ {
+ upload_texture_count++;
+ }
+ if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId())
+ {
+ upload_texture_count++;
+ }
+ if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId())
+ {
+ upload_texture_count++;
+ }
+ if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId())
+ {
+ upload_texture_count++;
+ }
+
+ mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost();
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+}
+
+void LLMaterialEditor::setCanSaveAs(BOOL value)
+{
+ childSetEnabled("save_as", value);
+}
+
+void LLMaterialEditor::setCanSave(BOOL value)
+{
+ childSetEnabled("save", value);
+}
+
+void LLMaterialEditor::onCommitAlbedoTexture(LLUICtrl * ctrl, const LLSD & data)
+{
+ // might be better to use arrays, to have a single callback
+ // and not to repeat the same thing for each tecture control
+ LLUUID new_val = mAlbedoTextureCtrl->getValue().asUUID();
+ if (new_val == mAlbedoTextureUploadId && mAlbedoTextureUploadId.notNull())
+ {
+ childSetValue("albedo_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ // Texture picker has 'apply now' with 'cancel' support.
+ // Keep mAlbedoJ2C and mAlbedoFetched, it's our storage in
+ // case user decides to cancel changes.
+ // Without mAlbedoFetched, viewer will eventually cleanup
+ // the texture that is not in use
+ childSetValue("albedo_upload_fee", getString("no_upload_fee_string"));
+ }
+ setHasUnsavedChanges(true);
+ applyToSelection();
+}
+
+void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data)
+{
+ LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID();
+ if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull())
+ {
+ childSetValue("metallic_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
+ }
+ setHasUnsavedChanges(true);
+ applyToSelection();
+}
+
+void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data)
+{
+ LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID();
+ if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull())
+ {
+ childSetValue("emissive_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
+ }
+ setHasUnsavedChanges(true);
+ applyToSelection();
+}
+
+void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data)
+{
+ LLUUID new_val = mNormalTextureCtrl->getValue().asUUID();
+ if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull())
+ {
+ childSetValue("normal_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
+ }
+ setHasUnsavedChanges(true);
+ applyToSelection();
+}
+
+
+static void write_color(const LLColor4& color, std::vector<double>& c)
+{
+ for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component
+ {
+ c[i] = color.mV[i];
+ }
+}
+
+static U32 write_texture(const LLUUID& id, tinygltf::Model& model)
+{
+ tinygltf::Image image;
+ image.uri = id.asString();
+ model.images.push_back(image);
+ U32 image_idx = model.images.size() - 1;
+
+ tinygltf::Texture texture;
+ texture.source = image_idx;
+ model.textures.push_back(texture);
+ U32 texture_idx = model.textures.size() - 1;
+
+ return texture_idx;
+}
+
+
+void LLMaterialEditor::onClickSave()
+{
+ if (!can_afford_transaction(mExpectedUploadCost))
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", mExpectedUploadCost);
+ LLNotificationsUtil::add("ErrorCannotAffordUpload", args);
+ return;
+ }
+
+ applyToSelection();
+ saveIfNeeded();
+}
+
+
+std::string LLMaterialEditor::getGLTFJson(bool prettyprint)
+{
+ tinygltf::Model model;
+ getGLTFModel(model);
+
+ std::ostringstream str;
+
+ tinygltf::TinyGLTF gltf;
+
+ gltf.WriteGltfSceneToStream(&model, str, prettyprint, false);
+
+ std::string dump = str.str();
+
+ return dump;
+}
+
+void LLMaterialEditor::getGLBData(std::vector<U8>& data)
+{
+ tinygltf::Model model;
+ getGLTFModel(model);
+
+ std::ostringstream str;
+
+ tinygltf::TinyGLTF gltf;
+
+ gltf.WriteGltfSceneToStream(&model, str, false, true);
+
+ std::string dump = str.str();
+
+ data.resize(dump.length());
+
+ memcpy(&data[0], dump.c_str(), dump.length());
+}
+
+void LLMaterialEditor::getGLTFModel(tinygltf::Model& model)
+{
+ model.materials.resize(1);
+ tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness;
+
+ // write albedo
+ LLColor4 albedo_color = getAlbedoColor();
+ albedo_color.mV[3] = getTransparency();
+ write_color(albedo_color, pbrMaterial.baseColorFactor);
+
+ model.materials[0].alphaCutoff = getAlphaCutoff();
+ model.materials[0].alphaMode = getAlphaMode();
+
+ LLUUID albedo_id = getAlbedoId();
+
+ if (albedo_id.notNull())
+ {
+ U32 texture_idx = write_texture(albedo_id, model);
+
+ pbrMaterial.baseColorTexture.index = texture_idx;
+ }
+
+ // write metallic/roughness
+ F32 metalness = getMetalnessFactor();
+ F32 roughness = getRoughnessFactor();
+
+ pbrMaterial.metallicFactor = metalness;
+ pbrMaterial.roughnessFactor = roughness;
+
+ LLUUID mr_id = getMetallicRoughnessId();
+ if (mr_id.notNull())
+ {
+ U32 texture_idx = write_texture(mr_id, model);
+ pbrMaterial.metallicRoughnessTexture.index = texture_idx;
+ }
+
+ //write emissive
+ LLColor4 emissive_color = getEmissiveColor();
+ model.materials[0].emissiveFactor.resize(3);
+ write_color(emissive_color, model.materials[0].emissiveFactor);
+
+ LLUUID emissive_id = getEmissiveId();
+ if (emissive_id.notNull())
+ {
+ U32 idx = write_texture(emissive_id, model);
+ model.materials[0].emissiveTexture.index = idx;
+ }
+
+ //write normal
+ LLUUID normal_id = getNormalId();
+ if (normal_id.notNull())
+ {
+ U32 idx = write_texture(normal_id, model);
+ model.materials[0].normalTexture.index = idx;
+ }
+
+ //write doublesided
+ model.materials[0].doubleSided = getDoubleSided();
+
+ model.asset.version = "2.0";
+}
+
+std::string LLMaterialEditor::getEncodedAsset()
+{
+ LLSD asset;
+ asset["version"] = "1.0";
+ asset["type"] = "GLTF 2.0";
+ asset["data"] = getGLTFJson(false);
+
+ std::ostringstream str;
+ LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY);
+
+ return str.str();
+}
+
+bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)
+{
+ LLSD asset;
+
+ std::istrstream str(&buffer[0], buffer.size());
+ if (LLSDSerialize::deserialize(asset, str, buffer.size()))
+ {
+ if (asset.has("version") && asset["version"] == "1.0")
+ {
+ if (asset.has("type") && asset["type"] == "GLTF 2.0")
+ {
+ if (asset.has("data") && asset["data"].isString())
+ {
+ std::string data = asset["data"];
+
+ tinygltf::TinyGLTF gltf;
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ tinygltf::Model model_in;
+
+ if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))
+ {
+ return setFromGltfModel(model_in, true);
+ }
+ else
+ {
+ LL_WARNS() << "Failed to decode material asset: " << LL_ENDL;
+ LL_WARNS() << warn_msg << LL_ENDL;
+ LL_WARNS() << error_msg << LL_ENDL;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Failed to deserialize material LLSD" << LL_ENDL;
+ }
+
+ return false;
+}
+
+bool LLMaterialEditor::saveIfNeeded()
+{
+ if (mUploadingTexturesCount > 0)
+ {
+ // upload already in progress
+ // wait until textures upload
+ // will retry saving on callback
+ return true;
+ }
+
+ if (saveTextures() > 0)
+ {
+ // started texture upload
+ setEnabled(false);
+ return true;
+ }
+
+ std::string buffer = getEncodedAsset();
+
+ const LLInventoryItem* item = getItem();
+ // save it out to database
+ if (item)
+ {
+ if (!saveToInventoryItem(buffer, mItemUUID, mObjectUUID))
+ {
+ return false;
+ }
+
+ if (mCloseAfterSave)
+ {
+ closeFloater();
+ }
+ else
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ setEnabled(false);
+ }
+ }
+ else
+ { //make a new inventory item
+#if 1
+ // gen a new uuid for this asset
+ LLTransactionID tid;
+ tid.generate(); // timestamp-based randomization + uniquification
+ LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ std::string res_desc = "Saved Material";
+ U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner();
+ LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ?
+
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, mMaterialName, res_desc,
+ LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm,
+ new LLBoostFuncInventoryCallback([output = buffer](LLUUID const& inv_item_id) {
+ // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem()
+ LLResourceUploadInfo::ptr_t uploadInfo =
+ std::make_shared<LLBufferedAssetUploadInfo>(
+ inv_item_id,
+ LLAssetType::AT_MATERIAL,
+ output,
+ [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) {
+ LL_INFOS("Material") << "inventory item uploaded. item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL;
+ LLSD params = llsd::map("ASSET_ID", new_asset_id);
+ LLNotificationsUtil::add("MaterialCreated", params);
+ });
+
+ // todo: apply permissions from textures here if server doesn't
+ // if any texture is 'no transfer', material should be 'no transfer' as well
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string agent_url(region->getCapability("UpdateMaterialAgentInventory"));
+ if (agent_url.empty())
+ {
+ LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL;
+ }
+ LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+ }
+ })
+ );
+
+ // We do not update floater with uploaded asset yet, so just close it.
+ closeFloater();
+#endif
+ }
+
+ return true;
+}
+
+// static
+bool LLMaterialEditor::saveToInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id)
+{
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (!region)
+ {
+ LL_WARNS() << "Not connected to a region, cannot save material." << LL_ENDL;
+ return false;
+ }
+ std::string agent_url = region->getCapability("UpdateMaterialAgentInventory");
+ std::string task_url = region->getCapability("UpdateMaterialTaskInventory");
+
+ if (!agent_url.empty() && !task_url.empty())
+ {
+ std::string url;
+ LLResourceUploadInfo::ptr_t uploadInfo;
+
+ if (task_id.isNull() && !agent_url.empty())
+ {
+ uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(item_id, LLAssetType::AT_MATERIAL, buffer,
+ [](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD) {
+ LLMaterialEditor::finishInventoryUpload(itemId, newAssetId, newItemId);
+ });
+ url = agent_url;
+ }
+ else if (!task_id.isNull() && !task_url.empty())
+ {
+ LLUUID object_uuid(task_id);
+ uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(task_id, item_id, LLAssetType::AT_MATERIAL, buffer,
+ [object_uuid](LLUUID itemId, LLUUID, LLUUID newAssetId, LLSD) {
+ LLMaterialEditor::finishTaskUpload(itemId, newAssetId, object_uuid);
+ });
+ url = task_url;
+ }
+
+ if (!url.empty() && uploadInfo)
+ {
+ LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ else // !gAssetStorage
+ {
+ LL_WARNS() << "Not connected to an materials capable region." << LL_ENDL;
+ return false;
+ }
+
+ // todo: apply permissions from textures here if server doesn't
+ // if any texture is 'no transfer', material should be 'no transfer' as well
+
+ return true;
+}
+
+void LLMaterialEditor::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId)
+{
+ // Update the UI with the new asset.
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId));
+ if (me)
+ {
+ if (newItemId.isNull())
+ {
+ me->setAssetId(newAssetId);
+ me->refreshFromInventory();
+ }
+ else if (newItemId.notNull())
+ {
+ // Not supposed to happen?
+ me->refreshFromInventory(newItemId);
+ }
+ else
+ {
+ me->refreshFromInventory(itemId);
+ }
+ }
+}
+
+void LLMaterialEditor::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId)
+{
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(itemId));
+ if (me)
+ {
+ me->setAssetId(newAssetId);
+ me->refreshFromInventory();
+ }
+}
+
+void LLMaterialEditor::finishSaveAs(const LLUUID &oldItemId, const LLUUID &newItemId, const std::string &buffer)
+{
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(oldItemId));
+ LLViewerInventoryItem* item = gInventory.getItem(newItemId);
+ if (item)
+ {
+ if (me)
+ {
+ me->mItemUUID = newItemId;
+ me->setKey(LLSD(newItemId)); // for findTypedInstance
+ me->setMaterialName(item->getName());
+ if (!saveToInventoryItem(buffer, newItemId, LLUUID::null))
+ {
+ me->setEnabled(true);
+ }
+ }
+ else
+ {
+ saveToInventoryItem(buffer, newItemId, LLUUID::null);
+ }
+ }
+ else if (me)
+ {
+ me->setEnabled(true);
+ LL_WARNS() << "Item does not exist" << LL_ENDL;
+ }
+}
+
+void LLMaterialEditor::refreshFromInventory(const LLUUID& new_item_id)
+{
+ if (new_item_id.notNull())
+ {
+ mItemUUID = new_item_id;
+ setKey(LLSD(new_item_id));
+ }
+ LL_DEBUGS() << "LLPreviewNotecard::refreshFromInventory()" << LL_ENDL;
+ loadAsset();
+}
+
+
+void LLMaterialEditor::onClickSaveAs()
+{
+ if (!can_afford_transaction(mExpectedUploadCost))
+ {
+ LLSD args;
+ args["COST"] = llformat("%d", mExpectedUploadCost);
+ LLNotificationsUtil::add("ErrorCannotAffordUpload", args);
+ return;
+ }
+
+ LLSD args;
+ args["DESC"] = mMaterialName;
+
+ LLNotificationsUtil::add("SaveMaterialAs", args, LLSD(), boost::bind(&LLMaterialEditor::onSaveAsMsgCallback, this, _1, _2));
+}
+
+void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ std::string new_name = response["message"].asString();
+ LLInventoryObject::correctInventoryName(new_name);
+ if (!new_name.empty())
+ {
+ const LLInventoryItem* item = getItem();
+ if (item)
+ {
+ const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+ LLUUID parent_id = item->getParentUUID();
+ if (mObjectUUID.notNull() || marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()))
+ {
+ parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ }
+
+ // A two step process, first copy an existing item, then create new asset
+ std::string buffer = getEncodedAsset();
+ LLPointer<LLInventoryCallback> cb = new LLMaterialEditorCopiedCallback(buffer, item->getUUID());
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ new_name,
+ cb);
+
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ setEnabled(false);
+ }
+ else
+ {
+ setMaterialName(new_name);
+ onClickSave();
+ }
+ }
+ else
+ {
+ LLNotificationsUtil::add("InvalidMaterialName");
+ }
+ }
+}
+
+void LLMaterialEditor::onClickCancel()
+{
+ if (mHasUnsavedChanges)
+ {
+ LLNotificationsUtil::add("UsavedMaterialChanges", LLSD(), LLSD(), boost::bind(&LLMaterialEditor::onCancelMsgCallback, this, _1, _2));
+ }
+ else
+ {
+ closeFloater();
+ }
+}
+
+void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ closeFloater();
+ }
+}
+
+class LLMaterialFilePicker : public LLFilePickerThread
+{
+public:
+ LLMaterialFilePicker(LLMaterialEditor* me);
+ virtual void notify(const std::vector<std::string>& filenames);
+ void loadMaterial(const std::string& filename);
+ static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata);
+private:
+ LLMaterialEditor* mME;
+};
+
+LLMaterialFilePicker::LLMaterialFilePicker(LLMaterialEditor* me)
+ : LLFilePickerThread(LLFilePicker::FFLOAD_MATERIAL)
+{
+ mME = me;
+}
+
+void LLMaterialFilePicker::notify(const std::vector<std::string>& filenames)
+{
+ if (LLAppViewer::instance()->quitRequested())
+ {
+ return;
+ }
+
+
+ if (filenames.size() > 0)
+ {
+ loadMaterial(filenames[0]);
+ }
+}
+
+const tinygltf::Image* get_image_from_texture_index(const tinygltf::Model& model, S32 texture_index)
+{
+ if (texture_index >= 0)
+ {
+ S32 source_idx = model.textures[texture_index].source;
+ if (source_idx >= 0)
+ {
+ return &(model.images[source_idx]);
+ }
+ }
+
+ return nullptr;
+}
+
+static LLImageRaw* get_texture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name)
+{
+ const tinygltf::Image* image = get_image_from_texture_index(model, texture_index);
+ LLImageRaw* rawImage = nullptr;
+
+ if (image != nullptr &&
+ image->bits == 8 &&
+ !image->image.empty() &&
+ image->component <= 4)
+ {
+ name = image->name;
+ rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component);
+ rawImage->verticalFlip();
+ }
+
+ return rawImage;
+}
+
+static void strip_alpha_channel(LLPointer<LLImageRaw>& img)
+{
+ if (img->getComponents() == 4)
+ {
+ LLImageRaw* tmp = new LLImageRaw(img->getWidth(), img->getHeight(), 3);
+ tmp->copyUnscaled4onto3(img);
+ img = tmp;
+ }
+}
+
+// copy red channel from src_img to dst_img
+// PRECONDITIONS:
+// dst_img must be 3 component
+// src_img and dst_image must have the same dimensions
+static void copy_red_channel(LLPointer<LLImageRaw>& src_img, LLPointer<LLImageRaw>& dst_img)
+{
+ llassert(src_img->getWidth() == dst_img->getWidth() && src_img->getHeight() == dst_img->getHeight());
+ llassert(dst_img->getComponents() == 3);
+
+ U32 pixel_count = dst_img->getWidth() * dst_img->getHeight();
+ U8* src = src_img->getData();
+ U8* dst = dst_img->getData();
+ S8 src_components = src_img->getComponents();
+
+ for (U32 i = 0; i < pixel_count; ++i)
+ {
+ dst[i * 3] = src[i * src_components];
+ }
+}
+
+static void pack_textures(tinygltf::Model& model, tinygltf::Material& material,
+ LLPointer<LLImageRaw>& albedo_img,
+ LLPointer<LLImageRaw>& normal_img,
+ LLPointer<LLImageRaw>& mr_img,
+ LLPointer<LLImageRaw>& emissive_img,
+ LLPointer<LLImageRaw>& occlusion_img,
+ LLPointer<LLViewerFetchedTexture>& albedo_tex,
+ LLPointer<LLViewerFetchedTexture>& normal_tex,
+ LLPointer<LLViewerFetchedTexture>& mr_tex,
+ LLPointer<LLViewerFetchedTexture>& emissive_tex,
+ LLPointer<LLImageJ2C>& albedo_j2c,
+ LLPointer<LLImageJ2C>& normal_j2c,
+ LLPointer<LLImageJ2C>& mr_j2c,
+ LLPointer<LLImageJ2C>& emissive_j2c)
+{
+ if (albedo_img)
+ {
+ albedo_tex = LLViewerTextureManager::getFetchedTexture(albedo_img, FTType::FTT_LOCAL_FILE, true);
+ albedo_j2c = LLViewerTextureList::convertToUploadFile(albedo_img);
+ }
+
+ if (normal_img)
+ {
+ strip_alpha_channel(normal_img);
+ normal_tex = LLViewerTextureManager::getFetchedTexture(normal_img, FTType::FTT_LOCAL_FILE, true);
+ normal_j2c = LLViewerTextureList::convertToUploadFile(normal_img);
+ }
+
+ if (mr_img)
+ {
+ strip_alpha_channel(mr_img);
+
+ if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index)
+ {
+ // occlusion is a distinct texture from pbrMetallicRoughness
+ // pack into mr red channel
+ int occlusion_idx = material.occlusionTexture.index;
+ int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (occlusion_idx != mr_idx)
+ {
+ //scale occlusion image to match resolution of mr image
+ occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight());
+
+ copy_red_channel(occlusion_img, mr_img);
+ }
+ }
+ }
+ else if (occlusion_img)
+ {
+ //no mr but occlusion exists, make a white mr_img and copy occlusion red channel over
+ mr_img = new LLImageRaw(occlusion_img->getWidth(), occlusion_img->getHeight(), 3);
+ mr_img->clear(255, 255, 255);
+ copy_red_channel(occlusion_img, mr_img);
+
+ }
+
+ if (mr_img)
+ {
+ mr_tex = LLViewerTextureManager::getFetchedTexture(mr_img, FTType::FTT_LOCAL_FILE, true);
+ mr_j2c = LLViewerTextureList::convertToUploadFile(mr_img);
+ }
+
+ if (emissive_img)
+ {
+ strip_alpha_channel(emissive_img);
+ emissive_tex = LLViewerTextureManager::getFetchedTexture(emissive_img, FTType::FTT_LOCAL_FILE, true);
+ emissive_j2c = LLViewerTextureList::convertToUploadFile(emissive_img);
+ }
+}
+
+static LLColor4 get_color(const std::vector<double>& in)
+{
+ LLColor4 out;
+ for (S32 i = 0; i < llmin((S32) in.size(), 4); ++i)
+ {
+ out.mV[i] = in[i];
+ }
+
+ return out;
+}
+
+void LLMaterialFilePicker::textureLoadedCallback(BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata)
+{
+}
+
+
+void LLMaterialFilePicker::loadMaterial(const std::string& filename)
+{
+ tinygltf::TinyGLTF loader;
+ std::string error_msg;
+ std::string warn_msg;
+
+ bool loaded = false;
+ tinygltf::Model model_in;
+
+ std::string filename_lc = filename;
+ LLStringUtil::toLower(filename_lc);
+
+ // Load a tinygltf model fom a file. Assumes that the input filename has already been
+ // been sanitized to one of (.gltf , .glb) extensions, so does a simple find to distinguish.
+ if (std::string::npos == filename_lc.rfind(".gltf"))
+ { // file is binary
+ loaded = loader.LoadBinaryFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+ else
+ { // file is ascii
+ loaded = loader.LoadASCIIFromFile(&model_in, &error_msg, &warn_msg, filename);
+ }
+
+ if (!loaded)
+ {
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ if (model_in.materials.empty())
+ {
+ // materials are missing
+ LLNotificationsUtil::add("CannotUploadMaterial");
+ return;
+ }
+
+ std::string folder = gDirUtilp->getDirName(filename);
+
+
+ tinygltf::Material material_in = model_in.materials[0];
+
+ tinygltf::Model model_out;
+ model_out.asset.version = "2.0";
+ model_out.materials.resize(1);
+
+ // get albedo texture
+ LLPointer<LLImageRaw> albedo_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, mME->mAlbedoName);
+ // get normal map
+ LLPointer<LLImageRaw> normal_img = get_texture(folder, model_in, material_in.normalTexture.index, mME->mNormalName);
+ // get metallic-roughness texture
+ LLPointer<LLImageRaw> mr_img = get_texture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, mME->mMetallicRoughnessName);
+ // get emissive texture
+ LLPointer<LLImageRaw> emissive_img = get_texture(folder, model_in, material_in.emissiveTexture.index, mME->mEmissiveName);
+ // get occlusion map if needed
+ LLPointer<LLImageRaw> occlusion_img;
+ if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index)
+ {
+ std::string tmp;
+ occlusion_img = get_texture(folder, model_in, material_in.occlusionTexture.index, tmp);
+ }
+
+ pack_textures(model_in, material_in, albedo_img, normal_img, mr_img, emissive_img, occlusion_img,
+ mME->mAlbedoFetched, mME->mNormalFetched, mME->mMetallicRoughnessFetched, mME->mEmissiveFetched,
+ mME->mAlbedoJ2C, mME->mNormalJ2C, mME->mMetallicRoughnessJ2C, mME->mEmissiveJ2C);
+
+ LLUUID albedo_id;
+ if (mME->mAlbedoFetched.notNull())
+ {
+ mME->mAlbedoFetched->forceToSaveRawImage(0, F32_MAX);
+ albedo_id = mME->mAlbedoFetched->getID();
+
+ if (mME->mAlbedoName.empty())
+ {
+ mME->mAlbedoName = MATERIAL_ALBEDO_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID normal_id;
+ if (mME->mNormalFetched.notNull())
+ {
+ mME->mNormalFetched->forceToSaveRawImage(0, F32_MAX);
+ normal_id = mME->mNormalFetched->getID();
+
+ if (mME->mNormalName.empty())
+ {
+ mME->mNormalName = MATERIAL_NORMAL_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID mr_id;
+ if (mME->mMetallicRoughnessFetched.notNull())
+ {
+ mME->mMetallicRoughnessFetched->forceToSaveRawImage(0, F32_MAX);
+ mr_id = mME->mMetallicRoughnessFetched->getID();
+
+ if (mME->mMetallicRoughnessName.empty())
+ {
+ mME->mMetallicRoughnessName = MATERIAL_METALLIC_DEFAULT_NAME;
+ }
+ }
+
+ LLUUID emissive_id;
+ if (mME->mEmissiveFetched.notNull())
+ {
+ mME->mEmissiveFetched->forceToSaveRawImage(0, F32_MAX);
+ emissive_id = mME->mEmissiveFetched->getID();
+
+ if (mME->mEmissiveName.empty())
+ {
+ mME->mEmissiveName = MATERIAL_EMISSIVE_DEFAULT_NAME;
+ }
+ }
+
+ mME->setAlbedoId(albedo_id);
+ mME->setAlbedoUploadId(albedo_id);
+ mME->setMetallicRoughnessId(mr_id);
+ mME->setMetallicRoughnessUploadId(mr_id);
+ mME->setEmissiveId(emissive_id);
+ mME->setEmissiveUploadId(emissive_id);
+ mME->setNormalId(normal_id);
+ mME->setNormalUploadId(normal_id);
+
+ mME->setFromGltfModel(model_in);
+
+ std::string new_material = LLTrans::getString("New Material");
+ mME->setMaterialName(new_material);
+
+ mME->setHasUnsavedChanges(true);
+ mME->openFloater();
+
+ mME->applyToSelection();
+}
+
+bool LLMaterialEditor::setFromGltfModel(tinygltf::Model& model, bool set_textures)
+{
+ if (model.materials.size() > 0)
+ {
+ tinygltf::Material& material_in = model.materials[0];
+
+ if (set_textures)
+ {
+ S32 index;
+ LLUUID id;
+
+ // get albedo texture
+ index = material_in.pbrMetallicRoughness.baseColorTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setAlbedoId(id);
+ }
+ else
+ {
+ setAlbedoId(LLUUID::null);
+ }
+
+ // get normal map
+ index = material_in.normalTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setNormalId(id);
+ }
+ else
+ {
+ setNormalId(LLUUID::null);
+ }
+
+ // get metallic-roughness texture
+ index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setMetallicRoughnessId(id);
+ }
+ else
+ {
+ setMetallicRoughnessId(LLUUID::null);
+ }
+
+ // get emissive texture
+ index = material_in.emissiveTexture.index;
+ if (index >= 0)
+ {
+ id.set(model.images[index].uri);
+ setEmissiveId(id);
+ }
+ else
+ {
+ setEmissiveId(LLUUID::null);
+ }
+ }
+
+ setAlphaMode(material_in.alphaMode);
+ setAlphaCutoff(material_in.alphaCutoff);
+
+ setAlbedoColor(get_color(material_in.pbrMetallicRoughness.baseColorFactor));
+ setEmissiveColor(get_color(material_in.emissiveFactor));
+
+ setMetalnessFactor(material_in.pbrMetallicRoughness.metallicFactor);
+ setRoughnessFactor(material_in.pbrMetallicRoughness.roughnessFactor);
+
+ setDoubleSided(material_in.doubleSided);
+ }
+
+ return true;
+}
+
+void LLMaterialEditor::importMaterial()
+{
+ (new LLMaterialFilePicker(this))->getFile();
+}
+
+void LLMaterialEditor::applyToSelection()
+{
+ // Todo: fix this, this is a hack, not a proper live preview
+ LLViewerObject* objectp = LLSelectMgr::instance().getSelection()->getFirstObject();
+ if (objectp && objectp->getVolume() && objectp->permModify())
+ {
+ LLGLTFMaterial* mat = new LLGLTFMaterial();
+ getGLTFMaterial(mat);
+ LLVOVolume* vobjp = (LLVOVolume*)objectp;
+ for (int i = 0; i < vobjp->getNumTEs(); ++i)
+ {
+ // this is here just to prevent material from immediately resetting
+ if (mAssetID.notNull())
+ {
+ vobjp->setRenderMaterialID(i, mAssetID);
+ }
+ else
+ {
+ const LLUUID placeholder("984e183e-7811-4b05-a502-d79c6f978a98");
+ vobjp->setRenderMaterialID(i, placeholder);
+ }
+
+ vobjp->getTE(i)->setGLTFMaterial(mat);
+ vobjp->updateTEMaterialTextures(i);
+ }
+
+ vobjp->markForUpdate(TRUE);
+ }
+}
+
+void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)
+{
+ mat->mAlbedoColor = getAlbedoColor();
+ mat->mAlbedoColor.mV[3] = getTransparency();
+ mat->mAlbedoId = getAlbedoId();
+
+ mat->mNormalId = getNormalId();
+
+ mat->mMetallicRoughnessId = getMetallicRoughnessId();
+ mat->mMetallicFactor = getMetalnessFactor();
+ mat->mRoughnessFactor = getRoughnessFactor();
+
+ mat->mEmissiveColor = getEmissiveColor();
+ mat->mEmissiveId = getEmissiveId();
+
+ mat->mDoubleSided = getDoubleSided();
+ mat->setAlphaMode(getAlphaMode());
+}
+
+void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)
+{
+ setAlbedoColor(mat->mAlbedoColor);
+ setAlbedoId(mat->mAlbedoId);
+ setNormalId(mat->mNormalId);
+
+ setMetallicRoughnessId(mat->mMetallicRoughnessId);
+ setMetalnessFactor(mat->mMetallicFactor);
+ setRoughnessFactor(mat->mRoughnessFactor);
+
+ setEmissiveColor(mat->mEmissiveColor);
+ setEmissiveId(mat->mEmissiveId);
+
+ setDoubleSided(mat->mDoubleSided);
+ setAlphaMode(mat->getAlphaMode());
+}
+
+void LLMaterialEditor::loadAsset()
+{
+ // derived from LLPreviewNotecard::loadAsset
+
+ // TODO: see commented out "editor" references and make them do something appropriate to the UI
+
+ // request the asset.
+ const LLInventoryItem* item = getItem();
+
+ bool fail = false;
+
+ if (item)
+ {
+ LLPermissions perm(item->getPermissions());
+ BOOL allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE);
+ BOOL allow_modify = canModify(mObjectUUID, item);
+ BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID());
+
+ setCanSaveAs(allow_copy);
+ setCanSave(allow_modify && !source_library);
+ setMaterialName(item->getName());
+
+ {
+ mAssetID = item->getAssetUUID();
+ if (mAssetID.isNull())
+ {
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ setHasUnsavedChanges(false);
+ }
+ else
+ {
+ LLHost source_sim = LLHost();
+ LLSD* user_data = new LLSD();
+
+ if (mObjectUUID.notNull())
+ {
+ LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
+ if (objectp && objectp->getRegion())
+ {
+ source_sim = objectp->getRegion()->getHost();
+ }
+ else
+ {
+ // The object that we're trying to look at disappeared, bail.
+ LL_WARNS() << "Can't find object " << mObjectUUID << " associated with notecard." << LL_ENDL;
+ mAssetID.setNull();
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ setHasUnsavedChanges(false);
+ return;
+ }
+ user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);
+ }
+ else
+ {
+ user_data = new LLSD(mItemUUID);
+ }
+
+ gAssetStorage->getInvItemAsset(source_sim,
+ gAgent.getID(),
+ gAgent.getSessionID(),
+ item->getPermissions().getOwner(),
+ mObjectUUID,
+ item->getUUID(),
+ item->getAssetUUID(),
+ item->getType(),
+ &onLoadComplete,
+ (void*)user_data,
+ TRUE);
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ }
+ }
+ }
+ else if (mObjectUUID.notNull() && mItemUUID.notNull())
+ {
+ LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
+ if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty()))
+ {
+ // It's a material in object's inventory and we failed to get it because inventory is not up to date.
+ // Subscribe for callback and retry at inventoryChanged()
+ registerVOInventoryListener(objectp, NULL); //removes previous listener
+
+ if (objectp->isInventoryDirty())
+ {
+ objectp->requestInventory();
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+
+ if (fail)
+ {
+ /*editor->setText(LLStringUtil::null);
+ editor->makePristine();
+ editor->setEnabled(TRUE);*/
+ // Don't set asset status here; we may not have set the item id yet
+ // (e.g. when this gets called initially)
+ //mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+}
+
+// static
+void LLMaterialEditor::onLoadComplete(const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status)
+{
+ LL_INFOS() << "LLMaterialEditor::onLoadComplete()" << LL_ENDL;
+ LLSD* floater_key = (LLSD*)user_data;
+ LLMaterialEditor* editor = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", *floater_key);
+ if (editor)
+ {
+ if (0 == status)
+ {
+ LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
+
+ S32 file_length = file.getSize();
+
+ std::vector<char> buffer(file_length + 1);
+ file.read((U8*)&buffer[0], file_length);
+
+ editor->decodeAsset(buffer);
+
+ BOOL modifiable = editor->canModify(editor->mObjectID, editor->getItem());
+ editor->setEnabled(modifiable);
+ editor->setHasUnsavedChanges(false);
+ editor->mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+ else
+ {
+ if (LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
+ LL_ERR_FILE_EMPTY == status)
+ {
+ LLNotificationsUtil::add("MaterialMissing");
+ }
+ else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
+ {
+ LLNotificationsUtil::add("MaterialNoPermissions");
+ }
+ else
+ {
+ LLNotificationsUtil::add("UnableToLoadMaterial");
+ }
+
+ LL_WARNS() << "Problem loading material: " << status << LL_ENDL;
+ editor->mAssetStatus = PREVIEW_ASSET_ERROR;
+ }
+ }
+ delete floater_key;
+}
+
+void LLMaterialEditor::inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data)
+{
+ removeVOInventoryListener();
+ loadAsset();
+}
+
+
+void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb)
+{
+ if (asset_id.isNull()
+ || img == nullptr
+ || img->getDataSize() == 0)
+ {
+ return;
+ }
+
+ // copy image bytes into string
+ std::string buffer;
+ buffer.assign((const char*) img->getData(), img->getDataSize());
+
+ U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+
+
+ LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewBufferedResourceUploadInfo>(
+ buffer,
+ asset_id,
+ name,
+ name,
+ 0,
+ LLFolderType::FT_TEXTURE,
+ LLInventoryType::IT_TEXTURE,
+ LLAssetType::AT_TEXTURE,
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
+ expected_upload_cost,
+ false,
+ cb));
+
+ upload_new_resource(uploadInfo);
+}
+
+S32 LLMaterialEditor::saveTextures()
+{
+ S32 work_count = 0;
+ LLSD key = getKey(); // must be locally declared for lambda's capture to work
+ if (mAlbedoTextureUploadId == getAlbedoId() && mAlbedoTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mAlbedoJ2C, mAlbedoName, mAlbedoTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setAlbedoId(newAssetId);
+ }
+ else
+ {
+ // To make sure that we won't retry (some failures can cb immediately)
+ me->setAlbedoId(LLUUID::null);
+ }
+ me->mUploadingTexturesCount--;
+
+ // try saving
+ me->saveIfNeeded();
+ }
+ });
+ }
+ if (mNormalTextureUploadId == getNormalId() && mNormalTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mNormalJ2C, mNormalName, mNormalTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setNormalId(newAssetId);
+ }
+ else
+ {
+ me->setNormalId(LLUUID::null);
+ }
+ me->setNormalId(newAssetId);
+ me->mUploadingTexturesCount--;
+
+ // try saving
+ me->saveIfNeeded();
+ }
+ });
+ }
+ if (mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mMetallicRoughnessJ2C, mMetallicRoughnessName, mMetallicTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", key);
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setMetallicRoughnessId(newAssetId);
+ }
+ else
+ {
+ me->setMetallicRoughnessId(LLUUID::null);
+ }
+ me->mUploadingTexturesCount--;
+
+ // try saving
+ me->saveIfNeeded();
+ }
+ });
+ }
+
+ if (mEmissiveTextureUploadId == getEmissiveId() && mEmissiveTextureUploadId.notNull())
+ {
+ mUploadingTexturesCount++;
+ work_count++;
+ saveTexture(mEmissiveJ2C, mEmissiveName, mEmissiveTextureUploadId, [key](LLUUID newAssetId, LLSD response)
+ {
+ LLMaterialEditor* me = LLFloaterReg::findTypedInstance<LLMaterialEditor>("material_editor", LLSD(key));
+ if (me)
+ {
+ if (response["success"].asBoolean())
+ {
+ me->setEmissiveId(newAssetId);
+ }
+ else
+ {
+ me->setEmissiveId(LLUUID::null);
+ }
+ me->mUploadingTexturesCount--;
+
+ // try saving
+ me->saveIfNeeded();
+ }
+ });
+ }
+
+ // discard upload buffers once textures have been saved
+ mAlbedoJ2C = nullptr;
+ mNormalJ2C = nullptr;
+ mEmissiveJ2C = nullptr;
+ mMetallicRoughnessJ2C = nullptr;
+
+ mAlbedoFetched = nullptr;
+ mNormalFetched = nullptr;
+ mMetallicRoughnessFetched = nullptr;
+ mEmissiveFetched = nullptr;
+
+ mAlbedoTextureUploadId.setNull();
+ mNormalTextureUploadId.setNull();
+ mMetallicTextureUploadId.setNull();
+ mEmissiveTextureUploadId.setNull();
+
+ // asset storage can callback immediately, causing a decrease
+ // of mUploadingTexturesCount, report amount of work scheduled
+ // not amount of work remaining
+ return work_count;
+}
+
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
new file mode 100644
index 0000000000..3da59c7f93
--- /dev/null
+++ b/indra/newview/llmaterialeditor.h
@@ -0,0 +1,200 @@
+/**
+ * @file llmaterialeditor.h
+ * @brief LLMaterialEditor class header file
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llpreview.h"
+#include "llvoinventorylistener.h"
+#include "llimagej2c.h"
+#include "llviewertexture.h"
+
+class LLTextureCtrl;
+
+namespace tinygltf
+{
+ class Model;
+}
+
+class LLGLTFMaterial;
+
+class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
+{
+public:
+ LLMaterialEditor(const LLSD& key);
+
+ bool setFromGltfModel(tinygltf::Model& model, bool set_textures = false);
+
+ // open a file dialog and select a gltf/glb file for import
+ void importMaterial();
+
+ // for live preview, apply current material to currently selected object
+ void applyToSelection();
+
+ void getGLTFMaterial(LLGLTFMaterial* mat);
+
+ void setFromGLTFMaterial(LLGLTFMaterial* mat);
+
+ void loadAsset() override;
+
+ static void onLoadComplete(const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status);
+
+ void inventoryChanged(LLViewerObject* object, LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) override;
+
+ typedef std::function<void(LLUUID newAssetId, LLSD response)> upload_callback_f;
+ void saveTexture(LLImageJ2C* img, const std::string& name, const LLUUID& asset_id, upload_callback_f cb);
+
+ // save textures to inventory if needed
+ // returns amount of scheduled uploads
+ S32 saveTextures();
+
+ void onClickSave();
+
+ // get a dump of the json representation of the current state of the editor UI in GLTF format
+ std::string getGLTFJson(bool prettyprint = true);
+
+ void getGLBData(std::vector<U8>& data);
+
+ void getGLTFModel(tinygltf::Model& model);
+
+ std::string getEncodedAsset();
+
+ bool decodeAsset(const std::vector<char>& buffer);
+
+ bool saveIfNeeded();
+ static bool saveToInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id);
+
+ static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId);
+
+ static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId);
+
+ static void finishSaveAs(const LLUUID &oldItemId, const LLUUID &newItemId, const std::string &buffer);
+
+ void refreshFromInventory(const LLUUID& new_item_id = LLUUID::null);
+
+ void onClickSaveAs();
+ void onSaveAsMsgCallback(const LLSD& notification, const LLSD& response);
+ void onClickCancel();
+ void onCancelMsgCallback(const LLSD& notification, const LLSD& response);
+
+ // llpanel
+ BOOL postBuild() override;
+ void onClickCloseBtn(bool app_quitting = false) override;
+
+ LLUUID getAlbedoId();
+ void setAlbedoId(const LLUUID& id);
+ void setAlbedoUploadId(const LLUUID& id);
+
+ LLColor4 getAlbedoColor();
+
+ // sets both albedo color and transparency
+ void setAlbedoColor(const LLColor4& color);
+
+ F32 getTransparency();
+ void setTransparency(F32 transparency);
+
+ std::string getAlphaMode();
+ void setAlphaMode(const std::string& alpha_mode);
+
+ F32 getAlphaCutoff();
+ void setAlphaCutoff(F32 alpha_cutoff);
+
+ void setMaterialName(const std::string &name);
+
+ LLUUID getMetallicRoughnessId();
+ void setMetallicRoughnessId(const LLUUID& id);
+ void setMetallicRoughnessUploadId(const LLUUID& id);
+
+ F32 getMetalnessFactor();
+ void setMetalnessFactor(F32 factor);
+
+ F32 getRoughnessFactor();
+ void setRoughnessFactor(F32 factor);
+
+ LLUUID getEmissiveId();
+ void setEmissiveId(const LLUUID& id);
+ void setEmissiveUploadId(const LLUUID& id);
+
+ LLColor4 getEmissiveColor();
+ void setEmissiveColor(const LLColor4& color);
+
+ LLUUID getNormalId();
+ void setNormalId(const LLUUID& id);
+ void setNormalUploadId(const LLUUID& id);
+
+ bool getDoubleSided();
+ void setDoubleSided(bool double_sided);
+
+ void setHasUnsavedChanges(bool value);
+ void setCanSaveAs(BOOL value);
+ void setCanSave(BOOL value);
+
+ void onCommitAlbedoTexture(LLUICtrl* ctrl, const LLSD& data);
+ void onCommitMetallicTexture(LLUICtrl* ctrl, const LLSD& data);
+ void onCommitEmissiveTexture(LLUICtrl* ctrl, const LLSD& data);
+ void onCommitNormalTexture(LLUICtrl* ctrl, const LLSD& data);
+
+private:
+ friend class LLMaterialFilePicker;
+
+ LLUUID mAssetID;
+ LLUUID mObjectID;
+
+ LLTextureCtrl* mAlbedoTextureCtrl;
+ LLTextureCtrl* mMetallicTextureCtrl;
+ LLTextureCtrl* mEmissiveTextureCtrl;
+ LLTextureCtrl* mNormalTextureCtrl;
+
+ // 'Default' texture, unless it's null or from inventory is the one with the fee
+ LLUUID mAlbedoTextureUploadId;
+ LLUUID mMetallicTextureUploadId;
+ LLUUID mEmissiveTextureUploadId;
+ LLUUID mNormalTextureUploadId;
+
+ // last known name of each texture
+ std::string mAlbedoName;
+ std::string mNormalName;
+ std::string mMetallicRoughnessName;
+ std::string mEmissiveName;
+
+ // keep pointers to fetched textures or viewer will remove them
+ // if user temporary selects something else with 'apply now'
+ LLPointer<LLViewerFetchedTexture> mAlbedoFetched;
+ LLPointer<LLViewerFetchedTexture> mNormalFetched;
+ LLPointer<LLViewerFetchedTexture> mMetallicRoughnessFetched;
+ LLPointer<LLViewerFetchedTexture> mEmissiveFetched;
+
+ // J2C versions of packed buffers for uploading
+ LLPointer<LLImageJ2C> mAlbedoJ2C;
+ LLPointer<LLImageJ2C> mNormalJ2C;
+ LLPointer<LLImageJ2C> mMetallicRoughnessJ2C;
+ LLPointer<LLImageJ2C> mEmissiveJ2C;
+
+ bool mHasUnsavedChanges;
+ S32 mUploadingTexturesCount;
+ S32 mExpectedUploadCost;
+ std::string mMaterialName;
+};
+
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 3bca4fde83..c3fbada9db 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -30,6 +30,7 @@
#include "llmodelloader.h"
#include "lldaeloader.h"
+#include "llgltfloader.h"
#include "llfloatermodelpreview.h"
#include "llagent.h"
@@ -732,20 +733,41 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
std::map<std::string, std::string> joint_alias_map;
getJointAliases(joint_alias_map);
- mModelLoader = new LLDAELoader(
- filename,
- lod,
- &LLModelPreview::loadedCallback,
- &LLModelPreview::lookupJointByName,
- &LLModelPreview::loadTextures,
- &LLModelPreview::stateChangedCallback,
- this,
- mJointTransformMap,
- mJointsFromNode,
- joint_alias_map,
- LLSkinningUtil::getMaxJointCount(),
- gSavedSettings.getU32("ImporterModelLimit"),
- gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+ // three possible file extensions, .dae .gltf .glb
+ // check for .dae and if not then assume one of the .gl??
+ if (std::string::npos != filename.rfind(".dae"))
+ {
+ mModelLoader = new LLDAELoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"),
+ gSavedSettings.getBOOL("ImporterPreprocessDAE"));
+ }
+ else
+ {
+ mModelLoader = new LLGLTFLoader(
+ filename,
+ lod,
+ &LLModelPreview::loadedCallback,
+ &LLModelPreview::lookupJointByName,
+ &LLModelPreview::loadTextures,
+ &LLModelPreview::stateChangedCallback,
+ this,
+ mJointTransformMap,
+ mJointsFromNode,
+ joint_alias_map,
+ LLSkinningUtil::getMaxJointCount(),
+ gSavedSettings.getU32("ImporterModelLimit"));
+ }
if (force_disable_slm)
{
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index a169712bd8..d17845ebc5 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -108,6 +108,8 @@ namespace
const std::string FIELD_SKY_DENSITY_DROPLET_RADIUS("droplet_radius");
const std::string FIELD_SKY_DENSITY_ICE_LEVEL("ice_level");
+ const std::string FIELD_REFLECTION_PROBE_AMBIANCE("probe_ambiance");
+
const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f);
const F32 SLIDER_SCALE_GLOW_R(20.0f);
@@ -150,6 +152,7 @@ BOOL LLPanelSettingsSkyAtmosTab::postBuild()
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); });
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); });
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); });
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setCommitCallback([this](LLUICtrl*, const LLSD&) { onReflectionProbeAmbianceChanged(); });
refresh();
return TRUE;
@@ -172,6 +175,7 @@ void LLPanelSettingsSkyAtmosTab::setEnabled(BOOL enabled)
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled);
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setEnabled(enabled);
}
}
@@ -203,10 +207,12 @@ void LLPanelSettingsSkyAtmosTab::refresh()
F32 moisture_level = mSkySettings->getSkyMoistureLevel();
F32 droplet_radius = mSkySettings->getSkyDropletRadius();
F32 ice_level = mSkySettings->getSkyIceLevel();
+ F32 rp_ambiance = mSkySettings->getReflectionProbeAmbiance();
getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius);
getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level);
+ getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->setValue(rp_ambiance);
}
//-------------------------------------------------------------------------
@@ -311,6 +317,15 @@ void LLPanelSettingsSkyAtmosTab::onIceLevelChanged()
setIsDirty();
}
+void LLPanelSettingsSkyAtmosTab::onReflectionProbeAmbianceChanged()
+{
+ if (!mSkySettings) return;
+ F32 ambiance = getChild<LLUICtrl>(FIELD_REFLECTION_PROBE_AMBIANCE)->getValue().asReal();
+ mSkySettings->setReflectionProbeAmbiance(ambiance);
+ mSkySettings->update();
+ setIsDirty();
+}
+
//==========================================================================
LLPanelSettingsSkyCloudTab::LLPanelSettingsSkyCloudTab() :
LLPanelSettingsSky()
diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h
index cb63d40b0c..cd89e02eea 100644
--- a/indra/newview/llpaneleditsky.h
+++ b/indra/newview/llpaneleditsky.h
@@ -79,6 +79,7 @@ private:
void onMoistureLevelChanged();
void onDropletRadiusChanged();
void onIceLevelChanged();
+ void onReflectionProbeAmbianceChanged();
};
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 7fe5b1dd3f..ec67a9cdc6 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -76,6 +76,18 @@
#include "llpluginclassmedia.h"
#include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI
+
+
+#include "llagent.h"
+#include "llfilesystem.h"
+#include "llviewerassetupload.h"
+#include "llviewermenufile.h"
+#include "llsd.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "llinventorymodel.h"
+
+
//
// Constant definitions for comboboxes
// Must match the commbobox definitions in panel_tools_texture.xml
@@ -130,6 +142,7 @@ F32 LLPanelFace::getCurrentShinyScaleU() { return getChild<LLUICtrl>("shinySca
F32 LLPanelFace::getCurrentShinyScaleV() { return getChild<LLUICtrl>("shinyScaleV")->getValue().asReal(); }
F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild<LLUICtrl>("shinyOffsetU")->getValue().asReal(); }
F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild<LLUICtrl>("shinyOffsetV")->getValue().asReal(); }
+LLUUID LLPanelFace::getCurrentMaterialID() { return getChild<LLUICtrl>("materialID")->getValue().asUUID(); }
//
// Methods
@@ -161,9 +174,11 @@ BOOL LLPanelFace::postBuild()
childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this);
childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this);
childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this);
+ childSetCommitCallback("materialID", &LLPanelFace::onCommitMaterialID, this);
childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
childSetAction("button align textures", &LLPanelFace::onAlignTexture, this);
+ childSetAction("button save material", &LLPanelFace::onSaveMaterial, this);
LLTextureCtrl* mTextureCtrl;
LLTextureCtrl* mShinyTextureCtrl;
@@ -1427,7 +1442,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
LLMaterialPtr material;
LLSelectedTEMaterial::getCurrent(material, identical);
- if (material && editable)
+ // enable this UI box if a single face is selected.
+ BOOL is_single_face = !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected();
+ childSetEnabled("button save material", static_cast<bool>(is_single_face));
+ childSetEnabled("materialID", static_cast<bool>(is_single_face)); // doesn't work - why?
+
+ // TODO: 2022-04 conflicts with media button placement. hide the button if applying media
+ // i.e. childSetVisible("button save material", !applying_media);
+
+ if (material && editable)
{
LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
@@ -1539,6 +1562,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
+
+ getChildView("materialID")->setEnabled(editable);
}
else
{
@@ -2334,6 +2359,17 @@ void LLPanelFace::onCommitMaterialMaskCutoff(LLUICtrl* ctrl, void* userdata)
LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff());
}
+//static
+void LLPanelFace::onCommitMaterialID(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = static_cast<LLPanelFace*>(userdata);
+ LLUUID matID = self->getCurrentMaterialID();
+ LLSelectedTEMaterial::setMaterialID(self, matID);
+
+ // Temporary demo hack - replace the TE entries with those from the Material's LLSD
+ applyMaterialUUID(matID, userdata);
+}
+
// static
void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata )
{
@@ -3660,3 +3696,197 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic
} max_diff_repeats_func;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
}
+
+
+void LLPanelFace::onSaveMaterial(void* userdata)
+{
+ // DRTVWR-559, Q&D material picker - save to inventory goes here
+ LL_DEBUGS("Material") << "saving render material to inventory" << LL_ENDL;
+
+ std::string name = "New Material";
+
+ LLSD material_data = llsd::map(
+ "version", "1",
+ "material", LLSD::emptyMap()
+ );
+
+ // gen a new uuid for this asset
+ LLTransactionID tid;
+ tid.generate(); // timestamp-based randomization + uniquification
+ LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+ material_data["material"] = renderMaterialToLLSD(new_asset_id, userdata);
+ std::stringstream output;
+ LLSDSerialize::toNotation(material_data, output);
+
+ //S32 expected_upload_cost = 0;// LLAgentBenefitsMgr::current().getTextureUploadCost();
+
+ std::string res_name = name;
+ std::string res_desc = "Saved Material";
+ //LLFolderType::EType folder_type = LLFolderType::FT_MATERIAL;
+ //LLInventoryType::EType inv_type = LLInventoryType::IT_MATERIAL;
+ U32 next_owner_perm = LLPermissions::DEFAULT.getMaskNextOwner();
+
+ LLUUID parent = gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ?
+
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(), parent, tid, res_name, res_desc,
+ LLAssetType::AT_MATERIAL, LLInventoryType::IT_MATERIAL, subtype, next_owner_perm,
+ new LLBoostFuncInventoryCallback([output=output.str()](LLUUID const & inv_item_id){
+ // from reference in LLSettingsVOBase::createInventoryItem()/updateInventoryItem()
+ LLResourceUploadInfo::ptr_t uploadInfo =
+ std::make_shared<LLBufferedAssetUploadInfo>(
+ inv_item_id,
+ LLAssetType::AT_SETTINGS, // TODO switch to AT_MATERIAL
+ output,
+ [](LLUUID item_id, LLUUID new_asset_id, LLUUID new_item_id, LLSD response) {
+ LL_INFOS("Material") << "inventory item uploaded. item: " << item_id << " asset: " << new_asset_id << " new_item_id: " << new_item_id << " response: " << response << LL_ENDL;
+ LLSD params = llsd::map("ASSET_ID", new_asset_id);
+ LLNotificationsUtil::add("MaterialCreated", params);
+ });
+
+ const LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+ if (agent_url.empty())
+ {
+ LL_ERRS() << "missing required agent inventory cap url" << LL_ENDL;
+ }
+ LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+ }
+ })
+ );
+
+}
+
+// Fill an LLSD with data describing the current face's texture settings
+// TODO 2022-05 FUBAR there are both colliding and different data in LLPanelFace vs the TE. Also, neither one has the diffuse tex settings.
+//
+LLSD LLPanelFace::renderMaterialToLLSD(LLUUID uuid, void* userdata)
+{
+ llassert(userdata != nullptr);
+
+ LLSD sd;
+
+ sd.insert("RenderMaterialUUID", LLSD(uuid));
+
+ // now pull same data from the selected TE (same but different. W T F?)
+ LLMaterialPtr mat = nullptr;
+ bool ident; // ?
+ LLSelectedTEMaterial::getCurrent(mat, ident);
+
+ if (mat)
+ {
+ sd.insert("teMaterialID", LLSD(mat->getMaterialID()));
+
+ sd.insert("teNormalMap", LLSD(mat->getNormalID()));
+ sd.insert("teNormalOffsetX", LLSD(mat->getNormalOffsetX()));
+ sd.insert("teNormalOffsetY", LLSD(mat->getNormalOffsetY()));
+ sd.insert("teNormalRepeatX", LLSD(mat->getNormalRepeatX()));
+ sd.insert("teNormalRepeatY", LLSD(mat->getNormalRepeatY()));
+ sd.insert("teNormalRotation", LLSD(mat->getNormalRotation()));
+
+ sd.insert("teSpecularMap", LLSD(mat->getSpecularID()));
+ LLColor4U color = mat->getSpecularLightColor();
+
+ sd.insert("teSpecularColorR", LLSD(static_cast<S32>(color.mV[0])));
+ sd.insert("teSpecularColorG", LLSD(static_cast<S32>(color.mV[1])));
+ sd.insert("teSpecularColorB", LLSD(static_cast<S32>(color.mV[2])));
+ sd.insert("teSpecularColorA", LLSD(static_cast<S32>(color.mV[3])));
+ sd.insert("teSpecularExponent", LLSD(static_cast<S32>(mat->getSpecularLightExponent())));
+ sd.insert("teSpecularOffsetX", LLSD(mat->getSpecularOffsetX()));
+ sd.insert("teSpecularOffsetY", LLSD(mat->getSpecularOffsetY()));
+ sd.insert("teSpecularRepeatX", LLSD(mat->getSpecularRepeatX()));
+ sd.insert("teSpecularRepeatY", LLSD(mat->getSpecularRepeatY()));
+ sd.insert("teSpecularRotation", LLSD(mat->getSpecularRotation()));
+
+ sd.insert("teAlphaMode", LLSD(static_cast<S32>(mat->getDiffuseAlphaMode())));
+ sd.insert("teAlphaCutoff", LLSD(static_cast<S32>(mat->getAlphaMaskCutoff())));
+ sd.insert("teEnvIntensity", LLSD(static_cast<S32>(mat->getEnvironmentIntensity())));
+ sd.insert("teShaderMask", LLSD(static_cast<S32>(mat->getShaderMask())));
+ }
+ else
+ {
+ // pull data from the LLPanelFace
+ LLPanelFace* instance = static_cast<LLPanelFace*>(userdata);
+ sd.insert("pfNormalMap", LLSD(instance->getCurrentNormalMap()));
+ sd.insert("pfSpecularMap", LLSD(instance->getCurrentSpecularMap()));
+ sd.insert("pfShininess", LLSD(static_cast<S32>(instance->getCurrentShininess())));
+ sd.insert("pfBumpiness", LLSD(static_cast<S32>(instance->getCurrentBumpiness())));
+ sd.insert("pfAlphaMode", LLSD(static_cast<S32>(instance->getCurrentDiffuseAlphaMode())));
+ sd.insert("pfAlphaCutoff", LLSD(static_cast<S32>(instance->getCurrentAlphaMaskCutoff())));
+ sd.insert("pfEnvIntensity", LLSD(static_cast<S32>(instance->getCurrentEnvIntensity())));
+ sd.insert("pfGlossiness", LLSD(static_cast<S32>(instance->getCurrentGlossiness())));
+ sd.insert("pfNormalRotation", LLSD(instance->getCurrentBumpyRot()));
+ sd.insert("pfNormalScaleU", LLSD(instance->getCurrentBumpyScaleU()));
+ sd.insert("pfNormalScaleV", LLSD(instance->getCurrentBumpyScaleV()));
+ sd.insert("pfNormalOffsetU", LLSD(instance->getCurrentBumpyOffsetU()));
+ sd.insert("pfNormalOffsetV", LLSD(instance->getCurrentBumpyOffsetV()));
+ sd.insert("pfSpecularRotation", LLSD(instance->getCurrentShinyRot()));
+ sd.insert("pfSpecularScaleU", LLSD(instance->getCurrentShinyScaleU()));
+ sd.insert("pfSpecularScaleV", LLSD(instance->getCurrentShinyScaleV()));
+ sd.insert("pfSpecularOffsetU", LLSD(instance->getCurrentShinyOffsetU()));
+ sd.insert("pfSpecularOffsetV", LLSD(instance->getCurrentShinyOffsetV()));
+ sd.insert("pfMaterialID", LLSD(instance->getCurrentMaterialID()));
+ }
+
+ return sd;
+}
+
+// Take the individual texture settings from the material and apply to current face & TE
+void LLPanelFace::applyMaterialUUID(LLUUID uuid, void* userdata)
+{
+ llassert(userdata != nullptr);
+ //LLPanelFace* instance = static_cast<LLPanelFace*>(userdata);
+
+ LLFileSystem material_file(uuid, LLAssetType::AT_MATERIAL, LLFileSystem::READ);
+ S32 bufsize = material_file.getSize();
+ llassert(bufsize > 0);
+ std::vector<U8> buffer(bufsize);
+ material_file.read(&buffer[0], bufsize);
+ std::istringstream input(std::string(buffer.begin(), buffer.end())); // TODO - extend LLFileSystem to expose iostream interface
+ LLSD matSD;
+
+ LLSDSerialize::fromNotation(matSD, input, bufsize);
+
+ LL_INFOS() << "dump matSD: " << matSD << LL_ENDL;
+
+ // strip off the versioning wrapper for now
+ matSD = matSD["material"];
+
+ // wrong, oops. llassert(uuid == matSD.get("RenderMaterialUUID").asUUID()); // if not, whoo boy
+
+ LLMaterialPtr mat = nullptr;
+ bool ident; // ?
+ LLSelectedTEMaterial::getCurrent(mat, ident);
+
+ mat->setMaterialID(matSD.get("teMaterialID").asUUID());
+
+ mat->setNormalID(matSD.get("teNormalMap").asUUID());
+ mat->setNormalOffsetX(matSD.get("teNormalOffsetX").asReal());
+ mat->setNormalOffsetY(matSD.get("teNormalOffsetY").asReal());
+ mat->setNormalRepeatX(matSD.get("teNormalRepeatX").asReal());
+ mat->setNormalRepeatY(matSD.get("teNormalRepeatY").asReal());
+ mat->setNormalRotation(matSD.get("teNormalRotation").asReal());
+
+ mat->setSpecularID(matSD.get("teSpecularMap").asUUID());
+ LLColor4U color;
+ color.mV[0] = static_cast<U8>(matSD.get("teSecularColorR").asInteger());
+ color.mV[1] = static_cast<U8>(matSD.get("teSecularColorG").asInteger());
+ color.mV[2] = static_cast<U8>(matSD.get("teSecularColorB").asInteger());
+ color.mV[3] = static_cast<U8>(matSD.get("teSecularColorA").asInteger());
+ mat->setSpecularLightColor(color);
+ mat->setSpecularLightExponent(static_cast<U8>(matSD.get("teSpecularExponent").asInteger()));
+ mat->setSpecularOffsetX(matSD.get("teSpecularOffsetX").asReal());
+ mat->setSpecularOffsetY(matSD.get("teSpecularOffsetY").asReal());
+ mat->setSpecularRepeatX(matSD.get("teSpecularRepeatX").asReal());
+ mat->setSpecularRepeatY(matSD.get("teSpecularRepeatY").asReal());
+ mat->setSpecularRotation(matSD.get("teSpecularRotation").asReal());
+
+ mat->setDiffuseAlphaMode(static_cast<U8>(matSD.get("teAlphaMode").asInteger()));
+ mat->setAlphaMaskCutoff(static_cast<U8>(matSD.get("teAlphaCutoff").asInteger()));
+ mat->setEnvironmentIntensity(static_cast<U8>(matSD.get("teEnvIntensity").asInteger()));
+ //mat->setShaderMask(static_cast<U32>(matSD.get(teShaderMask").asInteger());
+}
+
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index e3b925c1d4..08dc619402 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -196,6 +196,7 @@ protected:
static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata);
+ static void onCommitMaterialID( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata);
static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata);
@@ -210,6 +211,10 @@ protected:
static void onClickAutoFix(void*);
static void onAlignTexture(void*);
+ static void onSaveMaterial(void*);
+ static LLSD renderMaterialToLLSD(LLUUID uuid, void* userdata);
+ static void applyMaterialUUID(LLUUID uuid, void*);
+
public: // needs to be accessible to selection manager
void onCopyColor(); // records all selected faces
void onPasteColor(); // to specific face
@@ -250,6 +255,7 @@ private:
F32 getCurrentShinyScaleV();
F32 getCurrentShinyOffsetU();
F32 getCurrentShinyOffsetV();
+ LLUUID getCurrentMaterialID();
// Update visibility of controls to match current UI mode
// (e.g. materials vs media editing)
@@ -519,6 +525,7 @@ public:
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID);
DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID);
DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor);
+ DEF_EDIT_MAT_STATE(LLUUID, const LLUUID&, setMaterialID);
};
class LLSelectedTE
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index ab32ea3956..82f880c9ee 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -156,6 +156,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_CALLINGCARD:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 89256b40c4..49562da3f7 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -919,6 +919,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ getChild<LLUICtrl>("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL));
getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
@@ -975,6 +976,12 @@ void LLFloaterInventoryFinder::draw()
filtered_by_all_types = FALSE;
}
+ if (!getChild<LLUICtrl>("check_material")->getValue())
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_MATERIAL);
+ filtered_by_all_types = FALSE;
+ }
+
if (!getChild<LLUICtrl>("check_notecard")->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
@@ -1129,6 +1136,7 @@ void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
self->getChild<LLUICtrl>("check_clothing")->setValue(TRUE);
self->getChild<LLUICtrl>("check_gesture")->setValue(TRUE);
self->getChild<LLUICtrl>("check_landmark")->setValue(TRUE);
+ self->getChild<LLUICtrl>("check_material")->setValue(TRUE);
self->getChild<LLUICtrl>("check_notecard")->setValue(TRUE);
self->getChild<LLUICtrl>("check_object")->setValue(TRUE);
self->getChild<LLUICtrl>("check_script")->setValue(TRUE);
@@ -1149,6 +1157,7 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
self->getChild<LLUICtrl>("check_clothing")->setValue(FALSE);
self->getChild<LLUICtrl>("check_gesture")->setValue(FALSE);
self->getChild<LLUICtrl>("check_landmark")->setValue(FALSE);
+ self->getChild<LLUICtrl>("check_material")->setValue(FALSE);
self->getChild<LLUICtrl>("check_notecard")->setValue(FALSE);
self->getChild<LLUICtrl>("check_object")->setValue(FALSE);
self->getChild<LLUICtrl>("check_script")->setValue(FALSE);
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index cfaa9456be..2faa3a7137 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -715,6 +715,7 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_CALLINGCARD:
case DAD_MESH:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
if(accept && drop)
{
@@ -1162,6 +1163,56 @@ LLSettingsType::type_e LLTaskSettingsBridge::getSettingsType() const
}
///----------------------------------------------------------------------------
+/// Class LLTaskMaterialBridge
+///----------------------------------------------------------------------------
+
+class LLTaskMaterialBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskMaterialBridge(LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name) {}
+
+ BOOL canOpenItem() const override { return TRUE; }
+ void openItem() override;
+ BOOL removeItem() override;
+};
+
+void LLTaskMaterialBridge::openItem()
+{
+ LLViewerObject* object = gObjectList.findObject(mPanel->getTaskUUID());
+ if(!object || object->isInventoryPending())
+ {
+ return;
+ }
+
+ // Note: even if we are not allowed to modify copyable notecard, we should be able to view it
+ LLInventoryItem *item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mUUID));
+ BOOL item_copy = item && gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
+ if( item_copy
+ || object->permModify()
+ || gAgent.isGodlike())
+ {
+ LLSD floater_key;
+ floater_key["taskid"] = mPanel->getTaskUUID();
+ floater_key["itemid"] = mUUID;
+ LLPreviewNotecard* preview = LLFloaterReg::showTypedInstance<LLPreviewNotecard>("preview_notecard", floater_key, TAKE_FOCUS_YES);
+ if (preview)
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+ }
+}
+
+BOOL LLTaskMaterialBridge::removeItem()
+{
+ LLFloaterReg::hideInstance("preview_notecard", LLSD(mUUID));
+ return LLTaskInvFVBridge::removeItem();
+}
+
+
+///----------------------------------------------------------------------------
/// LLTaskInvFVBridge impl
//----------------------------------------------------------------------------
@@ -1248,6 +1299,11 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
object_name,
itemflags);
break;
+ case LLAssetType::AT_MATERIAL:
+ new_bridge = new LLTaskMaterialBridge(panel,
+ object_id,
+ object_name);
+ break;
default:
LL_INFOS() << "Unhandled inventory type (llassetstorage.h): "
<< (S32)type << LL_ENDL;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 5b02609a53..5c93271446 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -146,6 +146,15 @@ BOOL LLPanelVolume::postBuild()
getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
}
+ // REFLECTION PROBE Parameters
+ {
+ childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this);
+ childSetCommitCallback("Probe Dynamic", onCommitProbe, this);
+ childSetCommitCallback("Probe Volume Type", onCommitProbe, this);
+ childSetCommitCallback("Probe Ambiance", onCommitProbe, this);
+ childSetCommitCallback("Probe Near Clip", onCommitProbe, this);
+ }
+
// PHYSICS Parameters
{
// PhysicsShapeType combobox
@@ -366,6 +375,43 @@ void LLPanelVolume::getState( )
getChildView("Light Ambiance")->setEnabled(false);
}
+ // Reflection Probe
+ BOOL is_probe = volobjp && volobjp->isReflectionProbe();
+ getChild<LLUICtrl>("Reflection Probe")->setValue(is_probe);
+ getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp);
+
+ bool probe_enabled = is_probe && editable && single_volume;
+
+ getChildView("Probe Dynamic")->setEnabled(probe_enabled);
+ getChildView("Probe Volume Type")->setEnabled(probe_enabled);
+ getChildView("Probe Ambiance")->setEnabled(probe_enabled);
+ getChildView("Probe Near Clip")->setEnabled(probe_enabled);
+
+ if (!probe_enabled)
+ {
+ getChild<LLComboBox>("Probe Volume Type", true)->clear();
+ getChild<LLSpinCtrl>("Probe Ambiance", true)->clear();
+ getChild<LLSpinCtrl>("Probe Near Clip", true)->clear();
+ getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->clear();
+ }
+ else
+ {
+ std::string volume_type;
+ if (volobjp->getReflectionProbeIsBox())
+ {
+ volume_type = "Box";
+ }
+ else
+ {
+ volume_type = "Sphere";
+ }
+
+ getChild<LLComboBox>("Probe Volume Type", true)->setValue(volume_type);
+ getChild<LLSpinCtrl>("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance());
+ getChild<LLSpinCtrl>("Probe Near Clip", true)->setValue(volobjp->getReflectionProbeNearClip());
+ getChild<LLCheckBoxCtrl>("Probe Dynamic", true)->setValue(volobjp->getReflectionProbeIsDynamic());
+ }
+
// Animated Mesh
BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject();
getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh);
@@ -655,6 +701,11 @@ void LLPanelVolume::clearCtrls()
getChildView("Light Radius")->setEnabled(false);
getChildView("Light Falloff")->setEnabled(false);
+ getChildView("Reflection Probe")->setEnabled(false);;
+ getChildView("Probe Volume Type")->setEnabled(false);
+ getChildView("Probe Dynamic")->setEnabled(false);
+ getChildView("Probe Ambiance")->setEnabled(false);
+ getChildView("Probe Near Clip")->setEnabled(false);
getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
getChildView("FlexNumSections")->setEnabled(false);
@@ -692,6 +743,20 @@ void LLPanelVolume::sendIsLight()
LL_INFOS() << "update light sent" << LL_ENDL;
}
+void LLPanelVolume::sendIsReflectionProbe()
+{
+ LLViewerObject* objectp = mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+ BOOL value = getChild<LLUICtrl>("Reflection Probe")->getValue();
+ volobjp->setIsReflectionProbe(value);
+ LL_INFOS() << "update reflection probe sent" << LL_ENDL;
+}
+
void LLPanelVolume::sendIsFlexible()
{
LLViewerObject* objectp = mObject;
@@ -1219,6 +1284,27 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
}
+//static
+void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ LLViewerObject* objectp = self->mObject;
+ if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME))
+ {
+ return;
+ }
+ LLVOVolume* volobjp = (LLVOVolume*)objectp;
+
+
+ volobjp->setReflectionProbeAmbiance((F32)self->getChild<LLUICtrl>("Probe Ambiance")->getValue().asReal());
+ volobjp->setReflectionProbeNearClip((F32)self->getChild<LLUICtrl>("Probe Near Clip")->getValue().asReal());
+ volobjp->setReflectionProbeIsDynamic(self->getChild<LLUICtrl>("Probe Dynamic")->getValue().asBoolean());
+
+ std::string shape_type = self->getChild<LLUICtrl>("Probe Volume Type")->getValue().asString();
+
+ volobjp->setReflectionProbeIsBox(shape_type == "Box");
+}
+
// static
void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
{
@@ -1242,6 +1328,15 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item
//----------------------------------------------------------------------------
// static
+void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelVolume* self = (LLPanelVolume*)userdata;
+ self->sendIsReflectionProbe();
+}
+
+//----------------------------------------------------------------------------
+
+// static
void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
{
LLPanelVolume* self = (LLPanelVolume*) userdata;
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index d9198f3693..62a6d01b21 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -57,12 +57,15 @@ public:
void refresh();
void sendIsLight();
+ void sendIsReflectionProbe();
void sendIsFlexible();
static bool precommitValidate(const LLSD& data);
static void onCommitIsLight( LLUICtrl* ctrl, void* userdata);
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
+ static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata);
+ static void onCommitProbe(LLUICtrl* ctrl, void* userdata);
void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
void onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata);
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
new file mode 100644
index 0000000000..2a7ab84501
--- /dev/null
+++ b/indra/newview/llreflectionmap.cpp
@@ -0,0 +1,269 @@
+/**
+ * @file llreflectionmap.cpp
+ * @brief LLReflectionMap class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmap.h"
+#include "pipeline.h"
+#include "llviewerwindow.h"
+#include "llviewerregion.h"
+
+extern F32SecondsImplicit gFrameTimeSeconds;
+
+LLReflectionMap::LLReflectionMap()
+{
+}
+
+void LLReflectionMap::update(U32 resolution, U32 face)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ mLastUpdateTime = gFrameTimeSeconds;
+ llassert(mCubeArray.notNull());
+ llassert(mCubeIndex != -1);
+ llassert(LLPipeline::sRenderDeferred);
+
+ // make sure we don't walk off the edge of the render target
+ while (resolution > gPipeline.mRT->deferredScreen.getWidth() ||
+ resolution > gPipeline.mRT->deferredScreen.getHeight())
+ {
+ resolution /= 2;
+ }
+ gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic());
+}
+
+void LLReflectionMap::autoAdjustOrigin()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ if (mGroup)
+ {
+ const LLVector4a* bounds = mGroup->getBounds();
+ auto* node = mGroup->getOctreeNode();
+
+ if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
+ {
+ // for terrain, make probes float a couple meters above the highest point in the surface patch
+ mOrigin = bounds[0];
+ mOrigin.getF32ptr()[2] += bounds[1].getF32ptr()[2] + 3.f;
+
+ // update radius to encompass bounding box
+ LLVector4a d;
+ d.setAdd(bounds[0], bounds[1]);
+ d.sub(mOrigin);
+ mRadius = d.getLength3().getF32();
+ mPriority = 1;
+ }
+ else if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ mPriority = 1;
+ // cast a ray towards 8 corners of bounding box
+ // nudge origin towards center of empty space
+
+ if (node->isLeaf() || node->getChildCount() > 1 || node->getData().size() > 0)
+ { // use center of object bounding box for leaf nodes or nodes with multiple child nodes
+ mOrigin = bounds[0];
+
+ LLVector4a start;
+ LLVector4a end;
+
+ LLVector4a size = bounds[1];
+
+ LLVector4a corners[] =
+ {
+ { 1, 1, 1 },
+ { -1, 1, 1 },
+ { 1, -1, 1 },
+ { -1, -1, 1 },
+ { 1, 1, -1 },
+ { -1, 1, -1 },
+ { 1, -1, -1 },
+ { -1, -1, -1 }
+ };
+
+ for (int i = 0; i < 8; ++i)
+ {
+ corners[i].mul(size);
+ corners[i].add(bounds[0]);
+ }
+
+ LLVector4a extents[2];
+ extents[0].setAdd(bounds[0], bounds[1]);
+ extents[1].setSub(bounds[0], bounds[1]);
+
+ bool hit = false;
+ for (int i = 0; i < 8; ++i)
+ {
+ int face = -1;
+ LLVector4a intersection;
+ LLDrawable* drawable = mGroup->lineSegmentIntersect(bounds[0], corners[i], true, false, true, &face, &intersection);
+ if (drawable != nullptr)
+ {
+ hit = true;
+ update_min_max(extents[0], extents[1], intersection);
+ }
+ else
+ {
+ update_min_max(extents[0], extents[1], corners[i]);
+ }
+ }
+
+ if (hit)
+ {
+ mOrigin.setAdd(extents[0], extents[1]);
+ mOrigin.mul(0.5f);
+ }
+
+ // make sure radius encompasses all objects
+ LLSimdScalar r2 = 0.0;
+ for (int i = 0; i < 8; ++i)
+ {
+ LLVector4a v;
+ v.setSub(corners[i], mOrigin);
+
+ LLSimdScalar d = v.dot3(v);
+
+ if (d > r2)
+ {
+ r2 = d;
+ }
+ }
+
+ mRadius = llmax(sqrtf(r2.getF32()), 8.f);
+ }
+ else
+ {
+ // user placed probe
+ mPriority = 2;
+
+ // use center of octree node volume for nodes that are just branches without data
+ mOrigin = node->getCenter();
+
+ // update radius to encompass entire octree node volume
+ mRadius = node->getSize().getLength3().getF32();
+
+ //mOrigin = bounds[0];
+ //mRadius = bounds[1].getLength3().getF32();
+
+ }
+ }
+ }
+ else if (mViewerObject)
+ {
+ mPriority = 64;
+ mOrigin.load3(mViewerObject->getPositionAgent().mV);
+ mRadius = mViewerObject->getScale().mV[0]*0.5f;
+ }
+}
+
+bool LLReflectionMap::intersects(LLReflectionMap* other)
+{
+ // TODO: incorporate getBox
+ LLVector4a delta;
+ delta.setSub(other->mOrigin, mOrigin);
+
+ F32 dist = delta.dot3(delta).getF32();
+
+ F32 r2 = mRadius + other->mRadius;
+
+ r2 *= r2;
+
+ return dist < r2;
+}
+
+extern LLControlGroup gSavedSettings;
+
+F32 LLReflectionMap::getAmbiance()
+{
+ F32 ret = 0.f;
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance();
+ }
+
+ return ret;
+}
+
+F32 LLReflectionMap::getNearClip()
+{
+ const F32 MINIMUM_NEAR_CLIP = 0.1f;
+
+ F32 ret = 0.f;
+
+ if (mViewerObject && mViewerObject->getVolume())
+ {
+ ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeNearClip();
+ }
+
+ return llmax(ret, MINIMUM_NEAR_CLIP);
+}
+
+bool LLReflectionMap::getIsDynamic()
+{
+ if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY &&
+ mViewerObject &&
+ mViewerObject->getVolume())
+ {
+ return ((LLVOVolume*)mViewerObject)->getReflectionProbeIsDynamic();
+ }
+
+ return false;
+}
+
+bool LLReflectionMap::getBox(LLMatrix4& box)
+{
+ if (mViewerObject)
+ {
+ LLVolume* volume = mViewerObject->getVolume();
+ if (volume)
+ {
+ LLVOVolume* vobjp = (LLVOVolume*)mViewerObject;
+
+ if (vobjp->getReflectionProbeIsBox())
+ {
+ glh::matrix4f mv(gGLModelView);
+ glh::matrix4f scale;
+ LLVector3 s = vobjp->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f));
+ mRadius = s.magVec();
+ scale.set_scale(glh::vec3f(s.mV));
+ if (vobjp->mDrawable != nullptr)
+ {
+ glh::matrix4f rm((F32*)vobjp->mDrawable->getWorldMatrix().mMatrix);
+
+ glh::matrix4f rt((F32*)vobjp->getRelativeXform().mMatrix);
+
+ mv = mv * rm * scale; // *rt;
+ mv = mv.inverse();
+
+ box = LLMatrix4(mv.m);
+
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
new file mode 100644
index 0000000000..cf0bc2ff27
--- /dev/null
+++ b/indra/newview/llreflectionmap.h
@@ -0,0 +1,102 @@
+/**
+ * @file llreflectionmap.h
+ * @brief LLReflectionMap class declaration
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llcubemaparray.h"
+#include "llmemory.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+class alignas(16) LLReflectionMap : public LLRefCount
+{
+ LL_ALIGN_NEW
+public:
+ // allocate an environment map of the given resolution
+ LLReflectionMap();
+
+ // update this environment map
+ // resolution - size of cube map to generate
+ void update(U32 resolution, U32 face);
+
+ // for volume partition probes, try to place this probe in the best spot
+ void autoAdjustOrigin();
+
+ // return true if given Reflection Map's influence volume intersect's with this one's
+ bool intersects(LLReflectionMap* other);
+
+ // Get the ambiance value to use for this probe
+ F32 getAmbiance();
+
+ // Get the near clip plane distance to use for this probe
+ F32 getNearClip();
+
+ // Return true if this probe should include avatars in its reflection map
+ bool getIsDynamic();
+
+ // get the encoded bounding box of this probe's influence volume
+ // will only return a box if this probe is associated with a VOVolume
+ // with its reflection probe influence volume to to VOLUME_TYPE_BOX
+ // return false if no bounding box (treat as sphere influence volume)
+ bool getBox(LLMatrix4& box);
+
+ // point at which environment map was last generated from (in agent space)
+ LLVector4a mOrigin;
+
+ // distance from viewer camera
+ F32 mDistance;
+
+ // radius of this probe's affected area
+ F32 mRadius = 16.f;
+
+ // last time this probe was updated (or when its update timer got reset)
+ F32 mLastUpdateTime = 0.f;
+
+ // last time this probe was bound for rendering
+ F32 mLastBindTime = 0.f;
+
+ // cube map used to sample this environment map
+ LLPointer<LLCubeMapArray> mCubeArray;
+ S32 mCubeIndex = -1; // index into cube map array or -1 if not currently stored in cube map array
+
+ // index into array packed by LLReflectionMapManager::getReflectionMaps
+ // WARNING -- only valid immediately after call to getReflectionMaps
+ S32 mProbeIndex = -1;
+
+ // set of any LLReflectionMaps that intersect this map (maintained by LLReflectionMapManager
+ std::vector<LLReflectionMap*> mNeighbors;
+
+ // spatial group this probe is tracking (if any)
+ LLSpatialGroup* mGroup = nullptr;
+
+ // viewer object this probe is tracking (if any)
+ LLViewerObject* mViewerObject = nullptr;
+
+ // what priority should this probe have (higher is higher priority)
+ U32 mPriority = 1;
+};
+
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
new file mode 100644
index 0000000000..583c6de77b
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -0,0 +1,832 @@
+/**
+ * @file llreflectionmapmanager.cpp
+ * @brief LLReflectionMapManager class implementation
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llreflectionmapmanager.h"
+#include "llviewercamera.h"
+#include "llspatialpartition.h"
+#include "llviewerregion.h"
+#include "pipeline.h"
+#include "llviewershadermgr.h"
+#include "llviewercontrol.h"
+#include "llenvironment.h"
+
+extern BOOL gCubeSnapshot;
+extern BOOL gTeleportDisplay;
+
+LLReflectionMapManager::LLReflectionMapManager()
+{
+ for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i)
+ {
+ mCubeFree[i] = true;
+ }
+}
+
+struct CompareReflectionMapDistance
+{
+
+};
+
+
+struct CompareProbeDistance
+{
+ bool operator()(const LLPointer<LLReflectionMap>& lhs, const LLPointer<LLReflectionMap>& rhs)
+ {
+ return lhs->mDistance < rhs->mDistance;
+ }
+};
+
+// helper class to seed octree with probes
+void LLReflectionMapManager::update()
+{
+ if (!LLPipeline::sRenderPBR || gTeleportDisplay)
+ {
+ return;
+ }
+
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!gCubeSnapshot); // assert a snapshot is not in progress
+ if (LLAppViewer::instance()->logoutRequestSent())
+ {
+ return;
+ }
+
+ // =============== TODO -- move to an init function =================
+
+ if (mTexture.isNull())
+ {
+ mTexture = new LLCubeMapArray();
+ // 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())
+ {
+ U32 color_fmt = GL_RGBA;
+ const bool use_depth_buffer = true;
+ const bool use_stencil_buffer = true;
+ U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample
+ mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_RECT_TEXTURE);
+ }
+
+ if (mMipChain.empty())
+ {
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION;
+ U32 count = log2((F32)res) + 0.5f;
+
+ mMipChain.resize(count);
+ for (int i = 0; i < count; ++i)
+ {
+ mMipChain[i].allocate(res, res, GL_RGB, false, false, LLTexUnit::TT_RECT_TEXTURE);
+ res /= 2;
+ }
+ }
+
+
+ LLVector4a camera_pos;
+ camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
+
+ // process kill list
+ for (auto& probe : mKillList)
+ {
+ auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe);
+ if (iter != mProbes.end())
+ {
+ deleteProbe(iter - mProbes.begin());
+ }
+ }
+
+ mKillList.clear();
+
+ // process create list
+ for (auto& probe : mCreateList)
+ {
+ mProbes.push_back(probe);
+ }
+
+ mCreateList.clear();
+
+ if (mProbes.empty())
+ {
+ return;
+ }
+
+ bool did_update = false;
+
+ bool realtime = gSavedSettings.getS32("RenderReflectionProbeDetail") >= (S32)LLReflectionMapManager::DetailLevel::REALTIME;
+
+ LLReflectionMap* closestDynamic = nullptr;
+
+ LLReflectionMap* oldestProbe = nullptr;
+
+ if (mUpdatingProbe != nullptr)
+ {
+ did_update = true;
+ doProbeUpdate();
+ }
+
+ for (int i = 0; i < mProbes.size(); ++i)
+ {
+ LLReflectionMap* probe = mProbes[i];
+ if (probe->getNumRefs() == 1)
+ { // no references held outside manager, delete this probe
+ deleteProbe(i);
+ --i;
+ continue;
+ }
+
+ probe->mProbeIndex = i;
+
+ LLVector4a d;
+
+ if (!did_update &&
+ i < LL_REFLECTION_PROBE_COUNT &&
+ (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
+ {
+ oldestProbe = probe;
+ }
+
+ if (realtime &&
+ closestDynamic == nullptr &&
+ probe->mCubeArray.notNull() &&
+ probe->getIsDynamic())
+ {
+ closestDynamic = probe;
+ }
+
+ d.setSub(camera_pos, probe->mOrigin);
+ probe->mDistance = d.getLength3().getF32()-probe->mRadius;
+ }
+
+ if (realtime && closestDynamic != nullptr)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime");
+ // update the closest dynamic probe realtime
+ closestDynamic->autoAdjustOrigin();
+ for (U32 i = 0; i < 6; ++i)
+ {
+ updateProbeFace(closestDynamic, i);
+ }
+ }
+
+ // switch to updating the next oldest probe
+ if (!did_update && oldestProbe != nullptr)
+ {
+ LLReflectionMap* probe = oldestProbe;
+ if (probe->mCubeIndex == -1)
+ {
+ probe->mCubeArray = mTexture;
+ probe->mCubeIndex = allocateCubeIndex();
+ }
+
+ probe->autoAdjustOrigin();
+
+ mUpdatingProbe = probe;
+ doProbeUpdate();
+ }
+
+ // update distance to camera for all probes
+ std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
+}
+
+LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
+{
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mGroup = group;
+ probe->mOrigin = group->getOctreeNode()->getCenter();
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& maps)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ U32 count = 0;
+ U32 lastIdx = 0;
+ for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ mProbes[i]->mProbeIndex = count;
+ maps[count++] = mProbes[i];
+ }
+ else
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+ lastIdx = i;
+ }
+
+ // set remaining probe indices to -1
+ for (U32 i = lastIdx+1; i < mProbes.size(); ++i)
+ {
+ mProbes[i]->mProbeIndex = -1;
+ }
+
+ // null terminate list
+ if (count < maps.size())
+ {
+ maps[count] = nullptr;
+ }
+}
+
+LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)
+{
+#if 1
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 15.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+
+ if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
+ {
+ OctreeNode* node = group->getOctreeNode();
+ F32 size = node->getSize().getF32ptr()[0];
+ if (size >= 15.f && size <= 17.f)
+ {
+ return addProbe(group);
+ }
+ }
+#endif
+ return nullptr;
+}
+
+LLReflectionMap* LLReflectionMapManager::registerViewerObject(LLViewerObject* vobj)
+{
+ llassert(vobj != nullptr);
+
+ LLReflectionMap* probe = new LLReflectionMap();
+ probe->mViewerObject = vobj;
+ probe->mOrigin.load3(vobj->getPositionAgent().mV);
+
+ if (gCubeSnapshot)
+ { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
+ mCreateList.push_back(probe);
+ }
+ else
+ {
+ mProbes.push_back(probe);
+ }
+
+ return probe;
+}
+
+
+S32 LLReflectionMapManager::allocateCubeIndex()
+{
+ for (int i = 0; i < LL_REFLECTION_PROBE_COUNT; ++i)
+ {
+ if (mCubeFree[i])
+ {
+ mCubeFree[i] = false;
+ return i;
+ }
+ }
+
+ // no cubemaps free, steal one from the back of the probe list
+ for (int i = mProbes.size() - 1; i >= LL_REFLECTION_PROBE_COUNT; --i)
+ {
+ if (mProbes[i]->mCubeIndex != -1)
+ {
+ S32 ret = mProbes[i]->mCubeIndex;
+ mProbes[i]->mCubeIndex = -1;
+ return ret;
+ }
+ }
+
+ llassert(false); // should never fail to allocate, something is probably wrong with mCubeFree
+ return -1;
+}
+
+void LLReflectionMapManager::deleteProbe(U32 i)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ LLReflectionMap* probe = mProbes[i];
+
+ if (probe->mCubeIndex != -1)
+ { // mark the cube index used by this probe as being free
+ mCubeFree[probe->mCubeIndex] = true;
+ }
+ if (mUpdatingProbe == probe)
+ {
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+
+ // remove from any Neighbors lists
+ for (auto& other : probe->mNeighbors)
+ {
+ auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
+ llassert(iter != other->mNeighbors.end());
+ other->mNeighbors.erase(iter);
+ }
+
+ mProbes.erase(mProbes.begin() + i);
+}
+
+
+void LLReflectionMapManager::doProbeUpdate()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(mUpdatingProbe != nullptr);
+
+ updateProbeFace(mUpdatingProbe, mUpdatingFace);
+
+ if (++mUpdatingFace == 6)
+ {
+ updateNeighbors(mUpdatingProbe);
+ mUpdatingProbe = nullptr;
+ mUpdatingFace = 0;
+ }
+}
+
+void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
+{
+ mRenderTarget.bindTarget();
+ // hacky hot-swap of camera specific render targets
+ gPipeline.mRT = &gPipeline.mAuxillaryRT;
+ probe->update(mRenderTarget.getWidth(), 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);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ gReflectionMipProgram.bind();
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.matrixMode(gGL.MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+
+ gGL.flush();
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
+
+ S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f;
+
+ //for (int i = 0; i < mMipChain.size(); ++i)
+ for (int i = 0; i < 1; ++i)
+ {
+ LL_PROFILE_GPU_ZONE("probe mip");
+ mMipChain[i].bindTarget();
+
+ if (i == 0)
+ {
+ gGL.getTexUnit(0)->bind(&mRenderTarget);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(&(mMipChain[i - 1]));
+ }
+
+ gGL.begin(gGL.QUADS);
+
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(-1, -1);
+
+ gGL.texCoord2f(res, 0);
+ gGL.vertex2f(1, -1);
+
+ gGL.texCoord2f(res, res);
+ gGL.vertex2f(1, 1);
+
+ gGL.texCoord2f(0, res);
+ gGL.vertex2f(-1, 1);
+ gGL.end();
+ gGL.flush();
+
+ res /= 2;
+
+ S32 mip = i - (mMipChain.size() - mips);
+
+ 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, 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();
+ }
+
+ gGL.popMatrix();
+ gGL.matrixMode(gGL.MM_MODELVIEW);
+ gGL.popMatrix();
+
+ 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);
+ static LLStaticHashedString sSourceIdx("sourceIdx");
+ gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx);
+
+ static LLStaticHashedString sMipLevel("mipLevel");
+
+ 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);
+
+ mMipChain[i].bindTarget();
+ static LLStaticHashedString sRoughness("roughness");
+
+ 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);
+ 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();
+ }
+ }
+ gRadianceGenProgram.unbind();
+
+ //generate irradiance map
+ gIrradianceGenProgram.bind();
+ channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+
+ gIrradianceGenProgram.uniform1i(sSourceIdx, probe->mCubeIndex);
+
+ 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 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);
+
+ 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();
+ }
+}
+
+void LLReflectionMapManager::rebuild()
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mLastUpdateTime = 0.f;
+ }
+}
+
+void LLReflectionMapManager::shift(const LLVector4a& offset)
+{
+ for (auto& probe : mProbes)
+ {
+ probe->mOrigin.add(offset);
+ }
+}
+
+void LLReflectionMapManager::updateNeighbors(LLReflectionMap* probe)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ //remove from existing neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear");
+
+ for (auto& other : probe->mNeighbors)
+ {
+ auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe);
+ llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly
+ other->mNeighbors.erase(iter);
+ }
+
+ probe->mNeighbors.clear();
+ }
+
+ // search for new neighbors
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search");
+ for (auto& other : mProbes)
+ {
+ if (other != probe)
+ {
+ if (probe->intersects(other))
+ {
+ probe->mNeighbors.push_back(other);
+ other->mNeighbors.push_back(probe);
+ }
+ }
+ }
+ }
+}
+
+void LLReflectionMapManager::updateUniforms()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+
+ // structure for packing uniform buffer object
+ // see class3/deferred/reflectionProbeF.glsl
+ struct ReflectionProbeData
+ {
+ LLMatrix4 refBox[LL_REFLECTION_PROBE_COUNT]; // object bounding box as needed
+ LLVector4 refSphere[LL_REFLECTION_PROBE_COUNT]; //origin and radius of refmaps in clip space
+ LLVector4 refParams[LL_REFLECTION_PROBE_COUNT]; //extra parameters (currently only ambiance)
+ GLint refIndex[LL_REFLECTION_PROBE_COUNT][4];
+ GLint refNeighbor[4096];
+ GLint refmapCount;
+ };
+
+ mReflectionMaps.resize(LL_REFLECTION_PROBE_COUNT);
+ getReflectionMaps(mReflectionMaps);
+
+ ReflectionProbeData rpd;
+
+ // load modelview matrix into matrix 4a
+ LLMatrix4a modelview;
+ modelview.loadu(gGLModelView);
+ LLVector4a oa; // scratch space for transformed origin
+
+ S32 count = 0;
+ U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors
+
+ LLEnvironment& environment = LLEnvironment::instance();
+ LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+
+ F32 minimum_ambiance = psky->getReflectionProbeAmbiance();
+
+ for (auto* refmap : mReflectionMaps)
+ {
+ if (refmap == nullptr)
+ {
+ break;
+ }
+
+ llassert(refmap->mProbeIndex == count);
+ llassert(mReflectionMaps[refmap->mProbeIndex] == refmap);
+
+ llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged
+
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refSphere");
+
+ modelview.affineTransform(refmap->mOrigin, oa);
+ rpd.refSphere[count].set(oa.getF32ptr());
+ rpd.refSphere[count].mV[3] = refmap->mRadius;
+ }
+
+ rpd.refIndex[count][0] = refmap->mCubeIndex;
+ llassert(nc % 4 == 0);
+ rpd.refIndex[count][1] = nc / 4;
+ rpd.refIndex[count][3] = refmap->mPriority;
+
+ // for objects that are reflection probes, use the volume as the influence volume of the probe
+ // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres
+ if (refmap->getBox(rpd.refBox[count]))
+ { // negate priority to indicate this probe has a box influence volume
+ rpd.refIndex[count][3] = -rpd.refIndex[count][3];
+ }
+
+ rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance()), 0.f, 0.f, 0.f);
+
+ S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
+ {
+ //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refNeighbors");
+ //pack neghbor list
+ for (auto& neighbor : refmap->mNeighbors)
+ {
+ if (ni >= 4096)
+ { // out of space
+ break;
+ }
+
+ GLint idx = neighbor->mProbeIndex;
+ if (idx == -1)
+ {
+ continue;
+ }
+
+ // this neighbor may be sampled
+ rpd.refNeighbor[ni++] = idx;
+ }
+ }
+
+ if (nc == ni)
+ {
+ //no neighbors, tag as empty
+ rpd.refIndex[count][1] = -1;
+ }
+ else
+ {
+ rpd.refIndex[count][2] = ni - nc;
+
+ // move the cursor forward
+ nc = ni;
+ if (nc % 4 != 0)
+ { // jump to next power of 4 for compatibility with ivec4
+ nc += 4 - (nc % 4);
+ }
+ }
+
+
+ count++;
+ }
+
+ rpd.refmapCount = count;
+
+ //copy rpd into uniform buffer object
+ if (mUBO == 0)
+ {
+ glGenBuffersARB(1, &mUBO);
+ }
+
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer");
+ glBindBufferARB(GL_UNIFORM_BUFFER, mUBO);
+ glBufferDataARB(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW);
+ glBindBufferARB(GL_UNIFORM_BUFFER, 0);
+ }
+}
+
+void LLReflectionMapManager::setUniforms()
+{
+ llassert(LLPipeline::sRenderPBR);
+ if (mUBO == 0)
+ {
+ updateUniforms();
+ }
+ glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO);
+}
+
+
+void renderReflectionProbe(LLReflectionMap* probe)
+{
+ F32* po = probe->mOrigin.getF32ptr();
+
+ //draw orange line from probe to neighbors
+ gGL.flush();
+ gGL.diffuseColor4f(1, 0.5f, 0, 1);
+ gGL.begin(gGL.LINES);
+ for (auto& neighbor : probe->mNeighbors)
+ {
+ gGL.vertex3fv(po);
+ gGL.vertex3fv(neighbor->mOrigin.getF32ptr());
+ }
+ gGL.end();
+ gGL.flush();
+
+#if 0
+ LLSpatialGroup* group = probe->mGroup;
+ if (group)
+ { // draw lines from corners of object aabb to reflection probe
+
+ const LLVector4a* bounds = group->getBounds();
+ LLVector4a o = bounds[0];
+
+ gGL.flush();
+ gGL.diffuseColor4f(0, 0, 1, 1);
+ F32* c = o.getF32ptr();
+
+ const F32* bc = bounds[0].getF32ptr();
+ const F32* bs = bounds[1].getF32ptr();
+
+ // daaw blue lines from corners to center of node
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] + bs[2]);
+
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] + bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] + bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.vertex3fv(c);
+ gGL.vertex3f(bc[0] - bs[0], bc[1] - bs[1], bc[2] - bs[2]);
+ gGL.end();
+
+ //draw yellow line from center of node to reflection probe origin
+ gGL.flush();
+ gGL.diffuseColor4f(1, 1, 0, 1);
+ gGL.begin(gGL.LINES);
+ gGL.vertex3fv(c);
+ gGL.vertex3fv(po);
+ gGL.end();
+ gGL.flush();
+ }
+#endif
+}
+
+void LLReflectionMapManager::renderDebug()
+{
+ gDebugProgram.bind();
+
+ for (auto& probe : mProbes)
+ {
+ renderReflectionProbe(probe);
+ }
+
+ gDebugProgram.unbind();
+}
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
new file mode 100644
index 0000000000..5f0b11ec17
--- /dev/null
+++ b/indra/newview/llreflectionmapmanager.h
@@ -0,0 +1,152 @@
+/**
+ * @file llreflectionmapmanager.h
+ * @brief LLReflectionMapManager class declaration
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#pragma once
+
+#include "llreflectionmap.h"
+#include "llrendertarget.h"
+#include "llcubemaparray.h"
+#include "llcubemap.h"
+
+class LLSpatialGroup;
+class LLViewerObject;
+
+// number of reflection probes to keep in vram
+#define LL_REFLECTION_PROBE_COUNT 256
+
+// 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;
+
+class alignas(16) LLReflectionMapManager
+{
+ LL_ALIGN_NEW
+public:
+ enum class DetailLevel
+ {
+ STATIC_ONLY = 0,
+ STATIC_AND_DYNAMIC,
+ REALTIME = 2
+ };
+
+ // allocate an environment map of the given resolution
+ LLReflectionMapManager();
+
+ // maintain reflection probes
+ void update();
+
+ // add a probe for the given spatial group
+ LLReflectionMap* addProbe(LLSpatialGroup* group);
+
+ // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
+ // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
+ // maps -- presized array of Reflection Map pointers
+ void getReflectionMaps(std::vector<LLReflectionMap*>& maps);
+
+ // called by LLSpatialGroup constructor
+ // If spatial group should receive a Reflection Probe, will create one for the specified spatial group
+ LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group);
+
+ // presently hacked into LLViewerObject::setTE
+ // Used by LLViewerObjects that are Reflection Probes
+ // Guaranteed to not return null
+ LLReflectionMap* registerViewerObject(LLViewerObject* vobj);
+
+ // force an update of all probes
+ void rebuild();
+
+ // called on region crossing to "shift" probes into new coordinate frame
+ void shift(const LLVector4a& offset);
+
+ // debug display, called from llspatialpartition if reflection
+ // probe debug display is active
+ void renderDebug();
+
+private:
+ friend class LLPipeline;
+
+ // delete the probe with the given index in mProbes
+ void deleteProbe(U32 i);
+
+ // get a free cube index
+ // if no cube indices are free, free one starting from the back of the probe list
+ S32 allocateCubeIndex();
+
+ // update the neighbors of the given probe
+ void updateNeighbors(LLReflectionMap* probe);
+
+ // update UBO used for rendering (call only once per render pipe flush)
+ void updateUniforms();
+
+ // bind UBO used for rendering
+ void setUniforms();
+
+ // render target for cube snapshots
+ // used to generate mipmaps without doing a copy-to-texture
+ LLRenderTarget mRenderTarget;
+
+ std::vector<LLRenderTarget> mMipChain;
+
+ // storage for reflection probe radiance maps (plus two scratch space cubemaps)
+ LLPointer<LLCubeMapArray> mTexture;
+
+ // storage for reflection probe irradiance maps
+ LLPointer<LLCubeMapArray> mIrradianceMaps;
+
+ // array indicating if a particular cubemap is free
+ bool mCubeFree[LL_REFLECTION_PROBE_COUNT];
+
+ // start tracking the given spatial group
+ void trackGroup(LLSpatialGroup* group);
+
+ // perform an update on the currently updating Probe
+ void doProbeUpdate();
+
+ // update the specified face of the specified probe
+ void updateProbeFace(LLReflectionMap* probe, U32 face);
+
+ // list of active reflection maps
+ std::vector<LLPointer<LLReflectionMap> > mProbes;
+
+ // list of reflection maps to kill
+ std::vector<LLPointer<LLReflectionMap> > mKillList;
+
+ // list of reflection maps to create
+ std::vector<LLPointer<LLReflectionMap> > mCreateList;
+
+ // handle to UBO
+ U32 mUBO = 0;
+
+ // list of maps being used for rendering
+ std::vector<LLReflectionMap*> mReflectionMaps;
+
+ LLReflectionMap* mUpdatingProbe = nullptr;
+ U32 mUpdatingFace = 0;
+};
+
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 82a165cb35..853703b4d5 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1066,8 +1066,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
- || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced())))
{
// only select my own objects
return;
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 7c762170a7..a1c703b02f 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -758,6 +758,7 @@ LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
param_map[SETTING_SKY_DROPLET_RADIUS] = DefaultParam(LLShaderMgr::DROPLET_RADIUS, sky_defaults[SETTING_SKY_DROPLET_RADIUS]);
param_map[SETTING_SKY_ICE_LEVEL] = DefaultParam(LLShaderMgr::ICE_LEVEL, sky_defaults[SETTING_SKY_ICE_LEVEL]);
+ param_map[SETTING_REFLECTION_PROBE_AMBIANCE] = DefaultParam(LLShaderMgr::REFLECTION_PROBE_AMBIANCE, sky_defaults[SETTING_REFLECTION_PROBE_AMBIANCE]);
// AdvancedAtmospherics TODO
// Provide mappings for new shader params here
}
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 0d53950889..f445bc98eb 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -554,9 +554,12 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
sg_assert(mOctreeNode->getListenerCount() == 0);
setState(SG_INITIAL_STATE_MASK);
gPipeline.markRebuild(this, TRUE);
+
+ // let the reflection map manager know about this spatial group
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerSpatialGroup(this);
- mRadius = 1;
- mPixelArea = 1024.f;
+ mRadius = 1;
+ mPixelArea = 1024.f;
}
void LLSpatialGroup::updateDistance(LLCamera &camera)
@@ -1399,7 +1402,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
return 0;
}
-
+
+extern BOOL gCubeSnapshot;
+
S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL;
@@ -1418,7 +1423,7 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion)
LLOctreeCullShadow culler(&camera);
culler.traverse(mOctree);
}
- else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
+ else if (mInfiniteFarClip || (!LLPipeline::sUseFarClip && !gCubeSnapshot))
{
LLOctreeCullNoFarClip culler(&camera);
culler.traverse(mOctree);
@@ -1738,7 +1743,7 @@ void renderOctree(LLSpatialGroup* group)
}
}*/
}
-
+
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
// gGL.diffuseColor4f(0,1,0,1);
// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
@@ -2610,14 +2615,12 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
gGL.diffuseColor4fv(line_color.mV);
gGL.syncMatrices();
{
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x20FF20 )
glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
}
gGL.diffuseColor4fv(color.mV);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
{
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x40FF40 )
glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
}
}
@@ -3156,7 +3159,6 @@ void renderRaycast(LLDrawable* drawablep)
gGL.diffuseColor4f(0,1,1,0.5f);
glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions);
gGL.syncMatrices();
- LL_PROFILER_GPU_ZONEC( "gl.DrawElements", 0x60FF60 );
glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
}
@@ -3704,7 +3706,7 @@ void LLSpatialPartition::renderDebug()
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY |
- LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
+ LLPipeline::RENDER_DEBUG_TEXEL_DENSITY))
{
return;
}
@@ -3738,7 +3740,6 @@ void LLSpatialPartition::renderDebug()
LLOctreeRenderNonOccluded render_debug(camera);
render_debug.traverse(mOctree);
-
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
{
@@ -3801,8 +3802,9 @@ public:
LLDrawable* mHit;
BOOL mPickTransparent;
BOOL mPickRigged;
+ BOOL mPickUnselectable;
- LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged,
+ LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable,
S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
: mStart(start),
mEnd(end),
@@ -3813,7 +3815,8 @@ public:
mTangent(tangent),
mHit(NULL),
mPickTransparent(pick_transparent),
- mPickRigged(pick_rigged)
+ mPickRigged(pick_rigged),
+ mPickUnselectable(pick_unselectable)
{
}
@@ -3898,7 +3901,7 @@ public:
LLVOAvatar* avatar = (LLVOAvatar*) vobj;
if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools))))
{
- LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
+ LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent);
if (hit)
{
mEnd = intersection;
@@ -3914,7 +3917,7 @@ public:
}
}
- if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
+ if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent))
{
mEnd = intersection; // shorten ray so we only find CLOSER hits
if (mIntersection)
@@ -3934,6 +3937,7 @@ public:
LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -3942,12 +3946,30 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co
)
{
- LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, face_hit, intersection, tex_coord, normal, tangent);
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
LLDrawable* drawable = intersect.check(mOctree);
return drawable;
}
+LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ BOOL pick_unselectable,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector4a* normal, // return the surface normal at the intersection point
+ LLVector4a* tangent // return the surface tangent at the intersection point
+)
+
+{
+ LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* drawable = intersect.check(getOctreeNode());
+
+ return drawable;
+}
+
LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLViewerTexture* texture, LLVertexBuffer* buffer,
bool selected,
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 6d3ef33801..c3e9d8ceb9 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -53,6 +53,7 @@ class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
class LLViewerRegion;
+class LLReflectionMap;
void pushVerts(LLFace* face, U32 mask);
@@ -112,9 +113,14 @@ public:
LL_ALIGN_16(LLFace* mFace); //associated face
F32 mDistance;
U32 mDrawMode;
- LLMaterialPtr mMaterial; // If this is null, the following parameters are unused.
- LLMaterialID mMaterialID;
- U32 mShaderMask;
+
+ // Material points here are likely for debugging only and are immaterial (zing!)
+ LLMaterialPtr mMaterial;
+ LLPointer<LLGLTFMaterial> mGLTFMaterial;
+
+ LLUUID mMaterialID; // id of LLGLTFMaterial or LLMaterial applied to this draw info
+
+ U32 mShaderMask;
U32 mBlendFuncSrc;
U32 mBlendFuncDst;
BOOL mHasGlow;
@@ -122,6 +128,8 @@ public:
const LLMatrix4* mSpecularMapMatrix;
LLPointer<LLViewerTexture> mNormalMap;
const LLMatrix4* mNormalMapMatrix;
+ LLPointer<LLViewerTexture> mEmissiveMap;
+
LLVector4 mSpecColor; // XYZ = Specular RGB, W = Specular Exponent
F32 mEnvIntensity;
F32 mAlphaMaskCutoff;
@@ -313,6 +321,18 @@ public:
void drawObjectBox(LLColor4 col);
+ LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
+ BOOL pick_transparent,
+ BOOL pick_rigged,
+ BOOL pick_unselectable,
+ S32* face_hit, // return the face hit
+ LLVector4a* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector4a* normal = NULL, // return the surface normal at the intersection point
+ LLVector4a* tangent = NULL // return the surface tangent at the intersection point
+ );
+
+
LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;}
//LISTENER FUNCTIONS
@@ -355,6 +375,9 @@ public:
//used by LLVOAVatar to set render order in alpha draw pool to preserve legacy render order behavior
LLVOAvatar* mAvatarp = nullptr;
U32 mRenderOrder = 0;
+ // Reflection Probe associated with this node (if any)
+ LLPointer<LLReflectionMap> mReflectionProbe = nullptr;
+
} LL_ALIGN_POSTFIX(64);
class LLGeometryManager
@@ -382,6 +405,7 @@ public:
LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 51ee5b6157..e8ff14daac 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -182,8 +182,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker(
mOnUpdateImageStatsCallback(NULL),
mBakeTextureEnabled(FALSE)
{
- buildFromFile("floater_texture_ctrl.xml");
mCanApplyImmediately = can_apply_immediately;
+ buildFromFile("floater_texture_ctrl.xml");
setCanMinimize(FALSE);
}
@@ -254,10 +254,8 @@ void LLFloaterTexturePicker::setActive( BOOL active )
void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
{
mCanApplyImmediately = b;
- if (!mCanApplyImmediately)
- {
- getChild<LLUICtrl>("apply_immediate_check")->setValue(FALSE);
- }
+
+ getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately);
updateFilterPermMask();
}
@@ -474,11 +472,7 @@ BOOL LLFloaterTexturePicker::postBuild()
getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview"));
childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
-
- if (!mCanApplyImmediately)
- {
- getChildView("show_folders_check")->setEnabled(FALSE);
- }
+ getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
getChild<LLUICtrl>("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this));
childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
@@ -544,7 +538,7 @@ void LLFloaterTexturePicker::draw()
}
getChildView("Default")->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative);
- getChildView("Blank")->setEnabled(mImageAssetID != mBlankImageAssetID || mTentative);
+ getChildView("Blank")->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID != mDefaultImageAssetID) || mTentative);
getChildView("None")->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative));
LLFloater::draw();
@@ -1207,7 +1201,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
mOnCloseCallback(NULL),
mOnSelectCallback(NULL),
mBorderColor( p.border_color() ),
- mAllowNoTexture( FALSE ),
+ mAllowNoTexture( p.allow_no_texture ),
mAllowLocalTexture( TRUE ),
mImmediateFilterPermMask( PERM_NONE ),
mNonImmediateFilterPermMask( PERM_NONE ),
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index 3769f43737..a234124c08 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -101,7 +101,7 @@ public:
: image_id("image"),
default_image_id("default_image_id"),
default_image_name("default_image_name"),
- allow_no_texture("allow_no_texture"),
+ allow_no_texture("allow_no_texture", false),
can_apply_immediately("can_apply_immediately"),
no_commit_on_selection("no_commit_on_selection", false),
label_width("label_width", -1),
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 0edaf40c66..35e4bb03ac 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -3400,6 +3400,7 @@ void LLTextureFetch::sendRequestListToSimulators()
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
}
S32 packet = req->mLastPacket + 1;
+ LL_INFOS() << req->mID << ": " << req->mImagePriority << LL_ENDL;
gMessageSystem->nextBlockFast(_PREHASH_RequestImage);
gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID);
gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard);
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index f76a2f7f90..ab54e2afc6 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -256,7 +256,8 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
// |-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------|
addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL));
- addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_MATERIAL, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMaterialObject, &LLToolDragAndDrop::dad3dNULL));
+ addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL));
@@ -271,6 +272,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_SETTINGS, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
+
// TODO: animation on self could play it? edit it?
// TODO: gesture on self could play it? edit it?
};
@@ -1062,6 +1064,64 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj,
hit_obj->sendTEUpdate();
}
+
+void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj,
+ S32 hit_face,
+ LLInventoryItem* item,
+ LLToolDragAndDrop::ESource source,
+ const LLUUID& src_id)
+{
+ if (hit_face == -1) return;
+ if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no material item." << LL_ENDL;
+ return;
+ }
+ LLUUID asset_id = item->getAssetUUID();
+ BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ if (!success)
+ {
+ return;
+ }
+
+ hit_obj->setRenderMaterialID(hit_face, asset_id);
+
+ dialog_refresh_all();
+
+ // send the update to the simulator
+ hit_obj->sendTEUpdate();
+}
+
+
+void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj,
+ LLInventoryItem* item,
+ LLToolDragAndDrop::ESource source,
+ const LLUUID& src_id)
+{
+ if (!item || item->getInventoryType() != LLInventoryType::IT_MATERIAL)
+ {
+ LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no material item." << LL_ENDL;
+ return;
+ }
+ LLUUID asset_id = item->getAssetUUID();
+ BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id);
+ if (!success)
+ {
+ return;
+ }
+
+ S32 num_faces = hit_obj->getNumTEs();
+ for (S32 face = 0; face < num_faces; face++)
+ {
+ // update viewer side material in anticipation of update from simulator
+ hit_obj->setRenderMaterialID(face, asset_id);
+ dialog_refresh_all();
+ }
+ // send the update to the simulator
+ hit_obj->sendTEUpdate();
+}
+
+
void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj,
LLInventoryItem* item,
LLToolDragAndDrop::ESource source,
@@ -1630,6 +1690,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
case DAD_MESH:
case DAD_CATEGORY:
case DAD_SETTINGS:
+ case DAD_MATERIAL:
{
LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data;
if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID())
@@ -1984,6 +2045,17 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject(
dropTextureOneFace(obj, face, item, mSource, mSourceID);
}
}
+ else if (cargo_type == DAD_MATERIAL)
+ {
+ if ((mask & MASK_SHIFT))
+ {
+ dropMaterialAllFaces(obj, item, mSource, mSourceID);
+ }
+ else
+ {
+ dropMaterialOneFace(obj, face, item, mSource, mSourceID);
+ }
+ }
else if (cargo_type == DAD_MESH)
{
dropMesh(obj, item, mSource, mSourceID);
@@ -2012,6 +2084,12 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject(
return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE);
}
+EAcceptance LLToolDragAndDrop::dad3dMaterialObject(
+ LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
+{
+ return dad3dApplyToObject(obj, face, mask, drop, DAD_MATERIAL);
+}
+
EAcceptance LLToolDragAndDrop::dad3dMeshObject(
LLViewerObject* obj, S32 face, MASK mask, BOOL drop)
{
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 4537d73332..cfdbd931ce 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -168,6 +168,8 @@ protected:
MASK mask, BOOL drop);
EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face,
MASK mask, BOOL drop);
+ EAcceptance dad3dMaterialObject(LLViewerObject* obj, S32 face,
+ MASK mask, BOOL drop);
EAcceptance dad3dMeshObject(LLViewerObject* obj, S32 face,
MASK mask, BOOL drop);
// EAcceptance dad3dTextureSelf(LLViewerObject* obj, S32 face,
@@ -250,6 +252,14 @@ public:
LLInventoryItem* item,
ESource source,
const LLUUID& src_id);
+ static void dropMaterialOneFace(LLViewerObject* hit_obj, S32 hit_face,
+ LLInventoryItem* item,
+ ESource source,
+ const LLUUID& src_id);
+ static void dropMaterialAllFaces(LLViewerObject* hit_obj,
+ LLInventoryItem* item,
+ ESource source,
+ const LLUUID& src_id);
static void dropMesh(LLViewerObject* hit_obj,
LLInventoryItem* item,
ESource source,
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index e52bc0b015..c6f3905ddc 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -65,7 +65,8 @@ BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask)
{
// do immediate pick query
BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick");
- mPick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged);
+ BOOL pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects");
+ mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged);
// Pass mousedown to agent
LLTool::handleMouseDown(x, y, mask);
@@ -84,13 +85,13 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
}
BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly");
BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
-
- // *NOTE: These settings must be cleaned up at bottom of function.
+
+ // *NOTE: These settings must be cleaned up at bottom of function.
if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", FALSE);
gSavedSettings.setBOOL("SelectMovableOnly", FALSE);
- LLSelectMgr::getInstance()->setForceSelection(TRUE);
+ LLSelectMgr::getInstance()->setForceSelection(TRUE);
}
BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL);
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index 4804ef6ddc..481086f760 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -88,6 +88,7 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
addEntry(LLViewerAssetType::AT_SETTINGS, new ViewerAssetEntry(DAD_SETTINGS));
+ addEntry(LLViewerAssetType::AT_MATERIAL, new ViewerAssetEntry(DAD_MATERIAL));
};
EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type)
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 3f7e8531fb..8e1ebdf6fa 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -497,6 +497,67 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
}
//=========================================================================
+LLNewBufferedResourceUploadInfo::LLNewBufferedResourceUploadInfo(
+ const std::string& buffer,
+ const LLAssetID& asset_id,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ LLAssetType::EType assetType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory,
+ uploadFinish_f finish)
+ : LLResourceUploadInfo(name, description, compressionInfo,
+ destinationType, inventoryType,
+ nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory)
+ , mBuffer(buffer)
+ , mFinishFn(finish)
+{
+ setAssetType(assetType);
+ setAssetId(asset_id);
+}
+
+LLSD LLNewBufferedResourceUploadInfo::prepareUpload()
+{
+ if (getAssetId().isNull())
+ generateNewAssetId();
+
+ LLSD result = exportTempFile();
+ if (result.has("error"))
+ return result;
+
+ return LLResourceUploadInfo::prepareUpload();
+}
+
+LLSD LLNewBufferedResourceUploadInfo::exportTempFile()
+{
+ std::string filename = gDirUtilp->getTempFilename();
+
+ // copy buffer to the cache for upload
+ LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND);
+ file.write((U8*) mBuffer.c_str(), mBuffer.size());
+
+ return LLSD();
+}
+
+LLUUID LLNewBufferedResourceUploadInfo::finishUpload(LLSD &result)
+{
+ LLUUID newItemId = LLResourceUploadInfo::finishUpload(result);
+
+ if (mFinishFn)
+ {
+ mFinishFn(result["new_asset"].asUUID(), result);
+ }
+
+ return newItemId;
+}
+
+//=========================================================================
LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish) :
LLResourceUploadInfo(std::string(), std::string(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
0, 0, 0, 0),
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index e56ba7d8f7..9eddcfbd0e 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -168,6 +168,41 @@ private:
};
//-------------------------------------------------------------------------
+// use when you have a resource in memory and you want to make a new inventory item
+class LLNewBufferedResourceUploadInfo : public LLResourceUploadInfo
+{
+public:
+ typedef std::function<void(LLUUID newAssetId, LLSD response)> uploadFinish_f;
+
+ LLNewBufferedResourceUploadInfo(
+ const std::string& buffer,
+ const LLAssetID& asset_id,
+ std::string name,
+ std::string description,
+ S32 compressionInfo,
+ LLFolderType::EType destinationType,
+ LLInventoryType::EType inventoryType,
+ LLAssetType::EType assetType,
+ U32 nextOWnerPerms,
+ U32 groupPerms,
+ U32 everyonePerms,
+ S32 expectedCost,
+ bool show_inventory,
+ uploadFinish_f finish);
+
+ virtual LLSD prepareUpload();
+
+protected:
+
+ virtual LLSD exportTempFile();
+ virtual LLUUID finishUpload(LLSD &result);
+
+private:
+ uploadFinish_f mFinishFn;
+ std::string mBuffer;
+};
+
+//-------------------------------------------------------------------------
class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
{
public:
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 549778a841..b5841772ed 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -47,15 +47,14 @@ public:
typedef enum
{
CAMERA_WORLD = 0,
- CAMERA_SHADOW0,
- CAMERA_SHADOW1,
- CAMERA_SHADOW2,
- CAMERA_SHADOW3,
- CAMERA_SHADOW4,
- CAMERA_SHADOW5,
+ CAMERA_SUN_SHADOW0,
+ CAMERA_SUN_SHADOW1,
+ CAMERA_SUN_SHADOW2,
+ CAMERA_SUN_SHADOW3,
+ CAMERA_SPOT_SHADOW0,
+ CAMERA_SPOT_SHADOW1,
CAMERA_WATER0,
CAMERA_WATER1,
- CAMERA_GI_SOURCE,
NUM_CAMERAS
} eCameraID;
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 9036e87514..a6f5a09722 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -440,9 +440,10 @@ static bool handleRenderLocalLightsChanged(const LLSD& newvalue)
return true;
}
+// NOTE: may be triggered by RenderDeferred OR RenderPBR changing, don't trust "newvalue"
static bool handleRenderDeferredChanged(const LLSD& newvalue)
{
- LLRenderTarget::sUseFBO = newvalue.asBoolean();
+ LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred");
if (gPipeline.isInit())
{
LLPipeline::refreshCachedSettings();
@@ -662,7 +663,6 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
- gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));
@@ -686,6 +686,7 @@ void settings_setup_listeners()
gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2));
gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _2));
gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2));
+ gSavedSettings.getControl("RenderPBR")->getSignal()->connect(boost::bind(&handleRenderDeferredChanged, _2));
gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 6a2b06d9b5..6d98d9b10e 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -97,6 +97,7 @@ BOOL gResizeScreenTexture = FALSE;
BOOL gResizeShadowTexture = FALSE;
BOOL gWindowResized = FALSE;
BOOL gSnapshot = FALSE;
+BOOL gCubeSnapshot = FALSE;
BOOL gShaderProfileFrame = FALSE;
// This is how long the sim will try to teleport you before giving up.
@@ -193,15 +194,23 @@ void display_update_camera()
// Cut draw distance in half when customizing avatar,
// but on the viewer only.
F32 final_far = gAgentCamera.mDrawDistance;
- if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+ if (gCubeSnapshot)
+ {
+ final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance");
+ }
+ else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+
{
final_far *= 0.5f;
}
LLViewerCamera::getInstance()->setFar(final_far);
gViewerWindow->setup3DRender();
- // Update land visibility too
- LLWorld::getInstance()->setLandFarClip(final_far);
+ if (!gCubeSnapshot)
+ {
+ // Update land visibility too
+ LLWorld::getInstance()->setLandFarClip(final_far);
+ }
}
// Write some stats to LL_INFOS()
@@ -907,19 +916,19 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred)
{
- gPipeline.mDeferredScreen.bindTarget();
+ gPipeline.mRT->deferredScreen.bindTarget();
glClearColor(1, 0, 1, 1);
- gPipeline.mDeferredScreen.clear();
+ gPipeline.mRT->deferredScreen.clear();
}
else
{
- gPipeline.mScreen.bindTarget();
+ gPipeline.mRT->screen.bindTarget();
if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
{
const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
}
- gPipeline.mScreen.clear();
+ gPipeline.mRT->screen.clear();
}
gGL.setColorMask(true, false);
@@ -989,7 +998,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
- LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mDeferredScreen : gPipeline.mScreen);
+ LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mRT->deferredScreen : gPipeline.mRT->screen);
rt.flush();
if (rt.sUseFBO)
@@ -1001,7 +1010,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
if (LLPipeline::sRenderDeferred)
{
- gPipeline.renderDeferredLighting(&gPipeline.mScreen);
+ gPipeline.renderDeferredLighting(&gPipeline.mRT->screen);
}
LLPipeline::sUnderWaterRender = FALSE;
@@ -1048,6 +1057,113 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
}
+// WIP simplified copy of display() that does minimal work
+void display_cube_face()
+{
+ LL_RECORD_BLOCK_TIME(FTM_RENDER);
+ LL_PROFILE_GPU_ZONE("display cube face");
+
+ llassert(!gSnapshot);
+ llassert(!gTeleportDisplay);
+ llassert(LLPipeline::sRenderDeferred);
+ llassert(LLStartUp::getStartupState() >= STATE_PRECACHE);
+ llassert(!LLAppViewer::instance()->logoutRequestSent());
+ llassert(!gRestoreGL);
+ llassert(!gUseWireframe);
+
+ bool rebuild = false;
+
+ LLGLSDefault gls_default;
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+
+ LLVertexBuffer::unbind();
+
+ gPipeline.disableLights();
+
+ gPipeline.mBackfaceCull = TRUE;
+
+ gViewerWindow->setup3DViewport();
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+ { //don't draw hud particles in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ display_update_camera();
+
+ LLSpatialGroup::sNoDelete = TRUE;
+
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots
+ //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data
+
+ static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater();
+ gPipeline.updateCull(*LLViewerCamera::getInstance(), result);
+
+ gGL.setColorMask(true, true);
+ glClearColor(0, 0, 0, 0);
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+ }
+
+ LLPipeline::sUseOcclusion = occlusion;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+
+ gGL.setColorMask(true, true);
+
+ gPipeline.mRT->deferredScreen.bindTarget();
+ glClearColor(1, 0, 1, 1);
+ gPipeline.mRT->deferredScreen.clear();
+
+ gGL.setColorMask(true, false);
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+
+ gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
+
+ gGL.setColorMask(true, true);
+
+ gPipeline.mRT->deferredScreen.flush();
+
+ gPipeline.renderDeferredLighting(&gPipeline.mRT->screen);
+
+ LLPipeline::sUnderWaterRender = FALSE;
+
+ // Finalize scene
+ gPipeline.renderFinalize();
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
+}
+
void render_hud_attachments()
{
gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -1242,7 +1358,7 @@ bool setup_hud_matrices(const LLRect& screen_region)
void render_ui(F32 zoom_factor, int subfield)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
-
+ LL_PROFILE_GPU_ZONE("ui");
LLGLState::checkStates();
glh::matrix4f saved_view = get_current_modelview();
@@ -1325,7 +1441,7 @@ static LLTrace::BlockTimerStatHandle FTM_SWAP("Swap");
void swap()
{
LL_RECORD_BLOCK_TIME(FTM_SWAP);
-
+ LL_PROFILE_GPU_ZONE("swap");
if (gDisplaySwapBuffers)
{
gViewerWindow->getWindow()->swapBuffers();
@@ -1487,7 +1603,7 @@ void render_ui_2d()
LLView::sIsRectDirty = false;
LLRect t_rect;
- gPipeline.mUIScreen.bindTarget();
+ gPipeline.mRT->uiScreen.bindTarget();
gGL.setColorMask(true, true);
{
static const S32 pad = 8;
@@ -1519,7 +1635,7 @@ void render_ui_2d()
gViewerWindow->draw();
}
- gPipeline.mUIScreen.flush();
+ gPipeline.mRT->uiScreen.flush();
gGL.setColorMask(true, false);
LLView::sDirtyRect = t_rect;
@@ -1529,7 +1645,7 @@ void render_ui_2d()
LLGLDisable blend(GL_BLEND);
S32 width = gViewerWindow->getWindowWidthScaled();
S32 height = gViewerWindow->getWindowHeightScaled();
- gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.getTexUnit(0)->bind(&gPipeline.mRT->uiScreen);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.color4f(1,1,1,1);
gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index dd03d6cfdd..97cb8e2000 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -152,6 +152,7 @@
#include "llinspectobject.h"
#include "llinspectremoteobject.h"
#include "llinspecttoast.h"
+#include "llmaterialeditor.h"
#include "llmoveview.h"
#include "llfloaterimnearbychat.h"
#include "llpanelblockedlist.h"
@@ -337,6 +338,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("save_camera_preset", "floater_save_camera_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSaveCameraPreset>);
LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
+ LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
+
LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);
//LLFloaterReg::add("test_list_view", "floater_test_list_view.xml",&LLFloaterReg::build<LLFloaterTestListView>);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 55ac817479..2265379ce4 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -147,6 +147,7 @@ LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary()
mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture");
+ mInventoryItemsDict["New Material"] = LLTrans::getString("New Material");
mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
mInventoryItemsDict["New Note"] = LLTrans::getString("New Note");
@@ -1672,6 +1673,7 @@ void remove_folder_contents(const LLUUID& category, bool keep_outfit_links,
const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not)
const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not)
const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not)
+const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not)
// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements...
void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid)
@@ -1727,6 +1729,15 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
LLInventoryType::IT_GESTURE,
PERM_ALL); // overridden in create_new_item
}
+ else if ("material" == type_name)
+ {
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL);
+ create_new_item(NEW_MATERIAL_NAME,
+ parent_id,
+ LLAssetType::AT_MATERIAL,
+ LLInventoryType::IT_MATERIAL,
+ PERM_ALL); // overridden in create_new_item
+ }
else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name))
{
LLSettingsType::type_e stype(LLSettingsType::ST_NONE);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 459bbaa00a..69347ae4ce 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -267,16 +267,11 @@ void handle_reset_view();
void handle_duplicate_in_place(void*);
-
void handle_object_owner_self(void*);
void handle_object_owner_permissive(void*);
void handle_object_lock(void*);
void handle_object_asset_ids(void*);
void force_take_copy(void*);
-#ifdef _CORY_TESTING
-void force_export_copy(void*);
-void force_import_geometry(void*);
-#endif
void handle_force_parcel_owner_to_me(void*);
void handle_force_parcel_to_content(void*);
@@ -1093,6 +1088,10 @@ U64 info_display_from_string(std::string info_display)
{
return LLPipeline::RENDER_DEBUG_IMPOSTORS;
}
+ else if ("reflection probes" == info_display)
+ {
+ return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES;
+ }
else
{
LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL;
@@ -8044,6 +8043,18 @@ class LLToolsSelectOnlyMovableObjects : public view_listener_t
}
};
+class LLToolsSelectInvisibleObjects : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ BOOL cur_val = gSavedSettings.getBOOL("SelectInvisibleObjects");
+
+ gSavedSettings.setBOOL("SelectInvisibleObjects", !cur_val);
+
+ return true;
+ }
+};
+
class LLToolsSelectBySurrounding : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -8376,6 +8387,12 @@ void handle_cache_clear_immediately()
LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately);
}
+void handle_rebuild_reflection_probes()
+{
+ gPipeline.mReflectionMapManager.rebuild();
+}
+
+
void handle_web_content_test(const LLSD& param)
{
std::string url = param.asString();
@@ -9267,6 +9284,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool");
view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects");
view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects");
+ view_listener_t::addMenu(new LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects");
view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding");
view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection");
view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius");
@@ -9474,6 +9492,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger");
//Develop (clear cache immediately)
commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) );
+ //Develop (override environment map)
+ commit.add("Develop.RebuildReflectionProbes", boost::bind(&handle_rebuild_reflection_probes));
// Admin >Object
view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy");
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index f1e2c06e0c..148a76d93b 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -37,6 +37,7 @@
#include "llbuycurrencyhtml.h"
#include "llfloatermap.h"
#include "llfloatermodelpreview.h"
+#include "llmaterialeditor.h"
#include "llfloatersnapshot.h"
#include "llfloateroutfitsnapshot.h"
#include "llimage.h"
@@ -101,6 +102,20 @@ class LLFileEnableUploadModel : public view_listener_t
}
};
+class LLFileEnableUploadMaterial : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::findInstance("material_editor");
+ if (me && me->isShown())
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
class LLMeshEnabled : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -277,14 +292,12 @@ void LLMediaFilePicker::notify(const std::vector<std::string>& filenames)
static std::string SOUND_EXTENSIONS = "wav";
static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
static std::string ANIM_EXTENSIONS = "bvh anim";
-#ifdef _CORY_TESTING
-static std::string GEOMETRY_EXTENSIONS = "slg";
-#endif
static std::string XML_EXTENSIONS = "xml";
static std::string SLOBJECT_EXTENSIONS = "slobject";
#endif
static std::string ALL_FILE_EXTENSIONS = "*.*";
static std::string MODEL_EXTENSIONS = "dae";
+static std::string MATERIAL_EXTENSIONS = "gltf glb";
std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
{
@@ -301,10 +314,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
return SLOBJECT_EXTENSIONS;
case LLFilePicker::FFLOAD_MODEL:
return MODEL_EXTENSIONS;
-#ifdef _CORY_TESTING
- case LLFilePicker::FFLOAD_GEOMETRY:
- return GEOMETRY_EXTENSIONS;
-#endif
+ case LLFilePicker::FFLOAD_MATERIAL:
+ return MATERIAL_EXTENSIONS;
case LLFilePicker::FFLOAD_XML:
return XML_EXTENSIONS;
case LLFilePicker::FFLOAD_ALL:
@@ -573,7 +584,20 @@ class LLFileUploadModel : public view_listener_t
return TRUE;
}
};
-
+
+class LLFileUploadMaterial : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor");
+ if (me)
+ {
+ me->importMaterial();
+ }
+ return TRUE;
+ }
+};
+
class LLFileUploadSound : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -1104,6 +1128,7 @@ void init_menu_file()
view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
+ view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial");
view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index be80d0bc0a..e959f24f1f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1414,7 +1414,8 @@ bool check_asset_previewable(const LLAssetType::EType asset_type)
(asset_type == LLAssetType::AT_TEXTURE) ||
(asset_type == LLAssetType::AT_ANIMATION) ||
(asset_type == LLAssetType::AT_SCRIPT) ||
- (asset_type == LLAssetType::AT_SOUND);
+ (asset_type == LLAssetType::AT_SOUND) ||
+ (asset_type == LLAssetType::AT_MATERIAL);
}
void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)
@@ -1519,6 +1520,9 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam
case LLAssetType::AT_SOUND:
LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);
break;
+ case LLAssetType::AT_MATERIAL:
+ LLFloaterReg::showInstance("material editor", LLSD(obj_id), take_focus);
+ break;
default:
LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type) << LL_ENDL;
break;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a95636ff23..753fb014c9 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -107,6 +107,7 @@
#include "llcleanup.h"
#include "llcallstack.h"
#include "llmeshrepository.h"
+#include "llgltfmateriallist.h"
#include "llgl.h"
//#define DEBUG_UPDATE_TYPE
@@ -259,7 +260,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mTEImages(NULL),
mTENormalMaps(NULL),
mTESpecularMaps(NULL),
- mGLName(0),
mbCanSelect(TRUE),
mFlags(0),
mPhysicsShapeType(0),
@@ -343,6 +343,13 @@ LLViewerObject::~LLViewerObject()
{
deleteTEImages();
+ // unhook from reflection probe manager
+ if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe->mViewerObject = nullptr;
+ mReflectionProbe = nullptr;
+ }
+
if(mInventory)
{
mInventory->clear(); // will deref and delete entries
@@ -400,6 +407,11 @@ void LLViewerObject::deleteTEImages()
delete[] mTESpecularMaps;
mTESpecularMaps = NULL;
}
+
+ mGLTFAlbedoMaps.clear();
+ mGLTFNormalMaps.clear();
+ mGLTFMetallicRoughnessMaps.clear();
+ mGLTFEmissiveMaps.clear();
}
void LLViewerObject::markDead()
@@ -4566,6 +4578,7 @@ BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVecto
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -4724,6 +4737,11 @@ void LLViewerObject::setNumTEs(const U8 num_tes)
mTEImages = new_images;
mTENormalMaps = new_normmaps;
mTESpecularMaps = new_specmaps;
+
+ mGLTFAlbedoMaps.resize(num_tes);
+ mGLTFNormalMaps.resize(num_tes);
+ mGLTFMetallicRoughnessMaps.resize(num_tes);
+ mGLTFEmissiveMaps.resize(num_tes);
}
else
{
@@ -4852,23 +4870,28 @@ void LLViewerObject::updateAvatarMeshVisibility(const LLUUID& id, const LLUUID&
}
}
-void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
+
+void LLViewerObject::setTE(const U8 te, const LLTextureEntry& texture_entry)
{
- LLUUID old_image_id;
- if (getTE(te))
- {
- old_image_id = getTE(te)->getID();
- }
-
- LLPrimitive::setTE(te, texture_entry);
+ LLUUID old_image_id;
+ if (getTE(te))
+ {
+ old_image_id = getTE(te)->getID();
+ }
- const LLUUID& image_id = getTE(te)->getID();
- LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id);
- mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ LLPrimitive::setTE(te, texture_entry);
-
- updateAvatarMeshVisibility(image_id,old_image_id);
+ const LLUUID& image_id = getTE(te)->getID();
+ LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id);
+ mTEImages[te] = bakedTexture ? bakedTexture : LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+
+ updateAvatarMeshVisibility(image_id, old_image_id);
+
+ updateTEMaterialTextures(te);
+}
+void LLViewerObject::updateTEMaterialTextures(U8 te)
+{
if (getTE(te)->getMaterialParams().notNull())
{
const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID();
@@ -4877,6 +4900,40 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID();
mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE);
}
+
+ auto fetch_texture = [](const LLUUID& id)
+ {
+ return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_ALM, LLViewerTexture::LOD_TEXTURE);
+ };
+
+ LLGLTFMaterial* mat = getTE(te)->getGLTFMaterial();
+ LLUUID mat_id = getRenderMaterialID(te);
+ if (mat == nullptr && mat_id.notNull())
+ {
+ mat = gGLTFMaterialList.getMaterial(mat_id);
+ getTE(te)->setGLTFMaterial(mat);
+ }
+ else if (mat_id.isNull() && mat != nullptr)
+ {
+ mat = nullptr;
+ getTE(te)->setGLTFMaterial(nullptr);
+ }
+
+ if (mat != nullptr)
+ {
+ mGLTFAlbedoMaps[te] = fetch_texture(mat->mAlbedoId);
+ mGLTFNormalMaps[te] = fetch_texture(mat->mNormalId);
+ mGLTFMetallicRoughnessMaps[te] = fetch_texture(mat->mMetallicRoughnessId);
+ mGLTFEmissiveMaps[te] = fetch_texture(mat->mEmissiveId);
+ }
+ else
+ {
+ mGLTFAlbedoMaps[te] = nullptr;
+ mGLTFNormalMaps[te] = nullptr;
+ mGLTFMetallicRoughnessMaps[te] = nullptr;
+ mGLTFEmissiveMaps[te] = nullptr;
+ }
+
}
void LLViewerObject::refreshBakeTexture()
@@ -5417,7 +5474,6 @@ void LLViewerObject::fitFaceTexture(const U8 face)
LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL;
}
-
LLBBox LLViewerObject::getBoundingBoxAgent() const
{
LLVector3 position_agent;
@@ -5502,18 +5558,6 @@ S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
return count;
}
-
-void LLViewerObject::setCanSelect(BOOL canSelect)
-{
- mbCanSelect = canSelect;
- for (child_list_t::iterator iter = mChildList.begin();
- iter != mChildList.end(); iter++)
- {
- LLViewerObject* child = *iter;
- child->mbCanSelect = canSelect;
- }
-}
-
void LLViewerObject::setDebugText(const std::string &utf8text)
{
if (utf8text.empty() && !mText)
@@ -6017,6 +6061,16 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
new_block = new LLExtendedMeshParams();
break;
}
+ case LLNetworkData::PARAMS_RENDER_MATERIAL:
+ {
+ new_block = new LLRenderMaterialParams();
+ break;
+ }
+ case LLNetworkData::PARAMS_REFLECTION_PROBE:
+ {
+ new_block = new LLReflectionProbeParams();
+ break;
+ }
default:
{
LL_INFOS() << "Unknown param type." << LL_ENDL;
@@ -6958,6 +7012,69 @@ LLVOAvatar* LLViewerObject::getAvatar() const
return NULL;
}
+bool LLViewerObject::hasRenderMaterialParams() const
+{
+ return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL);
+}
+
+void LLViewerObject::setHasRenderMaterialParams(bool has_materials)
+{
+ bool had_materials = hasRenderMaterialParams();
+
+ if (had_materials != has_materials)
+ {
+ if (has_materials)
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, TRUE, true);
+ }
+ else
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL, FALSE, true);
+ }
+ }
+}
+
+const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const
+{
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ return param_block->getMaterial(te);
+ }
+
+ return LLUUID::null;
+}
+
+void LLViewerObject::setRenderMaterialID(U8 te, const LLUUID& id)
+{
+ if (id.notNull())
+ {
+ getTE(te)->setGLTFMaterial(gGLTFMaterialList.getMaterial(id));
+ setHasRenderMaterialParams(true);
+ }
+ else
+ {
+ getTE(te)->setGLTFMaterial(nullptr);
+ }
+
+ faceMappingChanged();
+ gPipeline.markTextured(mDrawable);
+
+ LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
+ if (param_block)
+ {
+ param_block->setMaterial(te, id);
+
+ if (param_block->isEmpty())
+ { // might be empty if id is null
+ setHasRenderMaterialParams(false);
+ }
+ else
+ {
+ parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
+ }
+ }
+}
class ObjectPhysicsProperties : public LLHTTPNode
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bef8e3e7e3..109c96dc9c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -43,6 +43,7 @@
#include "llvertexbuffer.h"
#include "llbbox.h"
#include "llrigginginfo.h"
+#include "llreflectionmap.h"
class LLAgent; // TODO: Get rid of this.
class LLAudioSource;
@@ -178,6 +179,13 @@ public:
const std::string& getAttachmentItemName() const;
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
+
+ bool hasRenderMaterialParams() const;
+ void setHasRenderMaterialParams(bool has_params);
+
+ const LLUUID& getRenderMaterialID(U8 te) const;
+ void setRenderMaterialID(U8 te, const LLUUID& id);
+
virtual BOOL isHUDAttachment() const { return FALSE; }
virtual BOOL isTempAttachment() const;
@@ -199,6 +207,7 @@ public:
// Graphical stuff for objects - maybe broken out into render class later?
virtual void updateTextures();
+ virtual void faceMappingChanged() {}
virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object
virtual LLDrawable* createDrawable(LLPipeline *pipeline);
@@ -238,6 +247,7 @@ public:
virtual BOOL isMesh() const { return FALSE; }
virtual BOOL isRiggedMesh() const { return FALSE; }
virtual BOOL hasLightTexture() const { return FALSE; }
+ virtual BOOL isReflectionProbe() const { return FALSE; }
// This method returns true if the object is over land owned by
// the agent, one of its groups, or it encroaches and
@@ -279,6 +289,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -318,6 +329,7 @@ public:
/*virtual*/ void setNumTEs(const U8 num_tes);
/*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry);
+ void updateTEMaterialTextures(U8 te);
/*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid);
/*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid);
@@ -356,6 +368,12 @@ public:
LLViewerTexture *getTEImage(const U8 te) const;
LLViewerTexture *getTENormalMap(const U8 te) const;
LLViewerTexture *getTESpecularMap(const U8 te) const;
+
+ LLViewerTexture* getGLTFAlbedoMap(U8 te) const { return mGLTFAlbedoMaps[te]; }
+ LLViewerTexture* getGLTFNormalMap(U8 te) const { return mGLTFNormalMaps[te]; }
+ LLViewerTexture* getGLTFEmissiveMap(U8 te) const { return mGLTFEmissiveMaps[te]; }
+ LLViewerTexture* getGLTFMetallicRoughnessMap(U8 te) const { return mGLTFMetallicRoughnessMaps[te]; }
+
bool isImageAlphaBlended(const U8 te) const;
@@ -420,8 +438,6 @@ public:
void sendMaterialUpdate() const;
- void setCanSelect(BOOL canSelect);
-
void setDebugText(const std::string &utf8text);
void initHudText();
void restoreHudText();
@@ -674,10 +690,17 @@ public:
LLPointer<LLViewerTexture> *mTEImages;
LLPointer<LLViewerTexture> *mTENormalMaps;
LLPointer<LLViewerTexture> *mTESpecularMaps;
+
+ std::vector<LLPointer<LLViewerTexture> > mGLTFAlbedoMaps;
+ std::vector<LLPointer<LLViewerTexture> > mGLTFNormalMaps;
+ std::vector<LLPointer<LLViewerTexture> > mGLTFMetallicRoughnessMaps;
+ std::vector<LLPointer<LLViewerTexture> > mGLTFEmissiveMaps;
- // Selection, picking and rendering variables
- U32 mGLName; // GL "name" used by selection code
- BOOL mbCanSelect; // true if user can select this object by clicking
+
+
+ // true if user can select this object by clicking under any circumstances (even if pick_unselectable is true)
+ // can likely be factored out
+ BOOL mbCanSelect;
private:
// Grabbed from UPDATE_FLAGS
@@ -845,7 +868,7 @@ protected:
F32 mLinksetCost;
F32 mPhysicsCost;
F32 mLinksetPhysicsCost;
-
+
bool mCostStale;
mutable bool mPhysicsShapeUnknown;
@@ -904,6 +927,11 @@ private:
LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
EObjectUpdateType mLastUpdateType;
BOOL mLastUpdateCached;
+
+public:
+ // reflection probe state
+ bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager
+ LLPointer<LLReflectionMap> mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed
};
///////////////////
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 55e2386d10..389f5087e2 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -1339,38 +1339,13 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp)
}
// Don't clean up mObject references, these will be cleaned up more efficiently later!
- // Also, not cleaned up
- removeDrawable(objectp->mDrawable);
-
+
if(new_dead_object)
{
mNumDeadObjects++;
}
}
-void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE;
-
- if (!drawablep)
- {
- return;
- }
-
- for (S32 i = 0; i < drawablep->getNumFaces(); i++)
- {
- LLFace* facep = drawablep->getFace(i) ;
- if(facep)
- {
- LLViewerObject* objectp = facep->getViewerObject();
- if(objectp)
- {
- mSelectPickList.erase(objectp);
- }
- }
- }
-}
-
BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
{
// Don't ever kill gAgentAvatarp, just force it to the agent's region
@@ -1836,146 +1811,6 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 &center)
{
}
-void LLViewerObjectList::generatePickList(LLCamera &camera)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
-
- LLViewerObject *objectp;
- S32 i;
- // Reset all of the GL names to zero.
- for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter)
- {
- (*iter)->mGLName = 0;
- }
-
- mSelectPickList.clear();
-
- std::vector<LLDrawable*> pick_drawables;
-
- for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
- {
- LLViewerRegion* region = *iter;
- for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
- {
- LLSpatialPartition* part = region->getSpatialPartition(i);
- if (part)
- {
- part->cull(camera, &pick_drawables, TRUE);
- }
- }
- }
-
- for (std::vector<LLDrawable*>::iterator iter = pick_drawables.begin();
- iter != pick_drawables.end(); iter++)
- {
- LLDrawable* drawablep = *iter;
- if( !drawablep )
- continue;
-
- LLViewerObject* last_objectp = NULL;
- for (S32 face_num = 0; face_num < drawablep->getNumFaces(); face_num++)
- {
- LLFace * facep = drawablep->getFace(face_num);
- if (!facep) continue;
-
- LLViewerObject* objectp = facep->getViewerObject();
-
- if (objectp && objectp != last_objectp)
- {
- mSelectPickList.insert(objectp);
- last_objectp = objectp;
- }
- }
- }
-
- LLHUDNameTag::addPickable(mSelectPickList);
-
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- objectp = (LLVOAvatar*) *iter;
- if (!objectp->isDead())
- {
- if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible())
- {
- mSelectPickList.insert(objectp);
- }
- }
- }
-
- // add all hud objects to pick list
- if (isAgentAvatarValid())
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin();
- iter != gAgentAvatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = attachment_iter->get())
- {
- mSelectPickList.insert(attached_object);
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* childp = *iter;
- if (childp)
- {
- mSelectPickList.insert(childp);
- }
- }
- }
- }
- }
- }
- }
-
- S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances();
-
- if (num_pickables != 0)
- {
- S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables;
-
- std::set<LLViewerObject*>::iterator pick_it;
- i = 0;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();)
- {
- LLViewerObject* objp = (*pick_it);
- if (!objp || objp->isDead() || !objp->mbCanSelect)
- {
- mSelectPickList.erase(pick_it++);
- continue;
- }
-
- objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET;
- i++;
- ++pick_it;
- }
-
- LLHUDIcon::generatePickIDs(i * step, step);
- }
-}
-
-LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id)
-{
- std::set<LLViewerObject*>::iterator pick_it;
- for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end(); ++pick_it)
- {
- if ((*pick_it)->mGLName == object_id)
- {
- return (*pick_it);
- }
- }
- return NULL;
-}
-
void LLViewerObjectList::addDebugBeacon(const LLVector3 &pos_agent,
const std::string &string,
const LLColor4 &color,
diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h
index 72b2b99004..f2cba8c259 100644
--- a/indra/newview/llviewerobjectlist.h
+++ b/indra/newview/llviewerobjectlist.h
@@ -77,7 +77,6 @@ public:
BOOL killObject(LLViewerObject *objectp);
void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region.
void killAllObjects();
- void removeDrawable(LLDrawable* drawablep);
void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list.
@@ -129,11 +128,6 @@ public:
void updateAvatarVisibility();
- // Selection related stuff
- void generatePickList(LLCamera &camera);
-
- LLViewerObject *getSelectedObject(const U32 object_id);
-
inline S32 getNumObjects() { return (S32) mObjects.size(); }
inline S32 getNumActiveObjects() { return (S32) mActiveObjects.size(); }
@@ -226,8 +220,6 @@ protected:
static std::map<U64, LLUUID> sIndexAndLocalIDToUUID;
- std::set<LLViewerObject *> mSelectPickList;
-
friend class LLViewerObject;
private:
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b282a2b90c..9b7f4ff30d 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -3096,6 +3096,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UpdateSettingsAgentInventory");
capabilityNames.append("UpdateSettingsTaskInventory");
+ capabilityNames.append("UpdateMaterialAgentInventory");
+ capabilityNames.append("UpdateMaterialTaskInventory");
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("UserInfo");
capabilityNames.append("ViewerAsset");
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 086b433c72..e76f0b36ee 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -49,6 +49,8 @@
#include "lljoint.h"
#include "llskinningutil.h"
+//#pragma optimize("", off)
+
static LLStaticHashedString sTexture0("texture0");
static LLStaticHashedString sTexture1("texture1");
static LLStaticHashedString sTex0("tex0");
@@ -82,6 +84,9 @@ LLGLSLShader gOcclusionCubeProgram;
LLGLSLShader gCustomAlphaProgram;
LLGLSLShader gGlowCombineProgram;
LLGLSLShader gSplatTextureRectProgram;
+LLGLSLShader gReflectionMipProgram;
+LLGLSLShader gRadianceGenProgram;
+LLGLSLShader gIrradianceGenProgram;
LLGLSLShader gGlowCombineFXAAProgram;
LLGLSLShader gTwoTextureAddProgram;
LLGLSLShader gTwoTextureCompareProgram;
@@ -258,6 +263,8 @@ LLGLSLShader gNormalMapGenProgram;
// Deferred materials shaders
LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+LLGLSLShader gDeferredPBROpaqueProgram;
+LLGLSLShader gDeferredSkinnedPBROpaqueProgram;
//helper for making a rigged variant of a given shader
bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader)
@@ -489,6 +496,7 @@ void LLViewerShaderMgr::setShaders()
bool canRenderDeferred = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
bool hasWindLightShaders = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");
S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
+ bool pbr = gSavedSettings.getBOOL("RenderPBR");
bool doingWindLight = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders");
bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred");
@@ -528,6 +536,11 @@ void LLViewerShaderMgr::setShaders()
}
}
+ if (deferred_class > 0 && pbr)
+ {
+ deferred_class = 3;
+ }
+
if (doingWindLight)
{
// user has disabled WindLight in their settings, downgrade
@@ -641,7 +654,6 @@ void LLViewerShaderMgr::setShaders()
}
if (loaded)
-
{
loaded = loadTransformShaders();
if (loaded)
@@ -660,8 +672,8 @@ void LLViewerShaderMgr::setShaders()
// Load max avatar shaders to set the max level
mShaderLevel[SHADER_AVATAR] = 3;
mMaxAvatarShaderLevel = 3;
-
- if (loadShadersObject())
+
+ if (loadShadersObject())
{ //hardware skinning is enabled and rigged attachment shaders loaded correctly
BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
@@ -752,6 +764,9 @@ void LLViewerShaderMgr::unloadShaders()
gCustomAlphaProgram.unload();
gGlowCombineProgram.unload();
gSplatTextureRectProgram.unload();
+ gReflectionMipProgram.unload();
+ gRadianceGenProgram.unload();
+ gIrradianceGenProgram.unload();
gGlowCombineFXAAProgram.unload();
gTwoTextureAddProgram.unload();
gTwoTextureCompareProgram.unload();
@@ -975,6 +990,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] ) );
@@ -1218,7 +1234,8 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
BOOL LLViewerShaderMgr::loadShadersDeferred()
{
- bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1;
+ bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1 &&
+ gSavedSettings.getS32("RenderShadowDetail") > 0;
BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable");
BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable");
@@ -1307,6 +1324,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].unload();
gDeferredMaterialWaterProgram[i].unload();
}
+
+ gDeferredPBROpaqueProgram.unload();
+ gDeferredSkinnedPBROpaqueProgram.unload();
+
return TRUE;
}
@@ -1498,6 +1519,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
gDeferredMaterialProgram[i].mFeatures.hasShadows = use_sun_shadow;
+ if (mShaderLevel[SHADER_DEFERRED] > 2)
+ {
+ gDeferredMaterialProgram[i].mFeatures.hasReflectionProbes = true;
+ gDeferredMaterialProgram[i].addPermutation("HAS_REFLECTION_PROBES", "1");
+ }
+
if (has_skin)
{
gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1");
@@ -1611,6 +1638,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true;
gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true;
+ if (success)
+ {
+ gDeferredPBROpaqueProgram.mName = "Deferred PBR Opaque Shader";
+ gDeferredPBROpaqueProgram.mFeatures.encodesNormal = true;
+ gDeferredPBROpaqueProgram.mFeatures.hasSrgb = true;
+
+ gDeferredPBROpaqueProgram.mShaderFiles.clear();
+ gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredPBROpaqueProgram.addPermutation("HAS_NORMAL_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("HAS_SPECULAR_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("HAS_EMISSIVE_MAP", "1");
+ gDeferredPBROpaqueProgram.addPermutation("DIFFUSE_ALPHA_MODE", "0");
+
+ success = make_rigged_variant(gDeferredPBROpaqueProgram, gDeferredSkinnedPBROpaqueProgram);
+ if (success)
+ {
+ success = gDeferredPBROpaqueProgram.createShader(NULL, NULL);
+ }
+ llassert(success);
+ }
if (success)
{
@@ -2181,6 +2230,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)
+ {
+ gDeferredFullbrightShinyProgram.addPermutation("HAS_REFLECTION_PROBES", "1");
+ gDeferredFullbrightShinyProgram.mFeatures.hasReflectionProbes = true;
+ }
success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram);
success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
llassert(success);
@@ -2253,6 +2307,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenProgram.mFeatures.hasGamma = true;
gDeferredSoftenProgram.mFeatures.isDeferred = true;
gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2;
gDeferredSoftenProgram.clearPermutations();
gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -2260,6 +2315,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (use_sun_shadow)
+ {
+ gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1");
+ }
+
if (ambient_kill)
{
gDeferredSoftenProgram.addPermutation("AMBIENT_KILL", "1");
@@ -2278,6 +2338,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
{ //if using SSAO, take screen space light map into account as if shadows are enabled
gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2);
+ gDeferredSoftenProgram.addPermutation("HAS_SSAO", "1");
}
success = gDeferredSoftenProgram.createShader(NULL, NULL);
@@ -2303,6 +2364,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;
gDeferredSoftenWaterProgram.mFeatures.hasShadows = use_sun_shadow;
+ gDeferredSoftenWaterProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2;
+
+ if (use_sun_shadow)
+ {
+ gDeferredSoftenWaterProgram.addPermutation("HAS_SUN_SHADOW", "1");
+ }
if (ambient_kill)
{
@@ -2317,6 +2384,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (local_light_kill)
{
gDeferredSoftenWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+ gDeferredSoftenWaterProgram.addPermutation("HAS_SSAO", "1");
}
if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
@@ -3574,7 +3642,6 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
}
}
-
if (success)
{
gTwoTextureAddProgram.mName = "Two Texture Add Shader";
@@ -3750,6 +3817,42 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
success = gAlphaMaskProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gReflectionMipProgram.mName = "Reflection Mip Shader";
+ gReflectionMipProgram.mShaderFiles.clear();
+ gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB));
+ gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gReflectionMipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gReflectionMipProgram.createShader(NULL, NULL);
+ if (success)
+ {
+ gReflectionMipProgram.bind();
+ gReflectionMipProgram.uniform1i(sScreenMap, 0);
+ gReflectionMipProgram.unbind();
+ }
+ }
+
+ 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)
+ {
+ 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 93bb29a355..87d90b49a9 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -161,6 +161,9 @@ extern LLGLSLShader gOcclusionCubeProgram;
extern LLGLSLShader gCustomAlphaProgram;
extern LLGLSLShader gGlowCombineProgram;
extern LLGLSLShader gSplatTextureRectProgram;
+extern LLGLSLShader gReflectionMipProgram;
+extern LLGLSLShader gRadianceGenProgram;
+extern LLGLSLShader gIrradianceGenProgram;
extern LLGLSLShader gGlowCombineFXAAProgram;
extern LLGLSLShader gDebugProgram;
extern LLGLSLShader gClipProgram;
@@ -313,4 +316,6 @@ extern LLGLSLShader gNormalMapGenProgram;
// Deferred materials shaders
extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
extern LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+
+extern LLGLSLShader gDeferredPBROpaqueProgram;
#endif
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index e2de7ac825..7c860936a5 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -879,6 +879,7 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_MESH:
+ case DAD_MATERIAL:
{
supported = true;
break;
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index e3ac56d0d3..c389d2122e 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -287,6 +287,13 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
return tex;
}
+LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps)
+{
+ LLViewerFetchedTexture* ret = new LLViewerFetchedTexture(raw, type, usemipmaps);
+ gTextureList.addImage(ret, TEX_LIST_STANDARD);
+ return ret;
+}
+
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
const LLUUID &image_id,
FTType f_type,
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index b953d7006b..53cf911102 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -668,6 +668,8 @@ public:
static LLPointer<LLViewerTexture> getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
static LLPointer<LLViewerTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ;
+ static LLViewerFetchedTexture* getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps);
+
static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
FTType f_type = FTT_DEFAULT,
BOOL usemipmap = TRUE,
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 119859a4ac..e102c917ee 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -227,6 +227,7 @@ extern BOOL gDebugClicks;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDepthDirty;
extern BOOL gResizeScreenTexture;
+extern BOOL gCubeSnapshot;
LLViewerWindow *gViewerWindow = NULL;
@@ -3375,7 +3376,7 @@ void LLViewerWindow::updateUI()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
{
gDebugRaycastFaceHit = -1;
- gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE,
+ gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE,
&gDebugRaycastFaceHit,
&gDebugRaycastIntersection,
&gDebugRaycastTexCoord,
@@ -4199,13 +4200,16 @@ void LLViewerWindow::pickAsync( S32 x,
BOOL pick_rigged,
BOOL pick_unselectable)
{
- BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = TRUE;
- }
+ // "Show Debug Alpha" means no object actually transparent
+ BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
+ if (LLDrawPoolAlpha::sShowDebugAlpha)
+ {
+ pick_transparent = TRUE;
+ }
+ else if (in_build_mode && !gSavedSettings.getBOOL("SelectInvisibleObjects"))
+ {
+ pick_transparent = FALSE;
+ }
LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, TRUE, pick_unselectable, callback);
schedulePick(pick_info);
@@ -4263,10 +4267,10 @@ void LLViewerWindow::returnEmptyPicks()
}
// Performs the GL object/land pick.
-LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle)
+LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable)
{
BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
+ if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha)
{
// build mode allows interaction with all transparent objects
// "Show Debug Alpha" means no object actually transparent
@@ -4312,6 +4316,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
S32 this_face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a *intersection,
LLVector2 *uv,
@@ -4382,7 +4387,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
{
if (this_object->isHUDAttachment()) // is a HUD object?
{
- if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -4390,7 +4395,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
}
else // is a world object
{
- if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged,
+ if (this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent))
{
found = this_object;
@@ -4404,7 +4409,7 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de
if (!found) // if not found in HUD, look in world:
{
- found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged,
+ found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable,
face_hit, intersection, uv, normal, tangent);
if (found && !pick_transparent)
{
@@ -4931,8 +4936,8 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA;
if (scratch_space.allocate(image_width, image_height, color_fmt, true, true))
{
- original_width = gPipeline.mDeferredScreen.getWidth();
- original_height = gPipeline.mDeferredScreen.getHeight();
+ original_width = gPipeline.mRT->deferredScreen.getWidth();
+ original_height = gPipeline.mRT->deferredScreen.getHeight();
if (gPipeline.allocateScreenBuffer(image_width, image_height))
{
@@ -5011,8 +5016,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- gObjectList.generatePickList(*LLViewerCamera::getInstance());
-
// Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen.
// In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y
for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
@@ -5175,6 +5178,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
gDisplaySwapBuffers = FALSE;
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -5189,8 +5193,8 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
LLPipeline::sShowHUDAttachments = FALSE;
LLRect window_rect = getWorldViewRectRaw();
- S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
- S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mDeferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
+ S32 original_width = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getWidth() : gViewerWindow->getWorldViewWidthRaw();
+ S32 original_height = LLPipeline::sRenderDeferred ? gPipeline.mRT->deferredScreen.getHeight() : gViewerWindow->getWorldViewHeightRaw();
LLRenderTarget scratch_space;
U32 color_fmt = GL_RGBA;
@@ -5271,6 +5275,149 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
return true;
}
+void display_cube_face();
+
+BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render)
+{
+ // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
+ LL_PROFILE_GPU_ZONE("cubeSnapshot");
+ llassert(LLPipeline::sRenderDeferred);
+ llassert(!gCubeSnapshot); //assert a snapshot isn't already in progress
+
+ U32 res = LLRenderTarget::sCurResX;
+
+ llassert(res <= gPipeline.mRT->deferredScreen.getWidth());
+ llassert(res <= gPipeline.mRT->deferredScreen.getHeight());
+
+ // save current view/camera settings so we can restore them afterwards
+ S32 old_occlusion = LLPipeline::sUseOcclusion;
+
+ // set new parameters specific to the 360 requirements
+ LLPipeline::sUseOcclusion = 0;
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+
+ LLViewerCamera saved_camera = LLViewerCamera::instance();
+ glh::matrix4f saved_proj = get_current_projection();
+ glh::matrix4f saved_mod = get_current_modelview();
+
+ // camera constants for the square, cube map capture image
+ camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
+ camera->setView(F_PI_BY_TWO);
+ camera->yaw(0.0);
+ camera->setOrigin(origin);
+ camera->setNear(near_clip);
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ U32 dynamic_render_types[] = {
+ LLPipeline::RENDER_TYPE_AVATAR,
+ LLPipeline::RENDER_TYPE_CONTROL_AV,
+ LLPipeline::RENDER_TYPE_PARTICLES
+ };
+ constexpr U32 dynamic_render_type_count = sizeof(dynamic_render_types) / sizeof(U32);
+ bool prev_dynamic_render_type[dynamic_render_type_count];
+
+
+ if (!dynamic_render)
+ {
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ prev_dynamic_render_type[i] = gPipeline.hasRenderType(dynamic_render_types[i]);
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
+ }
+
+ BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE;
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ LLPipeline::sShowHUDAttachments = FALSE;
+ LLRect window_rect = getWorldViewRectRaw();
+
+ mWorldViewRectRaw.set(0, res, res, 0);
+
+ // these are the 6 directions we will point the camera, see LLCubeMapArray::sTargets
+ LLVector3 look_dirs[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 look_upvecs[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)
+ };
+
+ // for each of six sides of cubemap
+ //for (int i = 0; i < 6; ++i)
+ int i = face;
+ {
+ // set up camera to look in each direction
+ camera->lookDir(look_dirs[i], look_upvecs[i]);
+
+ // turning this flag off here prohibits the screen swap
+ // to present the new page to the viewer - this stops
+ // the black flash in between captures when the number
+ // of render passes is more than 1. We need to also
+ // set it here because code in LLViewerDisplay resets
+ // it to TRUE each time.
+ gDisplaySwapBuffers = FALSE;
+
+ // actually render the scene
+ gCubeSnapshot = TRUE;
+ display_cube_face();
+ gCubeSnapshot = FALSE;
+ }
+
+ gDisplaySwapBuffers = TRUE;
+
+ if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ if (prev_draw_ui != false)
+ {
+ LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ }
+
+ if (!dynamic_render)
+ {
+ for (int i = 0; i < dynamic_render_type_count; ++i)
+ {
+ if (prev_dynamic_render_type[i])
+ {
+ gPipeline.toggleRenderType(dynamic_render_types[i]);
+ }
+ }
+ }
+
+ LLPipeline::sShowHUDAttachments = TRUE;
+
+ gPipeline.resetDrawOrders();
+ mWorldViewRectRaw = window_rect;
+
+ // restore original view/camera/avatar settings settings
+ *camera = saved_camera;
+ set_current_modelview(saved_mod);
+ set_current_projection(saved_proj);
+ LLPipeline::sUseOcclusion = old_occlusion;
+
+ // ====================================================
+ return true;
+}
+
void LLViewerWindow::destroyWindow()
{
if (mWindow)
@@ -5943,7 +6090,7 @@ void LLPickInfo::fetchResults()
}
LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
- NULL, -1, mPickTransparent, mPickRigged, &face_hit,
+ NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, &face_hit,
&intersection, &uv, &normal, &tangent, &start, &end);
mPickPt = mMousePt;
@@ -6088,7 +6235,7 @@ void LLPickInfo::getSurfaceInfo()
if (objectp)
{
if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f,
- objectp, -1, mPickTransparent, mPickRigged,
+ objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable,
&mObjectFace,
&intersection,
&mSTCoords,
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 979a560508..387a2cb06f 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -68,6 +68,8 @@ class LLWindowListener;
class LLViewerWindowListener;
class LLVOPartGroup;
class LLPopupView;
+class LLCubeMap;
+class LLCubeMapArray;
#define PICK_HALF_WIDTH 5
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -360,6 +362,20 @@ public:
BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes);
+
+
+ // take a cubemap snapshot
+ // origin - vantage point to take the snapshot from
+ // cubearray - cubemap array for storing the results
+ // index - cube index in the array to use (cube index, not face-layer)
+ // face - which cube face to update
+ // near_clip - near clip setting to use
+ BOOL cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars);
+
+
+ // special implementation of simpleSnapshot for reflection maps
+ BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes);
+
BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type);
BOOL isSnapshotLocSet() const;
void resetSnapshotLoc() const;
@@ -389,7 +405,7 @@ public:
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
BOOL pick_unselectable = FALSE);
- LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE);
+ LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE);
LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
LLVector4a* intersection);
@@ -398,6 +414,7 @@ public:
S32 this_face = -1,
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL,
LLVector4a *intersection = NULL,
LLVector2 *uv = NULL,
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 5c76f7b392..e55ee21414 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1777,6 +1777,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -1883,6 +1884,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -1913,7 +1915,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector
{
LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
+ if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 3c3decaad6..a085d773dc 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -164,6 +164,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -174,6 +175,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index 9a41eedb54..d109b7b34f 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -758,7 +758,7 @@ void LLVOGrass::updateDrawable(BOOL force_damped)
}
// virtual
-BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOGrass::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h
index 5634e048eb..63876dc099 100644
--- a/indra/newview/llvograss.h
+++ b/indra/newview/llvograss.h
@@ -79,6 +79,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 068e8a131d..cb4315a774 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -485,6 +485,7 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
@@ -756,6 +757,7 @@ LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) :
void LLParticlePartition::rebuildGeom(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED;
+ LL_PROFILE_GPU_ZONE("particle vbo");
if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY))
{
return;
diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h
index 4e4d6e609d..a45d381dfa 100644
--- a/indra/newview/llvopartgroup.h
+++ b/indra/newview/llvopartgroup.h
@@ -74,6 +74,7 @@ public:
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
+ BOOL pick_unselectable,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index b0af565867..6b56eaeb4a 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -880,7 +880,7 @@ void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride,
}
}
-BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index 884dbb3be3..aed67162d1 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -85,6 +85,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 493162b47b..e26791aa29 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -1170,7 +1170,7 @@ void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
mDrawable->setPositionGroup(pos);
}
-BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOTree::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index 93c22d2da3..996e970cf8 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -111,6 +111,7 @@ public:
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index f4a938e57d..d654c470e2 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -105,6 +105,8 @@ S32 LLVOVolume::mRenderComplexity_current = 0;
LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
+extern BOOL gCubeSnapshot;
+
// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
{
@@ -742,7 +744,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
// Update the pixel area of all faces
- if (mDrawable.isNull())
+ if (mDrawable.isNull() || gCubeSnapshot)
{
return;
}
@@ -1008,7 +1010,12 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
// Add it to the pipeline mLightSet
gPipeline.setLight(mDrawable, TRUE);
}
-
+
+ if (isReflectionProbe())
+ {
+ updateReflectionProbePtr();
+ }
+
updateRadius();
bool force_update = true; // avoid non-alpha mDistance update being optimized away
mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
@@ -2176,7 +2183,8 @@ void LLVOVolume::setNumTEs(const U8 num_tes)
return ;
}
-//virtual
+
+//virtual
void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep)
{
BOOL changed = (mTEImages[index] != imagep);
@@ -3408,6 +3416,11 @@ F32 LLVOVolume::getSpotLightPriority() const
void LLVOVolume::updateSpotLightPriority()
{
+ if (gCubeSnapshot)
+ {
+ return;
+ }
+
F32 r = getLightRadius();
LLVector3 pos = mDrawable->getPositionAgent();
@@ -3510,6 +3523,129 @@ F32 LLVOVolume::getLightCutoff() const
}
}
+BOOL LLVOVolume::isReflectionProbe() const
+{
+ return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE);
+}
+
+void LLVOVolume::setIsReflectionProbe(BOOL is_probe)
+{
+ BOOL was_probe = isReflectionProbe();
+ if (is_probe != was_probe)
+ {
+ if (is_probe)
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, TRUE, true);
+ }
+ else
+ {
+ setParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE, FALSE, true);
+ }
+ }
+
+ updateReflectionProbePtr();
+}
+
+void LLVOVolume::setReflectionProbeAmbiance(F32 ambiance)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getAmbiance() != ambiance)
+ {
+ param_block->setAmbiance(ambiance);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeNearClip(F32 near_clip)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getClipDistance() != near_clip)
+ {
+ param_block->setClipDistance(near_clip);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeIsBox(bool is_box)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsBox() != is_box)
+ {
+ param_block->setIsBox(is_box);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+void LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic)
+{
+ LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ if (param_block->getIsDynamic() != is_dynamic)
+ {
+ param_block->setIsDynamic(is_dynamic);
+ parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true);
+ }
+ }
+}
+
+F32 LLVOVolume::getReflectionProbeAmbiance() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getAmbiance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+F32 LLVOVolume::getReflectionProbeNearClip() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getClipDistance();
+ }
+ else
+ {
+ return 0.f;
+ }
+}
+
+bool LLVOVolume::getReflectionProbeIsBox() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsBox();
+ }
+
+ return false;
+}
+
+bool LLVOVolume::getReflectionProbeIsDynamic() const
+{
+ const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE);
+ if (param_block)
+ {
+ return param_block->getIsDynamic();
+ }
+
+ return false;
+}
+
U32 LLVOVolume::getVolumeInterfaceID() const
{
if (mVolumeImpl)
@@ -4395,6 +4531,23 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u
gPipeline.setLight(mDrawable, is_light);
}
}
+
+ updateReflectionProbePtr();
+}
+
+void LLVOVolume::updateReflectionProbePtr()
+{
+ if (isReflectionProbe())
+ {
+ if (mReflectionProbe.isNull())
+ {
+ mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this);
+ }
+ }
+ else if (mReflectionProbe.notNull())
+ {
+ mReflectionProbe = nullptr;
+ }
}
void LLVOVolume::setSelected(BOOL sel)
@@ -4594,7 +4747,7 @@ LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const
}
-BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, S32 *face_hitp,
+BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32 *face_hitp,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
{
@@ -4605,6 +4758,14 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
+ if (!pick_unselectable)
+ {
+ if (!LLSelectMgr::instance().canSelectObject(this))
+ {
+ return FALSE;
+ }
+ }
+
BOOL ret = FALSE;
LLVolume* volume = getVolume();
@@ -5237,10 +5398,26 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LLViewerTexture* tex = facep->getTexture();
+
U8 index = facep->getTextureIndex();
- LLMaterial* mat = facep->getTextureEntry()->getMaterialParams().get();
- LLMaterialID mat_id = facep->getTextureEntry()->getMaterialID();
+ LLMaterial* mat = nullptr;
+
+ LLUUID mat_id;
+
+ LLGLTFMaterial* gltf_mat = facep->getTextureEntry()->getGLTFMaterial();
+ if (gltf_mat != nullptr)
+ {
+ mat_id = gltf_mat->getHash(); // TODO: cache this hash
+ }
+ else
+ {
+ mat = facep->getTextureEntry()->getMaterialParams().get();
+ if (mat)
+ {
+ mat_id = facep->getTextureEntry()->getMaterialID().asUUID();
+ }
+ }
bool batchable = false;
@@ -5262,7 +5439,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0)
{
- if (mat || draw_vec[idx]->mMaterial)
+ if (mat || gltf_mat || draw_vec[idx]->mMaterial)
{ //can't batch textures when materials are present (yet)
batchable = false;
}
@@ -5294,7 +5471,6 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
#endif
- //draw_vec[idx]->mMaterial == mat &&
draw_vec[idx]->mMaterialID == mat_id &&
draw_vec[idx]->mFullbright == fullbright &&
draw_vec[idx]->mBump == bump &&
@@ -5351,11 +5527,22 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_info->mEnvIntensity = spec;
draw_info->mSpecularMap = NULL;
draw_info->mMaterial = mat;
+ draw_info->mGLTFMaterial = gltf_mat;
draw_info->mShaderMask = shader_mask;
draw_info->mAvatar = facep->mAvatar;
draw_info->mSkinInfo = facep->mSkinInfo;
- if (mat)
+ if (gltf_mat)
+ {
+ LLViewerObject* vobj = facep->getViewerObject();
+ U8 te = facep->getTEOffset();
+
+ draw_info->mTexture = vobj->getGLTFAlbedoMap(te);
+ draw_info->mNormalMap = vobj->getGLTFNormalMap(te);
+ draw_info->mSpecularMap = vobj->getGLTFMetallicRoughnessMap(te);
+ draw_info->mEmissiveMap = vobj->getGLTFEmissiveMap(te);
+ }
+ else if (mat)
{
draw_info->mMaterialID = mat_id;
@@ -5517,6 +5704,8 @@ static inline void add_face(T*** list, U32* count, T* face)
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
+ llassert(!gCubeSnapshot);
+
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -5694,6 +5883,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
continue;
}
+ // HACK -- brute force this check every time a drawable gets rebuilt
+ vobj->updateTEMaterialTextures(i);
+#if 0
+#if LL_RELEASE_WITH_DEBUG_INFO
+ const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" );
+ const LLUUID obj_id( vobj->getID() );
+ bool is_pbr = (obj_id == pbr_id);
+#else
+ bool is_pbr = false;
+#endif
+#else
+ bool is_pbr = facep->getTextureEntry()->getGLTFMaterial() != nullptr;
+#endif
+
//ALWAYS null out vertex buffer on rebuild -- if the face lands in a render
// batch, it will recover its vertex buffer reference from the spatial group
facep->setVertexBuffer(NULL);
@@ -5759,6 +5962,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA);
U32 type = gPipeline.getPoolTypeFromTE(te, tex);
+
+ if (is_pbr)
+ {
+ type = LLDrawPool::POOL_PBR_OPAQUE;
+ }
+ else
if (type != LLDrawPool::POOL_ALPHA && force_simple)
{
type = LLDrawPool::POOL_SIMPLE;
@@ -5823,28 +6032,39 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if (gPipeline.canUseWindLightShadersOnObjects()
&& LLPipeline::sRenderBump)
{
- if (LLPipeline::sRenderDeferred && te->getMaterialParams().notNull() && !te->getMaterialID().isNull())
+ LLGLTFMaterial* gltf_mat = te->getGLTFMaterial();
+
+ if (LLPipeline::sRenderDeferred &&
+ (gltf_mat != nullptr || (te->getMaterialParams().notNull() && !te->getMaterialID().isNull())))
{
- LLMaterial* mat = te->getMaterialParams().get();
- if (mat->getNormalID().notNull())
- {
- if (mat->getSpecularID().notNull())
- { //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
- add_face(sNormSpecFaces, normspec_count, facep);
- }
- else
- { //has normal map (needs texcoord1 and tangent)
- add_face(sNormFaces, norm_count, facep);
- }
- }
- else if (mat->getSpecularID().notNull())
- { //has specular map but no normal map, needs texcoord2
- add_face(sSpecFaces, spec_count, facep);
- }
- else
- { //has neither specular map nor normal map, only needs texcoord0
- add_face(sSimpleFaces, simple_count, facep);
- }
+ if (gltf_mat != nullptr)
+ {
+ // all gltf materials have all vertex attributes for now
+ add_face(sNormSpecFaces, normspec_count, facep);
+ }
+ else
+ {
+ LLMaterial* mat = te->getMaterialParams().get();
+ if (mat->getNormalID().notNull())
+ {
+ if (mat->getSpecularID().notNull())
+ { //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
+ add_face(sNormSpecFaces, normspec_count, facep);
+ }
+ else
+ { //has normal map (needs texcoord1 and tangent)
+ add_face(sNormFaces, norm_count, facep);
+ }
+ }
+ else if (mat->getSpecularID().notNull())
+ { //has specular map but no normal map, needs texcoord2
+ add_face(sSpecFaces, spec_count, facep);
+ }
+ else
+ { //has neither specular map nor normal map, only needs texcoord0
+ add_face(sSimpleFaces, simple_count, facep);
+ }
+ }
}
else if (te->getBumpmap())
{ //needs normal + tangent
@@ -6531,15 +6751,24 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
- LLMaterial* mat = te->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = te->getGLTFMaterial();
- bool can_be_shiny = true;
- if (mat)
- {
- U8 mode = mat->getDiffuseAlphaMode();
- can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
- mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
- }
+ LLMaterial* mat = nullptr;
+ bool can_be_shiny = false;
+
+ // ignore traditional material if GLTF material is present
+ if (gltf_mat == nullptr)
+ {
+ mat = te->getMaterialParams().get();
+
+ can_be_shiny = true;
+ if (mat)
+ {
+ U8 mode = mat->getDiffuseAlphaMode();
+ can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
+ mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
+ }
+ }
F32 te_alpha = te->getColor().mV[3];
bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull());
@@ -6548,10 +6777,15 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
is_alpha = (is_alpha || transparent) ? TRUE : FALSE;
- if (mat && LLPipeline::sRenderDeferred && !hud_group)
+ if ((gltf_mat || mat) && LLPipeline::sRenderDeferred && !hud_group)
{
bool material_pass = false;
+ if (gltf_mat)
+ { // all other parameters ignored if gltf material is present
+ registerFace(group, facep, LLRenderPass::PASS_PBR_OPAQUE);
+ }
+ else
// do NOT use 'fullbright' for this logic or you risk sending
// things without normals down the materials pipeline and will
// render poorly if not crash NORSPEC-240,314
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 4136c13315..391351c13e 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -114,49 +114,50 @@ public:
};
public:
- LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
- /*virtual*/ void markDead(); // Override (and call through to parent) to clean up media references
+ LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
+ void markDead() override; // Override (and call through to parent) to clean up media references
- /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
+ LLDrawable* createDrawable(LLPipeline *pipeline) override;
void deleteFaces();
void animateTextures();
BOOL isVisible() const ;
- /*virtual*/ BOOL isActive() const;
- /*virtual*/ BOOL isAttachment() const;
- /*virtual*/ BOOL isRootEdit() const; // overridden for sake of attachments treating themselves as a root object
- /*virtual*/ BOOL isHUDAttachment() const;
+ BOOL isActive() const override;
+ BOOL isAttachment() const override;
+ BOOL isRootEdit() const override; // overridden for sake of attachments treating themselves as a root object
+ BOOL isHUDAttachment() const override;
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
- /*virtual*/ BOOL setParent(LLViewerObject* parent);
- S32 getLOD() const { return mLOD; }
+ /*virtual*/ BOOL setParent(LLViewerObject* parent) override;
+ S32 getLOD() const override { return mLOD; }
void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; }
bool isNoLOD() const { return NO_LOD == mLOD; }
- const LLVector3 getPivotPositionAgent() const;
+ const LLVector3 getPivotPositionAgent() const override;
const LLMatrix4& getRelativeXform() const { return mRelativeXform; }
const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; }
- /*virtual*/ const LLMatrix4 getRenderMatrix() const;
+ /*virtual*/ const LLMatrix4 getRenderMatrix() const override;
typedef std::map<LLUUID, S32> texture_cost_t;
U32 getRenderCost(texture_cost_t &textures) const;
- /*virtual*/ F32 getEstTrianglesMax() const;
- /*virtual*/ F32 getEstTrianglesStreamingCost() const;
- /* virtual*/ F32 getStreamingCost() const;
- /*virtual*/ bool getCostData(LLMeshCostData& costs) const;
+ /*virtual*/ F32 getEstTrianglesMax() const override;
+ /*virtual*/ F32 getEstTrianglesStreamingCost() const override;
+ /* virtual*/ F32 getStreamingCost() const override;
+ /*virtual*/ bool getCostData(LLMeshCostData& costs) const override;
- /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const;
- /*virtual*/ U32 getHighLODTriangleCount();
+ /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const override;
+ /*virtual*/ U32 getHighLODTriangleCount() override;
/*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
S32 face = -1, // which face to check, -1 = ALL_SIDES
BOOL pick_transparent = FALSE,
BOOL pick_rigged = FALSE,
+ BOOL pick_unselectable = TRUE,
S32* face_hit = NULL, // which face was hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
LLVector4a* normal = NULL, // return the surface normal at the intersection point
LLVector4a* tangent = NULL // return the surface tangent at the intersection point
- );
+ ) override;
LLVector3 agentPositionToVolume(const LLVector3& pos) const;
LLVector3 agentDirectionToVolume(const LLVector3& dir) const;
@@ -166,55 +167,58 @@ public:
BOOL getVolumeChanged() const { return mVolumeChanged; }
- /*virtual*/ F32 getRadius() const { return mVObjRadius; };
- const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
+ F32 getVObjRadius() const override { return mVObjRadius; };
+ const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const override;
- void markForUpdate(BOOL priority);
+ void markForUpdate(BOOL priority) override;
void markForUnload() { LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; }
- void faceMappingChanged() { mFaceMappingChanged=TRUE; };
+ void faceMappingChanged() override { mFaceMappingChanged=TRUE; }
- /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts
+ /*virtual*/ void onShift(const LLVector4a &shift_vector) override; // Called when the drawable shifts
- /*virtual*/ void parameterChanged(U16 param_type, bool local_origin);
- /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
+ /*virtual*/ void parameterChanged(U16 param_type, bool local_origin) override;
+ /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) override;
+
+ // update mReflectionProbe based on isReflectionProbe()
+ void updateReflectionProbePtr();
/*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num, const EObjectUpdateType update_type,
- LLDataPacker *dp);
-
- /*virtual*/ void setSelected(BOOL sel);
- /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp);
-
- /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped);
-
- /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) ;
- /*virtual*/ void setNumTEs(const U8 num_tes);
- /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep);
- /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
- /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color);
- /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color);
- /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump);
- /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny);
- /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright);
- /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump);
- /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags);
- /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
- /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
+ LLDataPacker *dp) override;
+
+ /*virtual*/ void setSelected(BOOL sel) override;
+ /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp) override;
+
+ /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped) override;
+
+ /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) override;
+ /*virtual*/ void setNumTEs(const U8 num_tes) override;
+ /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep) override;
+ /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid) override;
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color) override;
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color) override;
+ /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override;
+ /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override;
+ /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override;
+ /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override;
+ /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override;
+ /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override;
+ /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) override;
static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te);
- /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams);
- /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
- /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
- /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
- /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen);
- /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media);
- /*virtual*/ BOOL setMaterial(const U8 material);
+ /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) override;
+ /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t) override;
+ /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s) override;
+ /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t) override;
+ /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen) override;
+ /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media) override;
+ /*virtual*/ BOOL setMaterial(const U8 material) override;
void setTexture(const S32 face);
S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];}
- /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
+ /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override;
void updateSculptTexture();
void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;}
void sculpt();
@@ -223,21 +227,21 @@ public:
void* user_data, S32 status, LLExtStat ext_status);
void updateRelativeXform(bool force_identity = false);
- /*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
- /*virtual*/ void updateFaceSize(S32 idx);
- /*virtual*/ BOOL updateLOD();
- void updateRadius();
- /*virtual*/ void updateTextures();
+ /*virtual*/ BOOL updateGeometry(LLDrawable *drawable) override;
+ /*virtual*/ void updateFaceSize(S32 idx) override;
+ /*virtual*/ BOOL updateLOD() override;
+ void updateRadius() override;
+ /*virtual*/ void updateTextures() override;
void updateTextureVirtualSize(bool forced = false);
void updateFaceFlags();
void regenFaces();
BOOL genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = TRUE);
void preRebuild();
- virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max);
- virtual F32 getBinRadius();
+ virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max) override;
+ virtual F32 getBinRadius() override;
- virtual U32 getPartitionType() const;
+ virtual U32 getPartitionType() const override;
// For Lights
void setIsLight(BOOL is_light);
@@ -280,14 +284,27 @@ public:
F32 getLightRadius() const;
F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
F32 getLightCutoff() const;
-
+
+ // Reflection Probes
+ void setIsReflectionProbe(BOOL is_probe);
+ void setReflectionProbeAmbiance(F32 ambiance);
+ void setReflectionProbeNearClip(F32 near_clip);
+ void setReflectionProbeIsBox(bool is_box);
+ void setReflectionProbeIsDynamic(bool is_dynamic);
+
+ BOOL isReflectionProbe() const override;
+ F32 getReflectionProbeAmbiance() const;
+ F32 getReflectionProbeNearClip() const;
+ bool getReflectionProbeIsBox() const;
+ bool getReflectionProbeIsDynamic() const;
+
// Flexible Objects
U32 getVolumeInterfaceID() const;
- virtual BOOL isFlexible() const;
- virtual BOOL isSculpted() const;
- virtual BOOL isMesh() const;
- virtual BOOL isRiggedMesh() const;
- virtual BOOL hasLightTexture() const;
+ virtual BOOL isFlexible() const override;
+ virtual BOOL isSculpted() const override;
+ virtual BOOL isMesh() const override;
+ virtual BOOL isRiggedMesh() const override;
+ virtual BOOL hasLightTexture() const override;
BOOL isVolumeGlobal() const;
@@ -304,12 +321,12 @@ public:
void onSetExtendedMeshFlags(U32 flags);
void setExtendedMeshFlags(U32 flags);
bool canBeAnimatedObject() const;
- bool isAnimatedObject() const;
- virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent);
- virtual void afterReparent();
+ bool isAnimatedObject() const override;
+ virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) override;
+ virtual void afterReparent() override;
//virtual
- void updateRiggingInfo();
+ void updateRiggingInfo() override;
S32 mLastRiggingInfoLOD;
// Functions that deal with media, or media navigation
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8abb49fba8..8837038d02 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -820,7 +820,7 @@ void LLWorld::updateNetStats()
void LLWorld::printPacketsLost()
{
- LL_INFOS() << "Simulators:" << LL_ENDL;
+ LL_INFOS() << "Simulators:" << LL_ENDL;
LL_INFOS() << "----------" << LL_ENDL;
LLCircuitData *cdp = NULL;
@@ -855,6 +855,7 @@ F32 LLWorld::getLandFarClip() const
void LLWorld::setLandFarClip(const F32 far_clip)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
static S32 const rwidth = (S32)REGION_WIDTH_U32;
S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
S32 const n2 = (llceil(far_clip) - 1) / rwidth;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 54e6c6fc6e..ee2dc82505 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -227,6 +227,7 @@ extern S32 gBoxFrame;
//extern BOOL gHideSelectedObjects;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
+extern BOOL gCubeSnapshot;
bool gAvatarBacklight = false;
@@ -280,29 +281,33 @@ static LLStaticHashedString sKern("kern");
static LLStaticHashedString sKernScale("kern_scale");
//----------------------------------------
-std::string gPoolNames[] =
+#if 0
+std::string gPoolNames[LLDrawPool::NUM_POOL_TYPES] =
{
// Correspond to LLDrawpool enum render type
- "NONE",
- "POOL_SIMPLE",
- "POOL_GROUND",
- "POOL_FULLBRIGHT",
- "POOL_BUMP",
- "POOL_MATERIALS",
- "POOL_TERRAIN,"
- "POOL_SKY",
- "POOL_WL_SKY",
- "POOL_TREE",
- "POOL_ALPHA_MASK",
- "POOL_FULLBRIGHT_ALPHA_MASK",
- "POOL_GRASS",
- "POOL_INVISIBLE",
- "POOL_AVATAR",
- "POOL_VOIDWATER",
- "POOL_WATER",
- "POOL_GLOW",
- "POOL_ALPHA"
+ "NONE"
+ , "POOL_SIMPLE"
+ , "POOL_GROUND"
+ , "POOL_FULLBRIGHT"
+ , "POOL_BUMP"
+ , "POOL_MATERIALS"
+ , "POOL_TERRAIN"
+ , "POOL_SKY"
+ , "POOL_WL_SKY"
+ , "POOL_TREE"
+ , "POOL_ALPHA_MASK"
+ , "POOL_FULLBRIGHT_ALPHA_MASK"
+ , "POOL_GRASS"
+ , "POOL_INVISIBLE"
+ , "POOL_AVATAR"
+ , "POOL_CONTROL_AV" // Animesh
+ , "POOL_VOIDWATER"
+ , "POOL_WATER"
+ , "POOL_GLOW"
+ , "POOL_ALPHA"
+ , "POOL_PBR_OPAQUE"
};
+#endif
void drawBox(const LLVector4a& c, const LLVector4a& r);
void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
@@ -350,6 +355,7 @@ bool LLPipeline::sRenderFrameTest = false;
bool LLPipeline::sRenderAttachedLights = true;
bool LLPipeline::sRenderAttachedParticles = true;
bool LLPipeline::sRenderDeferred = false;
+bool LLPipeline::sRenderPBR = false;
S32 LLPipeline::sVisibleLightCount = 0;
bool LLPipeline::sRenderingHUDs;
F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f;
@@ -366,8 +372,12 @@ void validate_framebuffer_object();
// for_impostor -- whether or not these render targets are for an impostor (if true, avoids implicit sRGB conversions)
bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
{
- return target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) && //specular
- target.addColorAttachment(GL_RGB10_A2); //normal+z
+ bool pbr = gSavedSettings.getBOOL("RenderPBR");
+ bool valid = true
+ && target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) // frag-data[1] specular or PBR sRGB Emissive
+ && target.addColorAttachment(GL_RGB10_A2) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight
+ && (pbr ? target.addColorAttachment(GL_RGBA) : true); // frag_data[3] PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl
+ return valid;
}
LLPipeline::LLPipeline() :
@@ -405,9 +415,7 @@ LLPipeline::LLPipeline() :
mWLSkyPool(NULL),
mLightMask(0),
mLightMovingMask(0),
- mLightingDetail(0),
- mScreenWidth(0),
- mScreenHeight(0)
+ mLightingDetail(0)
{
mNoiseMap = 0;
mTrueNoiseMap = 0;
@@ -436,6 +444,8 @@ void LLPipeline::init()
{
refreshCachedSettings();
+ mRT = &mMainRT;
+
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
@@ -462,6 +472,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_BUMP);
getPool(LLDrawPool::POOL_MATERIALS);
getPool(LLDrawPool::POOL_GLOW);
+ getPool(LLDrawPool::POOL_PBR_OPAQUE);
resetFrameStats();
@@ -539,6 +550,7 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("UseOcclusion");
connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders");
connectRefreshCachedSettingsSafe("RenderDeferred");
+ connectRefreshCachedSettingsSafe("RenderPBR");
connectRefreshCachedSettingsSafe("RenderDeferredSunWash");
connectRefreshCachedSettingsSafe("RenderFSAASamples");
connectRefreshCachedSettingsSafe("RenderResolutionDivisor");
@@ -732,8 +744,9 @@ void LLPipeline::requestResizeShadowTexture()
void LLPipeline::resizeShadowTexture()
{
- releaseShadowTargets();
- allocateShadowBuffer(mScreenWidth, mScreenHeight);
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
+ allocateShadowBuffer(mRT->width, mRT->height);
gResizeShadowTexture = FALSE;
}
@@ -744,10 +757,11 @@ void LLPipeline::resizeScreenTexture()
GLuint resX = gViewerWindow->getWorldViewWidthRaw();
GLuint resY = gViewerWindow->getWorldViewHeightRaw();
- if (gResizeScreenTexture || (resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
+ if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight()))
{
releaseScreenBuffers();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
allocateScreenBuffer(resX,resY);
gResizeScreenTexture = FALSE;
}
@@ -767,42 +781,16 @@ void LLPipeline::allocatePhysicsBuffer()
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
- bool save_settings = sRenderDeferred;
- if (save_settings)
- {
- // Set this flag in case we crash while resizing window or allocating space for deferred rendering targets
- gSavedSettings.setBOOL("RenderInitError", TRUE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
eFBOStatus ret = doAllocateScreenBuffer(resX, resY);
- if (save_settings)
- {
- // don't disable shaders on next session
- gSavedSettings.setBOOL("RenderInitError", FALSE);
- gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
- }
-
- if (ret == FBO_FAILURE)
- { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
- //NOTE: if the session closes successfully after this call, deferred rendering will be
- // disabled on future sessions
- if (LLPipeline::sRenderDeferred)
- {
- gSavedSettings.setBOOL("RenderDeferred", FALSE);
- LLPipeline::refreshCachedSettings();
- }
- }
-
return ret == FBO_SUCCESS_FULLRES;
}
LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
// try to allocate screen buffers at requested resolution and samples
// - on failure, shrink number of samples and try again
// - if not multisampled, shrink resolution and try again (favor X resolution over Y)
@@ -856,11 +844,20 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
- refreshCachedSettings();
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (mRT == &mMainRT)
+ { // hacky -- allocate auxillary buffer
+ gCubeSnapshot = TRUE;
+ mRT = &mAuxillaryRT;
+ U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
+ allocateScreenBuffer(res, res, samples);
+ mRT = &mMainRT;
+ gCubeSnapshot = FALSE;
+ }
// remember these dimensions
- mScreenWidth = resX;
- mScreenHeight = resY;
+ mRT->width = resX;
+ mRT->height = resY;
U32 res_mod = RenderResolutionDivisor;
@@ -872,7 +869,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
if (RenderUIBuffer)
{
- if (!mUIScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
+ if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE))
{
return false;
}
@@ -886,10 +883,10 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
const U32 occlusion_divisor = 3;
//allocate deferred rendering color buffers
- if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!mOcclusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
- if (!addDeferredAttachments(mDeferredScreen)) return false;
+ if (!mRT->deferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->deferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->occlusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!addDeferredAttachments(mRT->deferredScreen)) return false;
GLuint screenFormat = GL_RGBA16;
if (gGLManager.mIsAMD)
@@ -902,23 +899,23 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
screenFormat = GL_RGBA16F_ARB;
}
- if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
if (samples > 0)
{
- if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
+ if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
}
else
{
- mFXAABuffer.release();
+ mRT->fxaaBuffer.release();
}
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
- { //only need mDeferredLight for shadows OR ssao OR dof OR fxaa
- if (!mDeferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa
+ if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
}
else
{
- mDeferredLight.release();
+ mRT->deferredLight.release();
}
allocateShadowBuffer(resX, resY);
@@ -931,22 +928,23 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
}
else
{
- mDeferredLight.release();
+ mRT->deferredLight.release();
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
- mFXAABuffer.release();
- mScreen.release();
- mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
- mDeferredDepth.release();
- mOcclusionDepth.release();
+ mRT->fxaaBuffer.release();
+ mRT->screen.release();
+ mRT->deferredScreen.release(); //make sure to release any render targets that share a depth buffer with mRT->deferredScreen first
+ mRT->deferredDepth.release();
+ mRT->occlusionDepth.release();
- if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
+ if (!mRT->screen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;
}
if (LLPipeline::sRenderDeferred)
{ //share depth buffer between deferred targets
- mDeferredScreen.shareDepthBuffer(mScreen);
+ mRT->deferredScreen.shareDepthBuffer(mRT->screen);
}
gGL.getTexUnit(0)->disable();
@@ -961,68 +959,67 @@ inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0
bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
{
- refreshCachedSettings();
-
- if (LLPipeline::sRenderDeferred)
- {
- S32 shadow_detail = RenderShadowDetail;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ if (LLPipeline::sRenderDeferred)
+ {
+ S32 shadow_detail = RenderShadowDetail;
- const U32 occlusion_divisor = 3;
+ const U32 occlusion_divisor = 3;
- F32 scale = llmax(0.f,RenderShadowResolutionScale);
- U32 sun_shadow_map_width = BlurHappySize(resX, scale);
- U32 sun_shadow_map_height = BlurHappySize(resY, scale);
+ F32 scale = llmax(0.f, RenderShadowResolutionScale);
+ U32 sun_shadow_map_width = BlurHappySize(resX, scale);
+ U32 sun_shadow_map_height = BlurHappySize(resY, scale);
- if (shadow_detail > 0)
- { //allocate 4 sun shadow maps
- for (U32 i = 0; i < 4; i++)
- {
- if (!mShadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (shadow_detail > 0)
+ { //allocate 4 sun shadow maps
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- if (!mShadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+ if (!mRT->shadowOcclusion[i].allocate(sun_shadow_map_width / occlusion_divisor, sun_shadow_map_height / occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
{
return false;
}
- }
- }
- else
- {
- for (U32 i = 0; i < 4; i++)
- {
- releaseShadowTarget(i);
- }
- }
-
- U32 width = (U32) (resX*scale);
- U32 height = width;
+ }
+ }
+ else
+ {
+ for (U32 i = 0; i < 4; i++)
+ {
+ releaseSunShadowTarget(i);
+ }
+ }
- if (shadow_detail > 1)
- { //allocate two spot shadow maps
- U32 spot_shadow_map_width = width;
- U32 spot_shadow_map_height = height;
- for (U32 i = 4; i < 6; i++)
- {
- if (!mShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
- {
- return false;
- }
- if (!mShadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
- {
- return false;
- }
- }
+ if (!gCubeSnapshot) // hack to not allocate spot shadow maps during ReflectionMapManager init
+ {
+ U32 width = (U32)(resX * scale);
+ U32 height = width;
+
+ if (shadow_detail > 1)
+ { //allocate two spot shadow maps
+ U32 spot_shadow_map_width = width;
+ U32 spot_shadow_map_height = height;
+ for (U32 i = 0; i < 2; i++)
+ {
+ if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ if (!mSpotShadowOcclusion[i].allocate(spot_shadow_map_width / occlusion_divisor, height / occlusion_divisor, 0, TRUE, FALSE))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ releaseSpotShadowTargets();
+ }
}
- else
- {
- for (U32 i = 4; i < 6; i++)
- {
- releaseShadowTarget(i);
- }
- }
- }
+ }
return true;
}
@@ -1048,11 +1045,13 @@ void LLPipeline::updateRenderDeferred()
LLPipeline::sRenderBump &&
WindLightUseAtmosShaders &&
(bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
+ sRenderPBR = sRenderDeferred && gSavedSettings.getBOOL("RenderPBR");
}
// static
void LLPipeline::refreshCachedSettings()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
@@ -1194,36 +1193,50 @@ void LLPipeline::releaseLUTBuffers()
void LLPipeline::releaseShadowBuffers()
{
- releaseShadowTargets();
+ releaseSunShadowTargets();
+ releaseSpotShadowTargets();
}
void LLPipeline::releaseScreenBuffers()
{
- mUIScreen.release();
- mScreen.release();
- mFXAABuffer.release();
+ mRT->uiScreen.release();
+ mRT->screen.release();
+ mRT->fxaaBuffer.release();
mPhysicsDisplay.release();
- mDeferredScreen.release();
- mDeferredDepth.release();
- mDeferredLight.release();
- mOcclusionDepth.release();
+ mRT->deferredScreen.release();
+ mRT->deferredDepth.release();
+ mRT->deferredLight.release();
+ mRT->occlusionDepth.release();
}
-void LLPipeline::releaseShadowTarget(U32 index)
+void LLPipeline::releaseSunShadowTarget(U32 index)
{
- mShadow[index].release();
- mShadowOcclusion[index].release();
+ llassert(index < 4);
+ mRT->shadow[index].release();
+ mRT->shadowOcclusion[index].release();
}
-void LLPipeline::releaseShadowTargets()
+void LLPipeline::releaseSunShadowTargets()
{
- for (U32 i = 0; i < 6; i++)
+ for (U32 i = 0; i < 4; i++)
{
- releaseShadowTarget(i);
+ releaseSunShadowTarget(i);
}
}
+void LLPipeline::releaseSpotShadowTargets()
+{
+ if (!gCubeSnapshot) // hack to avoid freeing spot shadows during ReflectionMapManager init
+ {
+ for (U32 i = 0; i < 2; i++)
+ {
+ mSpotShadow[i].release();
+ mSpotShadowOcclusion[i].release();
+ }
+ }
+}
+
void LLPipeline::createGLBuffers()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
@@ -1256,8 +1269,8 @@ void LLPipeline::createGLBuffers()
}
allocateScreenBuffer(resX, resY);
- mScreenWidth = 0;
- mScreenHeight = 0;
+ mRT->width = 0;
+ mRT->height = 0;
if (sRenderDeferred)
{
@@ -1597,6 +1610,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
poolp = mWLSkyPool;
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ poolp = mPBROpaquePool;
+ break;
+
default:
llassert(0);
LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL;
@@ -1638,6 +1655,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
}
LLMaterial* mat = te->getMaterialParams().get();
+ LLGLTFMaterial* gltf_mat = te->getGLTFMaterial();
bool color_alpha = te->getColor().mV[3] < 0.999f;
bool alpha = color_alpha;
@@ -1671,6 +1689,10 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
{
return LLDrawPool::POOL_BUMP;
}
+ else if (gltf_mat && !alpha)
+ {
+ return LLDrawPool::POOL_PBR_OPAQUE;
+ }
else if (mat && !alpha)
{
return LLDrawPool::POOL_MATERIALS;
@@ -2028,6 +2050,7 @@ void LLPipeline::updateMove()
//static
F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
{
+ llassert(!gCubeSnapshot); // shouldn't be doing ANY of this during cube snap shots
LLVector3 lookAt = center - camera.getOrigin();
F32 dist = lookAt.length();
@@ -2353,11 +2376,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
{
if (LLPipeline::sRenderDeferred && can_use_occlusion)
{
- mOcclusionDepth.bindTarget();
+ mRT->occlusionDepth.bindTarget();
}
else
{
- mScreen.bindTarget();
+ mRT->screen.bindTarget();
}
}
@@ -2479,11 +2502,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* pla
{
if (LLPipeline::sRenderDeferred && can_use_occlusion)
{
- mOcclusionDepth.flush();
+ mRT->occlusionDepth.flush();
}
else
{
- mScreen.flush();
+ mRT->screen.flush();
}
}
}
@@ -2497,7 +2520,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
group->setVisible();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
group->updateDistance(camera);
}
@@ -2603,6 +2626,8 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d
void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderTarget& dest, LLRenderTarget* scratch_space)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
+ llassert(!gCubeSnapshot);
downsampleDepthBuffer(source, dest, scratch_space);
dest.bindTarget();
doOcclusion(camera);
@@ -2612,6 +2637,7 @@ void LLPipeline::doOcclusion(LLCamera& camera, LLRenderTarget& source, LLRenderT
void LLPipeline::doOcclusion(LLCamera& camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("doOcclusion");
if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested &&
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
{
@@ -2845,7 +2871,7 @@ void LLPipeline::rebuildPriorityGroups()
void LLPipeline::rebuildGroups()
{
- if (mGroupQ2.empty())
+ if (mGroupQ2.empty() || gCubeSnapshot)
{
return;
}
@@ -2895,6 +2921,10 @@ void LLPipeline::updateGeom(F32 max_dtime)
LLPointer<LLDrawable> drawablep;
LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE);
+ if (gCubeSnapshot)
+ {
+ return;
+ }
assertInitialized();
@@ -3134,6 +3164,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
}
+ mReflectionMapManager.shift(offseta);
+
LLHUDText::shiftAll(offset);
LLHUDNameTag::shiftAll(offset);
@@ -3314,7 +3346,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
LLSpatialGroup* last_group = NULL;
BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();
@@ -3396,7 +3428,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
stateSort(drawablep, camera);
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{ //avoid redundant stateSort calls
group->mLastUpdateDistance = group->mDistance;
}
@@ -3465,7 +3497,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
//if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here
{
@@ -3743,21 +3775,26 @@ void LLPipeline::postSort(LLCamera& camera)
assertInitialized();
LL_PUSH_CALLSTACKS();
- //rebuild drawable geometry
- for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
- {
- LLSpatialGroup* group = *i;
- if (!sUseOcclusion ||
- !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- group->rebuildGeom();
- }
- }
- LL_PUSH_CALLSTACKS();
- //rebuild groups
- sCull->assertDrawMapsEmpty();
- rebuildPriorityGroups();
+ if (!gCubeSnapshot)
+ {
+ //rebuild drawable geometry
+ for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!sUseOcclusion ||
+ !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ group->rebuildGeom();
+ }
+ }
+ LL_PUSH_CALLSTACKS();
+ //rebuild groups
+ sCull->assertDrawMapsEmpty();
+
+ rebuildPriorityGroups();
+ }
+
LL_PUSH_CALLSTACKS();
@@ -3773,7 +3810,7 @@ void LLPipeline::postSort(LLCamera& camera)
continue;
}
- if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY))
+ if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY) && !gCubeSnapshot)
{ //no way this group is going to be drawable without a rebuild
group->rebuildGeom();
}
@@ -3791,7 +3828,7 @@ void LLPipeline::postSort(LLCamera& camera)
LLDrawInfo* info = *k;
sCull->pushDrawInfo(j->first, info);
- if (!sShadowRender && !sReflectionRender)
+ if (!sShadowRender && !sReflectionRender && !gCubeSnapshot)
{
touchTextures(info);
addTrianglesDrawn(info->mCount, info->mDrawMode);
@@ -3806,7 +3843,7 @@ void LLPipeline::postSort(LLCamera& camera)
if (alpha != group->mDrawMap.end())
{ //store alpha groups for sorting
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot)
{
if (bridge)
{
@@ -4262,7 +4299,7 @@ U32 LLPipeline::sCurRenderPoolType = 0 ;
void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
-
+ LL_PROFILE_GPU_ZONE("renderGeom");
assertInitialized();
F32 saved_modelview[16];
@@ -4437,7 +4474,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
gGL.loadMatrix(gGLModelView);
if (occlude)
- {
+ { // catch uncommon condition where pools at drawpool grass and later are disabled
occlude = false;
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
@@ -4512,14 +4549,10 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
void LLPipeline::renderGeomDeferred(LLCamera& camera)
{
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
-
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
+ LL_PROFILE_GPU_ZONE("renderGeomDeferred");
+
{
- // SL-15709 -- NOTE: Tracy only allows one ZoneScoped per function.
- // Solutions are:
- // 1. Use a new scope
- // 2. Use named zones
- // 3. Use transient zones
LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); //LL_RECORD_BLOCK_TIME(FTM_DEFERRED_POOLS);
LLGLEnable cull(GL_CULL_FACE);
@@ -4540,6 +4573,12 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
LLGLState::checkStates();
LLGLState::checkTextureChannels();
+ if (LLViewerShaderMgr::instance()->mShaderLevel[LLViewerShaderMgr::SHADER_DEFERRED] > 1)
+ {
+ //update reflection probe uniform
+ mReflectionMapManager.updateUniforms();
+ }
+
U32 cur_type = 0;
gGL.setColorMask(true, true);
@@ -4611,6 +4650,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_POST_DEFERRED_POOLS);
+ LL_PROFILE_GPU_ZONE("renderGeomPostDeferred");
+
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -4633,11 +4674,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
{
+ llassert(!gCubeSnapshot); // never do occlusion culling on cube snapshots
occlude = false;
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
LLGLSLShader::bindNoShader();
- doOcclusion(camera, mScreen, mOcclusionDepth, &mDeferredDepth);
+ doOcclusion(camera, mRT->screen, mRT->occlusionDepth, &mRT->deferredDepth);
gGL.setColorMask(true, false);
}
@@ -4706,6 +4748,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
void LLPipeline::renderGeomShadow(LLCamera& camera)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderGeomShadow");
U32 cur_type = 0;
LLGLEnable cull(GL_CULL_FACE);
@@ -5160,7 +5203,6 @@ void LLPipeline::renderDebug()
glPointSize(1.f);
}
-
// Debug stuff.
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
@@ -5214,6 +5256,12 @@ void LLPipeline::renderDebug()
visible_selected_groups.clear();
+ //draw reflection probes and links between them
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_REFLECTION_PROBES) && !hud_only)
+ {
+ mReflectionMapManager.renderDebug();
+ }
+
gUIProgram.bind();
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only)
@@ -5702,6 +5750,18 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ if( mPBROpaquePool )
+ {
+ llassert(0);
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Opaque Pool" << LL_ENDL;
+ }
+ else
+ {
+ mPBROpaquePool = new_poolp;
+ }
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL;
@@ -5818,6 +5878,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mGroundPool = NULL;
break;
+ case LLDrawPool::POOL_PBR_OPAQUE:
+ llassert( poolp == mPBROpaquePool );
+ mPBROpaquePool = NULL;
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
@@ -5934,6 +5999,7 @@ void LLPipeline::setupAvatarLights(bool for_edit)
static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
F32 inten = light->getLightIntensity();
if (inten < .001f)
{
@@ -5957,9 +6023,10 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_
void LLPipeline::calcNearbyLights(LLCamera& camera)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
- if (LLPipeline::sReflectionRender)
+ if (LLPipeline::sReflectionRender || gCubeSnapshot)
{
return;
}
@@ -6142,6 +6209,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
void LLPipeline::setupHWLights(LLDrawPool* pool)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
assertInitialized();
LLEnvironment& environment = LLEnvironment::instance();
@@ -6703,15 +6771,6 @@ void LLPipeline::toggleRenderType(U32 type)
//static
void LLPipeline::toggleRenderTypeControl(U32 type)
{
- U32 bit = (1<<type);
- if (gPipeline.hasRenderType(type))
- {
- LL_INFOS() << "Toggling render type mask " << std::hex << bit << " off" << std::dec << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "Toggling render type mask " << std::hex << bit << " on" << std::dec << LL_ENDL;
- }
gPipeline.toggleRenderType(type);
}
@@ -6957,7 +7016,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, face_hit, &position, NULL, NULL, NULL);
if (hit)
{
drawable = hit;
@@ -6985,6 +7044,7 @@ LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start,
LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit,
LLVector4a* intersection, // return the intersection point
LLVector2* tex_coord, // return the texture coordinates of the intersection point
@@ -7018,7 +7078,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(j);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7075,7 +7135,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR);
if (part && hasRenderType(part->mDrawableType))
{
- LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, face_hit, &position, tex_coord, normal, tangent);
if (hit)
{
LLVector4a delta;
@@ -7163,7 +7223,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, c
LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD);
if (part)
{
- LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, face_hit, intersection, tex_coord, normal, tangent);
+ LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, face_hit, intersection, tex_coord, normal, tangent);
if (hit)
{
drawable = hit;
@@ -7464,9 +7524,11 @@ void LLPipeline::renderFinalize()
}
LLVector2 tc1(0, 0);
- LLVector2 tc2((F32) mScreen.getWidth() * 2, (F32) mScreen.getHeight() * 2);
+ LLVector2 tc2((F32) mRT->screen.getWidth() * 2, (F32) mRT->screen.getHeight() * 2);
LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+ LL_PROFILE_GPU_ZONE("renderFinalize");
+
gGL.color4f(1, 1, 1, 1);
LLGLDepthTest depth(GL_FALSE);
LLGLDisable blend(GL_BLEND);
@@ -7488,6 +7550,7 @@ void LLPipeline::renderFinalize()
if (sRenderGlow)
{
+ LL_PROFILE_GPU_ZONE("glow");
mGlow[2].bindTarget();
mGlow[2].clear();
@@ -7512,7 +7575,7 @@ void LLPipeline::renderFinalize()
gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
+ mRT->screen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
gGL.color4f(1, 1, 1, 1);
gPipeline.enableLightsFullbright();
@@ -7528,7 +7591,7 @@ void LLPipeline::renderFinalize()
gGL.end();
- gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+ gGL.getTexUnit(0)->unbind(mRT->screen.getUsage());
mGlow[2].flush();
@@ -7606,7 +7669,7 @@ void LLPipeline::renderFinalize()
gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- tc2.setVec((F32) mScreen.getWidth(), (F32) mScreen.getHeight());
+ tc2.setVec((F32) mRT->screen.getWidth(), (F32) mRT->screen.getHeight());
gGL.flush();
@@ -7614,17 +7677,18 @@ void LLPipeline::renderFinalize()
if (LLPipeline::sRenderDeferred)
{
-
bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
(RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
- RenderDepthOfField;
+ RenderDepthOfField &&
+ !gCubeSnapshot;
- bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+ bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete();
gViewerWindow->setup3DViewport();
if (dof_enabled)
{
+ LL_PROFILE_GPU_ZONE("dof");
LLGLSLShader *shader = &gDeferredPostProgram;
LLGLDisable blend(GL_BLEND);
@@ -7660,7 +7724,7 @@ void LLPipeline::renderFinalize()
LLVector4a result;
result.clear();
- gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result);
focus_point.set(result.getF32ptr());
}
@@ -7709,7 +7773,7 @@ void LLPipeline::renderFinalize()
const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
- // F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+ // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight();
F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
@@ -7729,15 +7793,15 @@ void LLPipeline::renderFinalize()
F32 magnification = focal_length / (subject_distance - focal_length);
{ // build diffuse+bloom+CoF
- mDeferredLight.bindTarget();
+ mRT->deferredLight.bindTarget();
shader = &gDeferredCoFProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
@@ -7760,23 +7824,23 @@ void LLPipeline::renderFinalize()
gGL.end();
unbindDeferredShader(*shader);
- mDeferredLight.flush();
+ mRT->deferredLight.flush();
}
- U32 dof_width = (U32)(mScreen.getWidth() * CameraDoFResScale);
- U32 dof_height = (U32)(mScreen.getHeight() * CameraDoFResScale);
+ U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale);
+ U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale);
{ // perform DoF sampling at half-res (preserve alpha channel)
- mScreen.bindTarget();
+ mRT->screen.bindTarget();
glViewport(0, 0, dof_width, dof_height);
gGL.setColorMask(true, false);
shader = &gDeferredPostProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
if (channel > -1)
{
- mDeferredLight.bindTexture(0, channel);
+ mRT->deferredLight.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
@@ -7795,15 +7859,15 @@ void LLPipeline::renderFinalize()
gGL.end();
unbindDeferredShader(*shader);
- mScreen.flush();
+ mRT->screen.flush();
gGL.setColorMask(true, true);
}
{ // combine result based on alpha
if (multisample)
{
- mDeferredLight.bindTarget();
- glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ mRT->deferredLight.bindTarget();
+ glViewport(0, 0, mRT->deferredScreen.getWidth(), mRT->deferredScreen.getHeight());
}
else
{
@@ -7817,10 +7881,10 @@ void LLPipeline::renderFinalize()
shader = &gDeferredDoFCombineProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
@@ -7844,24 +7908,25 @@ void LLPipeline::renderFinalize()
if (multisample)
{
- mDeferredLight.flush();
+ mRT->deferredLight.flush();
}
}
}
else
{
+ LL_PROFILE_GPU_ZONE("no dof");
if (multisample)
{
- mDeferredLight.bindTarget();
+ mRT->deferredLight.bindTarget();
}
LLGLSLShader *shader = &gDeferredPostNoDoFProgram;
bindDeferredShader(*shader);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->screen.getUsage());
if (channel > -1)
{
- mScreen.bindTexture(0, channel);
+ mRT->screen.bindTexture(0, channel);
}
gGL.begin(LLRender::TRIANGLE_STRIP);
@@ -7880,17 +7945,18 @@ void LLPipeline::renderFinalize()
if (multisample)
{
- mDeferredLight.flush();
+ mRT->deferredLight.flush();
}
}
if (multisample)
{
+ LL_PROFILE_GPU_ZONE("aa");
// bake out texture2D with RGBL for FXAA shader
- mFXAABuffer.bindTarget();
+ mRT->fxaaBuffer.bindTarget();
- S32 width = mScreen.getWidth();
- S32 height = mScreen.getHeight();
+ S32 width = mRT->screen.getWidth();
+ S32 height = mRT->screen.getHeight();
glViewport(0, 0, width, height);
LLGLSLShader *shader = &gGlowCombineFXAAProgram;
@@ -7898,10 +7964,10 @@ void LLPipeline::renderFinalize()
shader->bind();
shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
- S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
if (channel > -1)
{
- mDeferredLight.bindTexture(0, channel);
+ mRT->deferredLight.bindTexture(0, channel);
}
gGL.begin(LLRender::TRIANGLE_STRIP);
@@ -7912,18 +7978,18 @@ void LLPipeline::renderFinalize()
gGL.flush();
- shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+ shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mRT->deferredLight.getUsage());
shader->unbind();
- mFXAABuffer.flush();
+ mRT->fxaaBuffer.flush();
shader = &gFXAAProgram;
shader->bind();
- channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+ channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage());
if (channel > -1)
{
- mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+ mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
}
gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
@@ -7932,8 +7998,8 @@ void LLPipeline::renderFinalize()
gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- F32 scale_x = (F32) width / mFXAABuffer.getWidth();
- F32 scale_y = (F32) height / mFXAABuffer.getHeight();
+ F32 scale_x = (F32) width / mRT->fxaaBuffer.getWidth();
+ F32 scale_y = (F32) height / mRT->fxaaBuffer.getHeight();
shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
@@ -7984,7 +8050,7 @@ void LLPipeline::renderFinalize()
gGlowCombineProgram.bind();
gGL.getTexUnit(0)->bind(&mGlow[1]);
- gGL.getTexUnit(1)->bind(&mScreen);
+ gGL.getTexUnit(1)->bind(&mRT->screen);
LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
@@ -8027,10 +8093,10 @@ void LLPipeline::renderFinalize()
gSplatTextureRectProgram.unbind();
}
- if (LLRenderTarget::sUseFBO)
- { // copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0,
- mScreen.getWidth(), mScreen.getHeight(),
+ if (LLRenderTarget::sUseFBO && !gCubeSnapshot)
+ { // copy depth buffer from mRT->screen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mRT->screen, 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), 0, 0,
+ mRT->screen.getWidth(), mRT->screen.getHeight(),
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
}
@@ -8048,31 +8114,39 @@ void LLPipeline::renderFinalize()
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
-
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LL_PROFILE_GPU_ZONE("bindDeferredShader");
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
shader.bind();
S32 channel = 0;
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT); // frag_data[0]
}
+ // NOTE: PBR sRGB Emissive -- See: C++: addDeferredAttachments(), GLSL: pbropaqueF.glsl
channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT); // frag_data[1]
}
channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
if (channel > -1)
{
- deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT);
+ deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT); // frag_data[2]
}
+ // NOTE: PBR linear packed Occlusion, Roughness, Metal -- See: C++: addDeferredAttachments(), GLSL: pbropaqueF.glsl
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());
+ if (channel > -1)
+ {
+ deferred_target->bindTexture(3, channel, LLTexUnit::TFO_POINT); // frag_data[3]
+ }
+
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
if (channel > -1)
{
@@ -8133,7 +8207,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
for (U32 i = 0; i < 4; i++)
{
- LLRenderTarget* shadow_target = getShadowTarget(i);
+ LLRenderTarget* shadow_target = getSunShadowTarget(i);
if (shadow_target)
{
channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
@@ -8141,7 +8215,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
if (channel > -1)
{
stop_glerror();
- gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
+ gGL.getTexUnit(channel)->bind(getSunShadowTarget(i), TRUE);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
@@ -8153,27 +8227,27 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- for (U32 i = 4; i < 6; i++)
- {
- channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i);
- stop_glerror();
- if (channel > -1)
- {
- stop_glerror();
- LLRenderTarget* shadow_target = getShadowTarget(i);
- if (shadow_target)
- {
- gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
- stop_glerror();
- }
- }
- }
+ for (U32 i = 4; i < 6; i++)
+ {
+ channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0 + i);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ LLRenderTarget* shadow_target = getSpotShadowTarget(i-4);
+ if (shadow_target)
+ {
+ gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+ }
stop_glerror();
@@ -8200,16 +8274,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
{
cube_map->enable(channel);
cube_map->bind();
- 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);
}
+
+ 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);
}
+ bindReflectionProbes(shader);
+
if (gAtmosphere)
{
// bind precomputed textures necessary for calculating sun and sky luminance
@@ -8238,7 +8315,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
}
}
- shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ /*if (gCubeSnapshot)
+ { // we only really care about the first two values, but the shader needs increasing separation between clip planes
+ shader.uniform4f(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1.f, 64.f, 128.f, 256.f);
+ }
+ else*/
+ {
+ shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
+ }
shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
@@ -8273,8 +8357,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
- shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
- shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight());
+ shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight());
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
@@ -8310,14 +8394,15 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f)
void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("renderDeferredLighting");
if (!sCull)
{
return;
}
- LLRenderTarget *deferred_target = &mDeferredScreen;
- LLRenderTarget *deferred_depth_target = &mDeferredDepth;
- LLRenderTarget *deferred_light_target = &mDeferredLight;
+ LLRenderTarget *deferred_target = &mRT->deferredScreen;
+ LLRenderTarget *deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget *deferred_light_target = &mRT->deferredLight;
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred"); //LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
@@ -8384,6 +8469,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
if (RenderDeferredSSAO || RenderShadowDetail > 0)
{
+ LL_PROFILE_GPU_ZONE("sun program");
deferred_light_target->bindTarget();
{ // paint shadow/SSAO light map (direct lighting lightmap)
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - sun shadow");
@@ -8431,66 +8517,79 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
}
if (RenderDeferredSSAO)
- { // soften direct lighting lightmap
- LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow");
- // blur lightmap
- screen_target->bindTarget();
- glClearColor(1, 1, 1, 1);
- screen_target->clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0, 0, 0, 0);
-
- bindDeferredShader(gDeferredBlurLightProgram);
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- LLVector3 go = RenderShadowGaussian;
- const U32 kern_length = 4;
- F32 blur_size = RenderShadowBlurSize;
- F32 dist_factor = RenderShadowBlurDistFactor;
-
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = 0.f;
-
- LLVector3 gauss[32]; // xweight, yweight, offset
-
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
+ {
+ /*if (gCubeSnapshot)
+ { // SSAO and shadows disabled in reflection maps
+ deferred_light_target->bindTarget();
+ glClearColor(1, 1, 1, 1);
+ deferred_light_target->clear();
+ glClearColor(0, 0, 0, 0);
+ deferred_light_target->flush();
}
+ else*/
+ {
+ // soften direct lighting lightmap
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - soften shadow");
+ LL_PROFILE_GPU_ZONE("soften shadow");
+ // blur lightmap
+ screen_target->bindTarget();
+ glClearColor(1, 1, 1, 1);
+ screen_target->clear(GL_COLOR_BUFFER_BIT);
+ glClearColor(0, 0, 0, 0);
- gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
- gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
- gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
+ bindDeferredShader(gDeferredBlurLightProgram);
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ LLVector3 go = RenderShadowGaussian;
+ const U32 kern_length = 4;
+ F32 blur_size = RenderShadowBlurSize;
+ F32 dist_factor = RenderShadowBlurDistFactor;
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
- }
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
- screen_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ LLVector3 gauss[32]; // xweight, yweight, offset
- bindDeferredShader(gDeferredBlurLightProgram, screen_target);
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
- mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
- deferred_light_target->bindTarget();
+ gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
+ gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
- gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
+ screen_target->flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
- stop_glerror();
+ bindDeferredShader(gDeferredBlurLightProgram, screen_target);
+
+ mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+ deferred_light_target->bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+ stop_glerror();
+ }
+ deferred_light_target->flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
}
- deferred_light_target->flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
}
stop_glerror();
@@ -8511,12 +8610,19 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - atmospherics");
+ LL_PROFILE_GPU_ZONE("atmospherics");
bindDeferredShader(soften_shader);
LLEnvironment &environment = LLEnvironment::instance();
soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
+ if(LLPipeline::sRenderPBR)
+ {
+ LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis();
+ soften_shader.uniform3fv(LLShaderMgr::DEFERRED_VIEW_DIR, 1, cameraAtAxis.mV);
+ }
+
{
LLGLDepthTest depth(GL_FALSE);
LLGLDisable blend(GL_BLEND);
@@ -8557,7 +8663,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gPipeline.popRenderTypeMask();
}
- bool render_local = RenderLocalLights;
+ bool render_local = RenderLocalLights; // && !gCubeSnapshot;
if (render_local)
{
@@ -8566,9 +8672,12 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
LLDrawable::drawable_list_t spot_lights;
LLDrawable::drawable_list_t fullscreen_spot_lights;
- for (U32 i = 0; i < 2; i++)
+ if (!gCubeSnapshot)
{
- mTargetShadowSpotLight[i] = NULL;
+ for (U32 i = 0; i < 2; i++)
+ {
+ mTargetShadowSpotLight[i] = NULL;
+ }
}
std::list<LLVector4> light_colors;
@@ -8577,6 +8686,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - local lights");
+ LL_PROFILE_GPU_ZONE("local lights");
bindDeferredShader(gDeferredLightProgram);
if (mCubeVB.isNull())
@@ -8683,6 +8793,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
if (!spot_lights.empty())
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - projectors");
+ LL_PROFILE_GPU_ZONE("projectors");
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
bindDeferredShader(gDeferredSpotLightProgram);
@@ -8729,7 +8840,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - fullscreen lights");
LLGLDepthTest depth(GL_FALSE);
-
+ LL_PROFILE_GPU_ZONE("fullscreen lights");
// full screen blit
gGL.pushMatrix();
gGL.loadIdentity();
@@ -8825,6 +8936,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
gGL.loadIdentity();
{
+ LL_PROFILE_GPU_ZONE("gamma correct");
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
LLVector2 tc1(0, 0);
@@ -8904,6 +9016,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
popRenderTypeMask();
}
+ if (!gCubeSnapshot)
{
// render highlights, etc.
renderHighlights();
@@ -9015,6 +9128,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
+ //if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
//determine if this is a good light for casting shadows
@@ -9066,14 +9180,15 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
{
- LLRenderTarget* deferred_target = &mDeferredScreen;
- LLRenderTarget* deferred_depth_target = &mDeferredDepth;
- LLRenderTarget* deferred_light_target = &mDeferredLight;
+ LLRenderTarget* deferred_target = &mRT->deferredScreen;
+ LLRenderTarget* deferred_depth_target = &mRT->deferredDepth;
+ LLRenderTarget* deferred_light_target = &mRT->deferredLight;
stop_glerror();
shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
+ shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage());
shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
@@ -9107,11 +9222,59 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
cube_map->disable();
}
}
+
+ 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);
+ bool bound = false;
+ if (channel > -1 && mReflectionMapManager.mTexture.notNull())
+ {
+ 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;
+
+ 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();
+ if (channel == 0)
+ {
+ gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE);
+ }
+ }
+}
+
+
inline float sgn(float a)
{
if (a > 0.0F) return (1.0F);
@@ -9122,8 +9285,9 @@ inline float sgn(float a)
void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+ LL_PROFILE_GPU_ZONE("generateWaterReflection");
- if (!assertInitialized())
+ if (!assertInitialized() || gCubeSnapshot)
{
return;
}
@@ -9533,7 +9697,7 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbri
void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER);
-
+ LL_PROFILE_GPU_ZONE("renderShadow");
//disable occlusion culling for shadow passes (save setting to restore later)
S32 occlude = LLPipeline::sUseOcclusion;
if (!use_occlusion)
@@ -9556,6 +9720,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLRenderPass::PASS_NORMMAP_EMISSIVE,
LLRenderPass::PASS_NORMSPEC,
LLRenderPass::PASS_NORMSPEC_EMISSIVE,
+ LLRenderPass::PASS_PBR_OPAQUE, // NOTE: Assumes PASS_PBR_OPAQUE_RIGGED is consecutive
+ //LLRenderPass::PASS_PBR_OPAQUE_RIGGED,
};
LLGLEnable cull(GL_CULL_FACE);
@@ -9568,7 +9734,9 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gDeferredShadowCubeProgram.bind();
}
- LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_target = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadowOcclusion[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
occlusion_target.bindTarget();
updateCull(shadow_cam, result);
@@ -9620,7 +9788,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
}
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow simple"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE);
-
+ LL_PROFILE_GPU_ZONE("shadow simple");
gGL.getTexUnit(0)->disable();
for (U32 i = 0; i < sizeof(types) / sizeof(U32); ++i)
{
@@ -9653,7 +9821,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA);
-
+ LL_PROFILE_GPU_ZONE("shadow alpha");
for (int i = 0; i < 2; ++i)
{
bool rigged = i == 1;
@@ -9712,9 +9880,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
gGLLastMatrix = NULL;
gGL.loadMatrix(gGLModelView);
- LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID - 1];
+ LLRenderTarget& occlusion_source = LLViewerCamera::sCurCameraID >= LLViewerCamera::CAMERA_SPOT_SHADOW0 ?
+ mSpotShadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SPOT_SHADOW0] :
+ mRT->shadow[LLViewerCamera::sCurCameraID - LLViewerCamera::CAMERA_SUN_SHADOW0];
- doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ if (occlude > 1)
+ {
+ doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ }
if (use_shader)
{
@@ -9935,7 +10108,8 @@ void LLPipeline::generateHighlight(LLCamera& camera)
{
mHighlightSet.insert(HighlightItem(mHighlightObject));
}
-
+ llassert(!gCubeSnapshot);
+
if (!mHighlightSet.empty())
{
F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime;
@@ -9983,9 +10157,16 @@ void LLPipeline::generateHighlight(LLCamera& camera)
}
}
-LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
+LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i)
+{
+ llassert(i < 4);
+ return &mRT->shadow[i];
+}
+
+LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i)
{
- return &mShadow[i];
+ llassert(i < 2);
+ return &mSpotShadow[i];
}
static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
@@ -9999,6 +10180,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW);
+ LL_PROFILE_GPU_ZONE("generateSunShadow");
bool skip_avatar_update = false;
if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
@@ -10081,6 +10263,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_PBR_OPAQUE,
+ //LLRenderPass::PASS_PBR_OPAQUE_RIGGED,
END_RENDER_TYPES);
gGL.setColorMask(false, false);
@@ -10110,6 +10294,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
clip = RenderShadowOrthoClipPlanes;
mSunOrthoClipPlanes = LLVector4(clip, clip.mV[2]*clip.mV[2]/clip.mV[1]);
+ //if (gCubeSnapshot)
+ { //always do a single 64m shadow in reflection maps
+ mSunClipPlanes.set(64.f, 128.f, 256.f);
+ mSunOrthoClipPlanes.set(64.f, 128.f, 256.f);
+ }
+
//currently used for amount to extrude frusta corners for constructing shadow frusta
//LLVector3 n = RenderShadowNearDist;
//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
@@ -10226,28 +10416,41 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
// convenience array of 4 near clip plane distances
F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
-
if (mSunDiffuse == LLColor4::black)
- { //sun diffuse is totally black, shadows don't matter
+ { //sun diffuse is totally shadows don't matter
LLGLDepthTest depth(GL_TRUE);
for (S32 j = 0; j < 4; j++)
{
- mShadow[j].bindTarget();
- mShadow[j].clear();
- mShadow[j].flush();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
}
}
else
{
- for (S32 j = 0; j < 4; j++)
+ /*if (gCubeSnapshot)
+ {
+ // do one shadow split for cube snapshots, clear the rest
+ mSunClipPlanes.set(64.f, 64.f, 64.f);
+ dist[1] = dist[2] = dist[3] = dist[4] = 64.f;
+ for (S32 j = 1; j < 4; j++)
+ {
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].clear();
+ mRT->shadow[j].flush();
+ }
+ }*/
+
+ //for (S32 j = 0; j < (gCubeSnapshot ? 1 : 4); j++)
+ for (S32 j = 0; j < 4; j++)
{
if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA))
{
mShadowFrustPoints[j].clear();
}
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j);
//restore render matrices
set_current_modelview(saved_view);
@@ -10301,12 +10504,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
mShadowCamera[j+4] = shadow_cam;
}
- mShadow[j].bindTarget();
+ mRT->shadow[j].bindTarget();
{
LLGLDepthTest depth(GL_TRUE);
- mShadow[j].clear();
+ mRT->shadow[j].clear();
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
mShadowError.mV[j] = 0.f;
mShadowFOV.mV[j] = 0.f;
@@ -10593,18 +10796,18 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
stop_glerror();
- mShadow[j].bindTarget();
- mShadow[j].getViewport(gGLViewport);
- mShadow[j].clear();
+ mRT->shadow[j].bindTarget();
+ mRT->shadow[j].getViewport(gGLViewport);
+ mRT->shadow[j].clear();
- U32 target_width = mShadow[j].getWidth();
+ U32 target_width = mRT->shadow[j].getWidth();
{
static LLCullResult result[4];
renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, FALSE, target_width);
}
- mShadow[j].flush();
+ mRT->shadow[j].flush();
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
@@ -10619,142 +10822,150 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
if (gen_shadow)
{
- LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
- F32 fade_amt = gFrameIntervalSeconds.value()
- * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
+ LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat();
+ F32 fade_amt = gFrameIntervalSeconds.value()
+ * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
- //update shadow targets
- for (U32 i = 0; i < 2; i++)
- { //for each current shadow
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i);
+ //update shadow targets
+ for (U32 i = 0; i < 2; i++)
+ { //for each current shadow
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
+
+ if (mShadowSpotLight[i].notNull() &&
+ (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
+ mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
+ { //keep this spotlight
+ mSpotLightFade[i] = llmin(mSpotLightFade[i] + fade_amt, 1.f);
+ }
+ else
+ { //fade out this light
+ mSpotLightFade[i] = llmax(mSpotLightFade[i] - fade_amt, 0.f);
- if (mShadowSpotLight[i].notNull() &&
- (mShadowSpotLight[i] == mTargetShadowSpotLight[0] ||
- mShadowSpotLight[i] == mTargetShadowSpotLight[1]))
- { //keep this spotlight
- mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f);
- }
- else
- { //fade out this light
- mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f);
-
- if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
- { //faded out, grab one of the pending spots (whichever one isn't already taken)
- if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2])
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[0];
- }
- else
- {
- mShadowSpotLight[i] = mTargetShadowSpotLight[1];
- }
- }
- }
- }
+ if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull())
+ { //faded out, grab one of the pending spots (whichever one isn't already taken)
+ if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i + 1) % 2])
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[0];
+ }
+ else
+ {
+ mShadowSpotLight[i] = mTargetShadowSpotLight[1];
+ }
+ }
+ }
+ }
+ }
- for (S32 i = 0; i < 2; i++)
- {
- set_current_modelview(saved_view);
- set_current_projection(saved_proj);
+ for (S32 i = 0; i < 2; i++)
+ {
+ set_current_modelview(saved_view);
+ set_current_projection(saved_proj);
- if (mShadowSpotLight[i].isNull())
- {
- continue;
- }
+ if (mShadowSpotLight[i].isNull())
+ {
+ continue;
+ }
- LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
+ LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume();
- if (!volume)
- {
- mShadowSpotLight[i] = NULL;
- continue;
- }
+ if (!volume)
+ {
+ mShadowSpotLight[i] = NULL;
+ continue;
+ }
- LLDrawable* drawable = mShadowSpotLight[i];
+ LLDrawable* drawable = mShadowSpotLight[i];
- LLVector3 params = volume->getSpotLightParams();
- F32 fov = params.mV[0];
+ LLVector3 params = volume->getSpotLightParams();
+ F32 fov = params.mV[0];
- //get agent->light space matrix (modelview)
- LLVector3 center = drawable->getPositionAgent();
- LLQuaternion quat = volume->getRenderRotation();
+ //get agent->light space matrix (modelview)
+ LLVector3 center = drawable->getPositionAgent();
+ LLQuaternion quat = volume->getRenderRotation();
- //get near clip plane
- LLVector3 scale = volume->getScale();
- LLVector3 at_axis(0,0,-scale.mV[2]*0.5f);
- at_axis *= quat;
+ //get near clip plane
+ LLVector3 scale = volume->getScale();
+ LLVector3 at_axis(0, 0, -scale.mV[2] * 0.5f);
+ at_axis *= quat;
- LLVector3 np = center+at_axis;
- at_axis.normVec();
+ LLVector3 np = center + at_axis;
+ at_axis.normVec();
- //get origin that has given fov for plane np, at_axis, and given scale
- F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f);
+ //get origin that has given fov for plane np, at_axis, and given scale
+ F32 dist = (scale.mV[1] * 0.5f) / tanf(fov * 0.5f);
- LLVector3 origin = np - at_axis*dist;
+ LLVector3 origin = np - at_axis * dist;
- LLMatrix4 mat(quat, LLVector4(origin, 1.f));
+ LLMatrix4 mat(quat, LLVector4(origin, 1.f));
- view[i+4] = glh::matrix4f((F32*) mat.mMatrix);
+ view[i + 4] = glh::matrix4f((F32*)mat.mMatrix);
- view[i+4] = view[i+4].inverse();
+ view[i + 4] = view[i + 4].inverse();
- //get perspective matrix
- F32 near_clip = dist+0.01f;
- F32 width = scale.mV[VX];
- F32 height = scale.mV[VY];
- F32 far_clip = dist+volume->getLightRadius()*1.5f;
+ //get perspective matrix
+ F32 near_clip = dist + 0.01f;
+ F32 width = scale.mV[VX];
+ F32 height = scale.mV[VY];
+ F32 far_clip = dist + volume->getLightRadius() * 1.5f;
- F32 fovy = fov * RAD_TO_DEG;
- F32 aspect = width/height;
-
- proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip);
+ F32 fovy = fov * RAD_TO_DEG;
+ F32 aspect = width / height;
- //translate and scale to from [-1, 1] to [0, 1]
- glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
- 0.f, 0.5f, 0.f, 0.5f,
- 0.f, 0.f, 0.5f, 0.5f,
- 0.f, 0.f, 0.f, 1.f);
+ proj[i + 4] = gl_perspective(fovy, aspect, near_clip, far_clip);
- set_current_modelview(view[i+4]);
- set_current_projection(proj[i+4]);
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
- mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
-
- for (U32 j = 0; j < 16; j++)
- {
- gGLLastModelView[j] = mShadowModelview[i+4].m[j];
- gGLLastProjection[j] = mShadowProjection[i+4].m[j];
- }
+ set_current_modelview(view[i + 4]);
+ set_current_projection(proj[i + 4]);
- mShadowModelview[i+4] = view[i+4];
- mShadowProjection[i+4] = proj[i+4];
+ mSunShadowMatrix[i + 4] = trans * proj[i + 4] * view[i + 4] * inv_view;
- LLCamera shadow_cam = camera;
- shadow_cam.setFar(far_clip);
- shadow_cam.setOrigin(origin);
+ for (U32 j = 0; j < 16; j++)
+ {
+ gGLLastModelView[j] = mShadowModelview[i + 4].m[j];
+ gGLLastProjection[j] = mShadowProjection[i + 4].m[j];
+ }
- LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+ mShadowModelview[i + 4] = view[i + 4];
+ mShadowProjection[i + 4] = proj[i + 4];
- stop_glerror();
+ if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates
+ {
+ LLCamera shadow_cam = camera;
+ shadow_cam.setFar(far_clip);
+ shadow_cam.setOrigin(origin);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+ stop_glerror();
- mShadow[i+4].bindTarget();
- mShadow[i+4].getViewport(gGLViewport);
- mShadow[i+4].clear();
+ //
+
+ mSpotShadow[i].bindTarget();
+ mSpotShadow[i].getViewport(gGLViewport);
+ mSpotShadow[i].clear();
- U32 target_width = mShadow[i+4].getWidth();
+ U32 target_width = mSpotShadow[i].getWidth();
- static LLCullResult result[2];
+ static LLCullResult result[2];
- LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+ LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SPOT_SHADOW0 + i);
- RenderSpotLight = drawable;
+ RenderSpotLight = drawable;
- renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
+ renderShadow(view[i + 4], proj[i + 4], shadow_cam, result[i], FALSE, FALSE, target_width);
- RenderSpotLight = nullptr;
+ RenderSpotLight = nullptr;
- mShadow[i+4].flush();
- }
+ mSpotShadow[i].flush();
+ }
+ }
}
else
{ //no spotlight shadows
@@ -10827,6 +11038,7 @@ static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
{
LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
+ LL_PROFILE_GPU_ZONE("generateImpostor");
LLGLState::checkStates();
LLGLState::checkTextureChannels();
@@ -11095,7 +11307,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
if (LLPipeline::sRenderDeferred)
{
GLuint buff = GL_COLOR_ATTACHMENT0;
- LL_PROFILER_GPU_ZONEC( "gl.DrawBuffersARB", 0x8000FF );
glDrawBuffersARB(1, &buff);
}
@@ -11496,3 +11707,9 @@ void LLPipeline::restoreHiddenObject( const LLUUID& id )
}
}
+void LLPipeline::overrideEnvironmentMap()
+{
+ //mReflectionMapManager.mProbes.clear();
+ //mReflectionMapManager.addProbe(LLViewerCamera::instance().getOrigin());
+}
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 62d3ae7a39..cd7d0b88d8 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -38,6 +38,7 @@
#include "llgl.h"
#include "lldrawable.h"
#include "llrendertarget.h"
+#include "llreflectionmapmanager.h"
#include <stack>
@@ -187,6 +188,7 @@ public:
LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end,
bool pick_transparent,
bool pick_rigged,
+ bool pick_unselectable,
S32* face_hit, // return the face hit
LLVector4a* intersection = NULL, // return the intersection point
LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
@@ -216,8 +218,9 @@ public:
U32 addObject(LLViewerObject *obj);
void enableShadows(const bool enable_shadows);
- void releaseShadowTargets();
- void releaseShadowTarget(U32 index);
+ void releaseSpotShadowTargets();
+ void releaseSunShadowTargets();
+ void releaseSunShadowTarget(U32 index);
// void setLocalLighting(const bool local_lighting);
// bool isLocalLightingEnabled() const;
@@ -293,12 +296,17 @@ 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);
void generateWaterReflection(LLCamera& camera);
void generateSunShadow(LLCamera& camera);
- LLRenderTarget* getShadowTarget(U32 i);
+ LLRenderTarget* getSunShadowTarget(U32 i);
+ LLRenderTarget* getSpotShadowTarget(U32 i);
void generateHighlight(LLCamera& camera);
void renderHighlight(const LLViewerObject* obj, F32 fade);
@@ -426,6 +434,9 @@ public:
void hideObject( const LLUUID& id );
void restoreHiddenObject( const LLUUID& id );
+ LLReflectionMapManager mReflectionMapManager;
+ void overrideEnvironmentMap();
+
private:
void unloadShaders();
void addToQuickLookup( LLDrawPool* new_poolp );
@@ -517,6 +528,8 @@ public:
RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED,
RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE,
RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED,
+ RENDER_TYPE_PASS_PBR_OPAQUE = LLRenderPass::PASS_PBR_OPAQUE,
+ RENDER_TYPE_PASS_PBR_OPAQUE_RIGGED = LLRenderPass::PASS_PBR_OPAQUE_RIGGED,
// Following are object types (only used in drawable mRenderType)
RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES,
RENDER_TYPE_VOLUME,
@@ -574,7 +587,8 @@ public:
RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used
RENDER_DEBUG_TEXEL_DENSITY = 0x40000000,
RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000,
- RENDER_DEBUG_IMPOSTORS = 0x100000000
+ RENDER_DEBUG_IMPOSTORS = 0x100000000,
+ RENDER_DEBUG_REFLECTION_PROBES = 0x200000000
};
public:
@@ -626,26 +640,48 @@ public:
static bool sRenderAttachedLights;
static bool sRenderAttachedParticles;
static bool sRenderDeferred;
+ static bool sRenderPBR;
static S32 sVisibleLightCount;
static bool sRenderingHUDs;
static F32 sDistortionWaterClipPlaneMargin;
static LLTrace::EventStatHandle<S64> sStatBatchSize;
- //screen texture
- U32 mScreenWidth;
- U32 mScreenHeight;
-
- LLRenderTarget mScreen;
- LLRenderTarget mUIScreen;
- LLRenderTarget mDeferredScreen;
- LLRenderTarget mFXAABuffer;
- LLRenderTarget mEdgeMap;
- LLRenderTarget mDeferredDepth;
- LLRenderTarget mOcclusionDepth;
- LLRenderTarget mDeferredLight;
- LLRenderTarget mHighlight;
- LLRenderTarget mPhysicsDisplay;
+ class RenderTargetPack
+ {
+ public:
+ U32 width = 0;
+ U32 height = 0;
+
+ //screen texture
+ LLRenderTarget screen;
+ LLRenderTarget uiScreen;
+ LLRenderTarget deferredScreen;
+ LLRenderTarget fxaaBuffer;
+ LLRenderTarget edgeMap;
+ LLRenderTarget deferredDepth;
+ LLRenderTarget occlusionDepth;
+ LLRenderTarget deferredLight;
+
+ //sun shadow map
+ LLRenderTarget shadow[4];
+ LLRenderTarget shadowOcclusion[4];
+ };
+
+ // main full resoltuion render target
+ RenderTargetPack mMainRT;
+
+ // auxillary 512x512 render target pack
+ RenderTargetPack mAuxillaryRT;
+
+ // currently used render target pack
+ RenderTargetPack* mRT;
+
+ LLRenderTarget mSpotShadow[2];
+ LLRenderTarget mSpotShadowOcclusion[2];
+
+ LLRenderTarget mHighlight;
+ LLRenderTarget mPhysicsDisplay;
LLCullResult mSky;
LLCullResult mReflectedObjects;
@@ -657,15 +693,16 @@ public:
//utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1]
LLPointer<LLVertexBuffer> mCubeVB;
- //sun shadow map
- LLRenderTarget mShadow[6];
- LLRenderTarget mShadowOcclusion[6];
+ //list of currently bound reflection maps
+ std::vector<LLReflectionMap*> mReflectionMaps;
+
std::vector<LLVector3> mShadowFrustPoints[4];
LLVector4 mShadowError;
LLVector4 mShadowFOV;
LLVector3 mShadowFrustOrigin[4];
LLCamera mShadowCamera[8];
LLVector3 mShadowExtents[4][2];
+ // TODO : separate Sun Shadow and Spot Shadow matrices
glh::matrix4f mSunShadowMatrix[6];
glh::matrix4f mShadowModelview[6];
glh::matrix4f mShadowProjection[6];
@@ -860,6 +897,7 @@ protected:
LLDrawPool* mBumpPool;
LLDrawPool* mMaterialsPool;
LLDrawPool* mWLSkyPool;
+ LLDrawPool* mPBROpaquePool;
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
public:
diff --git a/indra/newview/skins/default/textures/icons/Inv_Material.png b/indra/newview/skins/default/textures/icons/Inv_Material.png
new file mode 100644
index 0000000000..f5918ceaed
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_Material.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index e9ef888a7f..f18dff5b22 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -303,6 +303,7 @@ with the same filename but different name
<texture name="Inv_LostClosed" file_name="icons/Inv_LostClosed.png" preload="false" />
<texture name="Inv_LostOpen" file_name="icons/Inv_LostOpen.png" preload="false" />
<texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
+ <texture name="Inv_Material" file_name="icons/Inv_Material.png" preload="false" />
<texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" />
<texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
<texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
index d783d1e23c..e91efb89b2 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="466"
+ height="486"
layout="topleft"
name="Inventory Finder"
help_topic="inventory_finder"
@@ -95,12 +95,29 @@
width="126" />
<icon
height="16"
+ image_name="Inv_Material"
+ layout="topleft"
+ left="8"
+ mouse_opaque="true"
+ name="icon_material"
+ top="122"
+ width="16" />
+ <check_box
+ height="16"
+ label="Materials"
+ layout="topleft"
+ left_pad="2"
+ name="check_material"
+ top_delta="0"
+ width="126" />
+ <icon
+ height="16"
image_name="Inv_Notecard"
layout="topleft"
left="8"
mouse_opaque="true"
name="icon_notecard"
- top="122"
+ top="142"
width="16" />
<check_box
height="16"
@@ -117,7 +134,7 @@
left="8"
mouse_opaque="true"
name="icon_object"
- top="142"
+ top="162"
width="16" />
<check_box
height="16"
@@ -134,7 +151,7 @@
left="8"
mouse_opaque="true"
name="icon_script"
- top="162"
+ top="182"
width="16" />
<check_box
height="16"
@@ -151,7 +168,7 @@
left="8"
mouse_opaque="true"
name="icon_sound"
- top="182"
+ top="202"
width="16" />
<check_box
height="16"
@@ -168,7 +185,7 @@
left="8"
mouse_opaque="true"
name="icon_texture"
- top="202"
+ top="222"
width="16" />
<check_box
height="16"
@@ -185,7 +202,7 @@
left="8"
mouse_opaque="true"
name="icon_snapshot"
- top="222"
+ top="242"
width="16" />
<check_box
height="16"
@@ -202,7 +219,7 @@
left="8"
mouse_opaque="true"
name="icon_settings"
- top="242"
+ top="262"
width="16" />
<check_box
height="16"
@@ -220,7 +237,7 @@
layout="topleft"
left="8"
name="All"
- top="262"
+ top="282"
width="100" />
<button
height="20"
@@ -274,7 +291,7 @@
width="260"/>
<check_box
height="16"
- top="352"
+ top="372"
label="Since Logoff"
layout="topleft"
left_delta="0"
@@ -290,7 +307,7 @@
layout="topleft"
left_delta="0"
name="- OR -"
- top="370"
+ top="390"
width="144">
- OR -
</text>
@@ -298,7 +315,7 @@
height="16"
layout="topleft"
name="date_search_direction"
- top="388"
+ top="408"
left="8"
width="270">
<radio_item
@@ -368,6 +385,6 @@
layout="topleft"
name="Close"
right="-6"
- top="434"
+ top="454"
width="76" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml
new file mode 100644
index 0000000000..74adc86126
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="false"
+ default_tab_group="1"
+ height="887"
+ layout="topleft"
+ name="material editor"
+ help_topic="material_editor"
+ title="[MATERIAL_NAME]"
+ width="256">
+ <string name="no_upload_fee_string">no upload fee</string>
+ <string name="upload_fee_string">L$[FEE] upload fee</string>
+ <check_box
+ follows="left|top"
+ label="Double Sided"
+ left="14"
+ top="14"
+ name="double sided"
+ height="25"
+ width="120" />
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="196"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="albedo_texture_pnl"
+ top_pad="5"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64">
+ Albedo:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="albedo_texture"
+ tool_tip="Albedo map. Alpha channel is optional and used for transparency."
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="albedo_upload_fee"
+ >
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ >
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="albedo color"
+ width="40" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ >
+ Transparency
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ max_val="1"
+ name="transparency"
+ width="64"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label alphamode"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="5"
+ width="90">
+ Alpha mode
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="alpha mode"
+ top_pad="4"
+ width="96">
+ <combo_box.item
+ label="None"
+ name="None"
+ value="OPAQUE" />
+ <combo_box.item
+ label="Alpha blending"
+ name="Alpha blending"
+ value="BLEND" />
+ <combo_box.item
+ label="Alpha masking"
+ name="Alpha masking"
+ value="MASK" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ >
+ Alpha Cutoff
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ max_val="1"
+ name="alpha cutoff"
+ width="64"
+ />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="metallic_texture_pnl"
+ top_pad="5"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ >
+ Metallic-Roughness:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ width="128"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="metallic_roughness_texture"
+ tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
+ top_pad="8"
+ />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="metallic_upload_fee"
+ >
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ >
+ Metallic Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ max_val="1"
+ name="metalness factor"
+ width="64"
+ />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96"
+ >
+ Roughness Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+
+ max_val="1"
+ name="roughness factor"
+ width="64"
+ />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ name="emissive_texture_pnl"
+ top_pad="5"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64">
+ Emissive:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="emissive_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="emissive_upload_fee"
+ >
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8"
+ >
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="emissive color"
+ width="40" />
+ <!--<text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="64"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ >
+ Intensity
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ max_val="100"
+ width="64"
+ />-->
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="5"
+ mouse_opaque="false"
+ top_pad="5"
+ name="normal_texture_pnl"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64">
+ Normal:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="normal_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="normal_upload_fee"
+ >
+ No upload fee
+ </text>
+ </panel>
+
+ <panel
+ follows="right|bottom"
+ width="246"
+ height="97"
+ layout="bottomright"
+ top_delta="-2"
+ left="5"
+ name="button_panel"
+ >
+ <text
+ type="string"
+ name="unsaved_changes"
+ font.style="BOLD"
+ text_color="DrYellow"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="200"
+ layout="topleft"
+ left="10"
+ top="0"
+ >
+ Usaved changes
+ </text>
+ <button
+ follows="left|top"
+ height="25"
+ label="Save"
+ layout="topleft"
+ name="save"
+ top_pad="7"
+ left="0"
+ width="120" />
+ <button
+ follows="left|top"
+ height="25"
+ label="Save As..."
+ layout="topleft"
+ name="save_as"
+ top_delta="0"
+ left_pad="6"
+ width="120" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="220"
+ layout="topleft"
+ left="10"
+ top_pad="5"
+ name="total_upload_fee"
+ >
+ Total upload fee: L$ [FEE]
+ </text>
+
+ <view_border
+ bevel_style="none"
+ height="0"
+ layout="topleft"
+ left="0"
+ name="button_border"
+ top_pad="7"
+ width="246"/>
+
+ <button
+ follows="left|top"
+ height="25"
+ label="Cancel"
+ layout="topleft"
+ name="cancel"
+ top_pad="7"
+ left="61"
+ width="121" />
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index d1e167df64..b7708b057d 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -289,52 +289,6 @@
top_delta="16"
width="335" />
- <slider
- control_name="RenderFogRatio"
- follows="left|top"
- height="16"
- initial_value="4"
- decimal_digits="1"
- label="Fog Distance Ratio:"
- label_width="185"
- layout="topleft"
- left="30"
- name="fog"
- min_val="0.5"
- max_val="10"
- increment="0.1"
- top_delta="16"
- width="332" />
-
- <slider
- control_name="RenderGamma"
- follows="left|top"
- height="16"
- initial_value="1"
- decimal_digits="2"
- label="Gamma:"
- label_width="185"
- layout="topleft"
- left="30"
- name="gamma"
- min_val="0"
- max_val="2"
- increment="0.01"
- top_delta="16"
- width="332" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="30"
- name="(brightness, lower is brighter)"
- top_delta="16"
- width="260">
- (0 = default brightness, lower = brighter)
- </text>
-
<check_box
control_name="RenderAnisotropic"
height="16"
@@ -602,20 +556,6 @@
</check_box>
<check_box
- control_name="RenderObjectBump"
- height="16"
- initial_value="true"
- label="Bump mapping and shiny"
- layout="topleft"
- left="420"
- name="BumpShiny"
- top_delta="16"
- width="300">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
control_name="RenderLocalLights"
height="16"
initial_value="true"
@@ -626,51 +566,6 @@
top_delta="16"
width="300" />
- <slider
- control_name="RenderTerrainDetail"
- follows="left|top"
- height="16"
- label="Terrain Detail:"
- label_width="165"
- layout="topleft"
- left="440"
- show_text="false"
- initial_value="0"
- increment="1"
- min_val="0"
- max_val="1"
- name="TerrainDetail"
- top_delta="16"
- width="280" >
- <slider.commit_callback
- function="Pref.UpdateSliderText"
- parameter="TerrainDetail" />
- </slider>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="16"
- layout="topleft"
- top_delta="0"
- left_delta="284"
- name="TerrainDetailText"
- text_readonly_color="LabelDisabledColor"
- width="65">
- Low
- </text>
-
- <check_box
- control_name="RenderAvatarCloth"
- height="16"
- initial_value="true"
- label="Avatar cloth"
- layout="topleft"
- left="440"
- name="AvatarCloth"
- top_delta="16"
- width="280" />
-
<text
type="string"
length="1"
@@ -680,7 +575,7 @@
name="ReflectionsText"
text_readonly_color="LabelDisabledColor"
top_delta="16"
- left="440"
+ left="420"
width="128">
Water Reflections:
</text>
@@ -722,20 +617,6 @@
value="4"/>
</combo_box>
- <check_box
- control_name="WindLightUseAtmosShaders"
- height="16"
- initial_value="true"
- label="Atmospheric shaders"
- layout="topleft"
- left="440"
- name="WindLightUseAtmosShaders"
- top_delta="16"
- width="280">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
<slider
control_name="WLSkyDetail"
decimal_digits="0"
@@ -746,7 +627,7 @@
label="Sky:"
label_width="145"
layout="topleft"
- left="460"
+ left="420"
min_val="16"
max_val="128"
name="SkyMeshDetail"
@@ -772,26 +653,12 @@
</text>
<check_box
- control_name="RenderDeferred"
- height="16"
- initial_value="true"
- label="Advanced Lighting Model"
- layout="topleft"
- left="460"
- name="UseLightShaders"
- top_delta="16"
- width="260">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
control_name="RenderDeferredSSAO"
height="16"
initial_value="true"
label="Ambient Occlusion"
layout="topleft"
- left="480"
+ left="420"
name="UseSSAO"
top_delta="16"
width="240">
@@ -805,7 +672,7 @@
initial_value="true"
label="Depth of Field"
layout="topleft"
- left="480"
+ left="420"
name="UseDoF"
top_delta="16"
width="240">
@@ -813,29 +680,13 @@
function="Pref.RenderOptionUpdate" />
</check_box>
- <!--
- <check_box
- control_name="RenderUseAdvancedAtmospherics"
- height="16"
- initial_value="true"
- label="Advanced Atmospherics"
- layout="topleft"
- left="480"
- name="UseAdvancedAtmo"
- top_delta="16"
- width="240">
- <check_box.commit_callback
- function="Pref.AdvancedAtmosphericsEnable" />
- </check_box>
- -->
-
<text
type="string"
length="1"
follows="left|top"
height="16"
layout="topleft"
- left="480"
+ left="420"
name="RenderShadowDetailText"
text_readonly_color="LabelDisabledColor"
top_delta="16"
@@ -863,15 +714,49 @@
name="2"
value="2"/>
</combo_box>
-
-<!-- End of Advanced Settings block -->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="420"
+ name="RenderReflectionDetailText"
+ text_readonly_color="LabelDisabledColor"
+ top_delta="16"
+ width="128">
+ Reflections:
+ </text>
+ <combo_box
+ control_name="RenderReflectionProbeDetail"
+ height="18"
+ layout="topleft"
+ left_delta="130"
+ top_delta="0"
+ name="ReflectionDetial"
+ width="150">
+ <combo_box.item
+ label="Static Only"
+ name="0"
+ value="0"/>
+ <combo_box.item
+ label="Static+Dynamic"
+ name="1"
+ value="1"/>
+ <combo_box.item
+ label="Realtime"
+ name="2"
+ value="2"/>
+ </combo_box>
+
+ <!-- End of Advanced Settings block -->
<view_border
bevel_style="in"
height="0"
layout="topleft"
left="13"
name="horiz_border"
- top_pad="21"
+ top="338"
top_delta="5"
width="774"/>
<button
@@ -881,7 +766,7 @@
layout="topleft"
left="20"
name="Defaults"
- top_delta="10"
+ top_delta="20"
width="210">
<button.commit_callback
function="Pref.HardwareDefaults" />
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index ade79b8884..3471d4b7b1 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -2531,7 +2531,70 @@ even though the user gets a free copy.
mouse_opaque="true"
name="Light Ambiance"
width="120" />
- <text
+ <check_box
+ height="16"
+ label="Reflection Probe"
+ layout="topleft"
+ left="10"
+ name="Reflection Probe"
+ tool_tip="Adjusts how objects within this volume receive reflections when PBR is enabled"
+ top_pad="10"
+ width="60" />
+ <combo_box
+ height="19"
+ top_delta="0"
+ left="144"
+ follows="left|top"
+ name="Probe Volume Type"
+ tool_tip="Choose the probe influence volume"
+ width="108">
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Box"
+ name="Box"
+ value="Box"/>
+ </combo_box>
+ <check_box
+ height="16"
+ label="Dynamic"
+ layout="topleft"
+ left="10"
+ name="Probe Dynamic"
+ tool_tip="When enabled, Avatars will appear in reflections within this probe's influence volume."
+ bottom_delta="19"
+ width="60" />
+ <spinner bottom_delta="19"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="0"
+ label="Ambiance"
+ label_width="55"
+ left="10"
+ max_val="1"
+ min_val="0"
+ mouse_opaque="true"
+ name="Probe Ambiance"
+ width="120" />
+ <spinner bottom_delta="0"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="0"
+ label="Near Clip"
+ label_width="55"
+ left="144"
+ max_val="1024"
+ min_val="0"
+ mouse_opaque="true"
+ name="Probe Near Clip"
+ width="120" />
+ <text
type="string"
length="1"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index aa3d0ae071..c7c1e1d75a 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -143,264 +143,6 @@
function="Inventory.EmptyLostAndFound"
parameter="rename" />
</menu_item_call>
- <menu_item_call
- label="New Folder"
- layout="topleft"
- name="New Folder">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="category" />
- </menu_item_call>
- <menu_item_call
- label="New Outfit"
- layout="topleft"
- name="New Outfit">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="outfit" />
- </menu_item_call>
- <menu_item_call
- label="New Script"
- layout="topleft"
- name="New Script">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="lsl" />
- </menu_item_call>
- <menu_item_call
- label="New Notecard"
- layout="topleft"
- name="New Note">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="notecard" />
- </menu_item_call>
- <menu_item_call
- label="New Gesture"
- layout="topleft"
- name="New Gesture">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="gesture" />
- </menu_item_call>
- <menu
- label="New Clothes"
- layout="topleft"
- name="New Clothes">
- <menu_item_call
- label="New Shirt"
- layout="topleft"
- name="New Shirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shirt" />
- </menu_item_call>
- <menu_item_call
- label="New Pants"
- layout="topleft"
- name="New Pants">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="pants" />
- </menu_item_call>
- <menu_item_call
- label="New Shoes"
- layout="topleft"
- name="New Shoes">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shoes" />
- </menu_item_call>
- <menu_item_call
- label="New Socks"
- layout="topleft"
- name="New Socks">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="socks" />
- </menu_item_call>
- <menu_item_call
- label="New Jacket"
- layout="topleft"
- name="New Jacket">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="jacket" />
- </menu_item_call>
- <menu_item_call
- label="New Skirt"
- layout="topleft"
- name="New Skirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="skirt" />
- </menu_item_call>
- <menu_item_call
- label="New Gloves"
- layout="topleft"
- name="New Gloves">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="gloves" />
- </menu_item_call>
- <menu_item_call
- label="New Undershirt"
- layout="topleft"
- name="New Undershirt">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="undershirt" />
- </menu_item_call>
- <menu_item_call
- label="New Underpants"
- layout="topleft"
- name="New Underpants">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="underpants" />
- </menu_item_call>
- <menu_item_call
- label="New Alpha Mask"
- layout="topleft"
- name="New Alpha Mask">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="alpha" />
- </menu_item_call>
- <menu_item_call
- label="New Tattoo"
- layout="topleft"
- name="New Tattoo">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="tattoo" />
- </menu_item_call>
- <menu_item_call
- label="New Universal"
- layout="topleft"
- name="New Universal">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="universal" />
- </menu_item_call>
- <menu_item_call
- label="New Physics"
- layout="topleft"
- name="New Physics">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="physics" />
- </menu_item_call>
- </menu>
- <menu
- label="New Body Parts"
- layout="topleft"
- name="New Body Parts">
- <menu_item_call
- label="New Shape"
- layout="topleft"
- name="New Shape">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="shape" />
- </menu_item_call>
- <menu_item_call
- label="New Skin"
- layout="topleft"
- name="New Skin">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="skin" />
- </menu_item_call>
- <menu_item_call
- label="New Hair"
- layout="topleft"
- name="New Hair">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="hair" />
- </menu_item_call>
- <menu_item_call
- label="New Eyes"
- layout="topleft"
- name="New Eyes">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="eyes" />
- </menu_item_call>
- </menu>
- <menu
- label="New Settings"
- layout="topleft"
- name="New Settings">
- <menu_item_call
- label="New Sky"
- layout="topleft"
- name="New Sky">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="sky"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- <menu_item_call
- label="New Water"
- layout="topleft"
- name="New Water">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="water"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- <menu_item_call
- label="New Day Cycle"
- layout="topleft"
- name="New Day Cycle">
- <menu_item_call.on_click
- function="Inventory.DoCreate"
- parameter="daycycle"/>
- <menu_item_call.on_enable
- function="Inventory.EnvironmentEnabled" />
- </menu_item_call>
- </menu>
- <menu
- label="Use as default for"
- layout="topleft"
- name="upload_def">
- <menu_item_call
- label="Image uploads"
- layout="topleft"
- name="Image uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="texture" />
- </menu_item_call>
- <menu_item_call
- label="Sound uploads"
- layout="topleft"
- name="Sound uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="sound" />
- </menu_item_call>
- <menu_item_call
- label="Animation uploads"
- layout="topleft"
- name="Animation uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="animation" />
- </menu_item_call>
- <menu_item_call
- label="Model uploads"
- layout="topleft"
- name="Model uploads">
- <menu_item_call.on_click
- function="Inventory.FileUploadLocation"
- parameter="model" />
- </menu_item_call>
- </menu>
<menu
label="Change Type"
layout="topleft"
@@ -683,6 +425,275 @@
parameter="delete_system_folder" />
</menu_item_call>
<menu_item_separator
+ layout="topleft"
+ name="Create Separator" />
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Outfit"
+ layout="topleft"
+ name="New Outfit">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="outfit" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Notecard"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Material"
+ layout="topleft"
+ name="New Material">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="material" />
+ </menu_item_call>
+ <menu
+ label="New Clothes"
+ layout="topleft"
+ name="New Clothes">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha Mask"
+ layout="topleft"
+ name="New Alpha Mask">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Universal"
+ layout="topleft"
+ name="New Universal">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="universal" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Physics"
+ layout="topleft"
+ name="New Physics">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="physics" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Body Parts"
+ layout="topleft"
+ name="New Body Parts">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="New Settings"
+ layout="topleft"
+ name="New Settings">
+ <menu_item_call
+ label="New Sky"
+ layout="topleft"
+ name="New Sky">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="sky"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Water"
+ layout="topleft"
+ name="New Water">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="water"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Day Cycle"
+ layout="topleft"
+ name="New Day Cycle">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="daycycle"/>
+ <menu_item_call.on_enable
+ function="Inventory.EnvironmentEnabled" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Use as default for"
+ layout="topleft"
+ name="upload_def">
+ <menu_item_call
+ label="Image uploads"
+ layout="topleft"
+ name="Image uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="texture" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound uploads"
+ layout="topleft"
+ name="Sound uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="sound" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation uploads"
+ layout="topleft"
+ name="Animation uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="animation" />
+ </menu_item_call>
+ <menu_item_call
+ label="Model uploads"
+ layout="topleft"
+ name="Model uploads">
+ <menu_item_call.on_click
+ function="Inventory.FileUploadLocation"
+ parameter="model" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
layout="topleft" />
<menu_item_separator
layout="topleft" />
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index 3385a29a6c..0e193521a3 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -97,6 +97,14 @@
function="Inventory.DoCreate"
parameter="gesture" />
</menu_item_call>
+ <menu_item_call
+ label="New Material"
+ layout="topleft"
+ name="New Material">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="material" />
+ </menu_item_call>
<menu
height="175"
label="New Clothes"
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1caa0908ea..d3b13bfc2a 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1417,6 +1417,15 @@ function="World.EnvPreset"
function="Tools.SelectOnlyMovableObjects"
parameter="movable" />
</menu_item_check>
+ <menu_item_check
+ label="Select Invisible Objects"
+ name="Select Invisible Objects">
+ <menu_item_check.on_check
+ control="SelectInvisibleObjects" />
+ <menu_item_check.on_click
+ function="Tools.SelectInvisibleObjects"
+ parameter="invisible" />
+ </menu_item_check>
<menu_item_check
label="Select By Surrounding"
name="Select By Surrounding">
@@ -1574,6 +1583,16 @@ function="World.EnvPreset"
<menu_item_call.on_visible
function="File.VisibleUploadModel"/>
</menu_item_call>
+ <menu_item_call
+ label="Material..."
+ layout="topleft"
+ name="Upload Material">
+ <menu_item_call.on_click
+ function="File.UploadMaterial"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUploadMaterial" />
+ </menu_item_call>
<menu_item_call
label="Bulk..."
layout="topleft"
@@ -1586,7 +1605,15 @@ function="World.EnvPreset"
parameter="" />
</menu_item_call>
</menu>
- <menu_item_separator/>
+ <menu_item_call
+ label="Material Editor"
+ name="material_editor_menu_item">
+ <menu_item_call.on_click
+ function="Floater.ToggleOrBringToFront"
+ parameter="material_editor" />
+ </menu_item_call>
+
+ <menu_item_separator/>
<menu_item_call
enabled="false"
label="Undo"
@@ -2912,6 +2939,16 @@ function="World.EnvPreset"
parameter="lights" />
</menu_item_check>
<menu_item_check
+ label="Reflection Probes"
+ name="Reflection Probes">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="reflection probes" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="reflection probes" />
+ </menu_item_check>
+ <menu_item_check
label="Particles"
name="Particles">
<menu_item_check.on_check
@@ -3250,6 +3287,13 @@ function="World.EnvPreset"
function="ToggleControl"
parameter="RenderHoverGlowEnable" />
</menu_item_check>
+ <menu_item_call
+ enabled="true"
+ label="Rebuild Reflection Probes"
+ name="Rebuild Reflection Probes">
+ <menu_item_call.on_click
+ function="Develop.RebuildReflectionProbes" />
+ </menu_item_call>
<menu_item_separator />
<menu_item_call
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1ee0d9c64a..24a934fbb8 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6764,6 +6764,22 @@ You don&apos;t have permission to view this notecard.
<notification
icon="notifytip.tga"
+ name="MaterialMissing"
+ type="notifytip">
+ Material is missing from database.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="MaterialNoPermissions"
+ type="notifytip">
+ You don&apos;t have permission to view this material.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
name="RezItemNoPermissions"
type="notifytip">
Insufficient permissions to rez object.
@@ -6795,6 +6811,15 @@ Please try again.
<notification
icon="notifytip.tga"
+ name="UnableToLoadMaterial"
+ type="notifytip">
+ Unable to load material.
+ Please try again.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="notifytip.tga"
name="ScriptMissing"
type="notifytip">
Script is missing from database.
@@ -9025,7 +9050,64 @@ Unable to upload texture.
[REASON]
<tag>fail</tag>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="CannotUploadMaterial"
+ type="alertmodal">
+There was a problem uploading the file
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ label="Save Material"
+ name="SaveMaterialAs"
+ type="alertmodal">
+ <unique/>
+ Name this material:
+ <tag>confirm</tag>
+ <form name="form">
+ <input name="message" type="text">
+ [DESC]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="InvalidMaterialName"
+ type="alertmodal">
+Please enter a non-empty name
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UsavedMaterialChanges"
+ type="alertmodal">
+ You have unsaved changes.
+ <form name="form">
+ <button
+ index="0"
+ name="discard"
+ text="Discard changes"/>
+ <button
+ index="1"
+ name="keep"
+ text="Keep editing"/>
+ </form>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="LivePreviewUnavailable"
@@ -11876,4 +11958,10 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB
yestext="OK"/>
</notification>
+<notification
+ icon="notifytip.tga"
+ name="MaterialCreated"
+ type="notifytip">
+Material successfully created. Asset ID: [ASSET_ID]
+</notification>
</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 5aff7a5127..908ddd32b5 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -232,33 +232,19 @@
</text>
<check_box
- control_name="WindLightUseAtmosShaders"
+ control_name="RenderPBR"
height="16"
initial_value="true"
- label="Atmospheric shaders"
+ label="Physically Based Rendering"
layout="topleft"
left="30"
- name="WindLightUseAtmosShaders"
- top_delta="24"
- width="280">
- <check_box.commit_callback
- function="Pref.RenderOptionUpdate" />
- </check_box>
-
- <check_box
- control_name="RenderDeferred"
- height="16"
- initial_value="true"
- label="Advanced Lighting Model"
- layout="topleft"
- left="30"
- name="UseLightShaders"
+ name="UsePBRShaders"
top_delta="24"
width="256">
<check_box.commit_callback
function="Pref.RenderOptionUpdate" />
</check_box>
-
+
<slider
control_name="IndirectMaxComplexity"
tool_tip="Controls at what point a visually complex avatar is drawn as a JellyDoll"
@@ -274,7 +260,7 @@
max_val="101"
name="IndirectMaxComplexity"
show_text="false"
- top_delta="60"
+ top_delta="36"
width="300">
<slider.commit_callback
function="Pref.UpdateIndirectMaxComplexity"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
index 6f82a0efa1..094be36b01 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -315,6 +315,29 @@
top_delta="20"
width="219"
can_edit_text="true"/>
+ <text
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="-5"
+ top_delta="25"
+ width="200">
+ Reflection Probe Ambiance:
+ </text>
+ <slider
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="5"
+ min_val="0"
+ max_val="1"
+ name="probe_ambiance"
+ top_delta="20"
+ width="219"
+ can_edit_text="true"/>
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index 0cbd7fe2dd..c8f5a66661 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -2,7 +2,7 @@
<panel
border="false"
follows="all"
- height="420"
+ height="500"
label="Texture"
layout="topleft"
left="0"
@@ -845,4 +845,29 @@
height="4"
start_url="about:blank"
decouple_texture_size="true" />
- </panel>
+ <button
+ left="90"
+ top="222"
+ height="20"
+ label="Save as Material"
+ label_selected="Save current face as a Material"
+ layout="topleft"
+ name="button save material"
+ top_delta="0"
+ tool_tip="Save material to inventory"
+ width="110" />
+
+ <line_editor
+ enabled="true"
+ follows="top|left"
+ height="16"
+ layout="topleft"
+ left="7"
+ label="Material UUID"
+ name="materialID"
+ select_on_focus="true"
+ top="380"
+ width="200"
+ tool_tip="UUID for a material asset"
+ />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 8382e3970c..4169929be8 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -405,6 +405,7 @@ http://secondlife.com/support for help fixing this problem.
<string name="symbolic link">link</string>
<string name="symbolic folder link">folder link</string>
<string name="settings blob">settings</string>
+ <string name="render material">material</string>
<string name="mesh">mesh</string>
<!-- llvoavatar. Displayed in the avatar chat bubble -->
@@ -2420,6 +2421,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="Clothing" value=" Clothing," />
<string name="Gestures" value=" Gestures," />
<string name="Landmarks" value=" Landmarks," />
+ <string name="Materials" value=" Materials," />
<string name="Notecards" value=" Notecards," />
<string name="Objects" value=" Objects," />
<string name="Scripts" value=" Scripts," />
@@ -3841,6 +3843,7 @@ Abuse Report</string>
<string name="New Physics">New Physics</string>
<string name="Invalid Wearable">Invalid Wearable</string>
<string name="New Gesture">New Gesture</string>
+ <string name="New Material">New Material</string>
<string name="New Script">New Script</string>
<string name="New Note">New Note</string>
<string name="New Folder">New Folder</string>