# Conflicts:
#	indra/llappearance/llavatarappearance.h
#	indra/llimage/llimage.cpp
#	indra/llmath/llvolume.cpp
#	indra/llmath/llvolume.h
#	indra/llprimitive/llgltfmaterial.h
#	indra/llrender/llshadermgr.cpp
#	indra/newview/lldynamictexture.cpp
#	indra/newview/llenvironment.cpp
#	indra/newview/llfetchedgltfmaterial.cpp
#	indra/newview/llfloaterimagepreview.cpp
#	indra/newview/llfloaterimagepreview.h
#	indra/newview/llfloaterpreference.cpp
#	indra/newview/llfloaterregioninfo.cpp
#	indra/newview/llfloaterregioninfo.h
#	indra/newview/llmaniprotate.cpp
#	indra/newview/llmaniptranslate.cpp
#	indra/newview/llpanelvolume.cpp
#	indra/newview/llselectmgr.cpp
#	indra/newview/llselectmgr.h
#	indra/newview/llsurface.cpp
#	indra/newview/llsurface.h
#	indra/newview/llsurfacepatch.cpp
#	indra/newview/lltexturectrl.cpp
#	indra/newview/lltexturectrl.h
#	indra/newview/lltinygltfhelper.cpp
#	indra/newview/llviewerregion.cpp
#	indra/newview/llviewerwindow.cpp
#	indra/newview/llviewerwindow.h
#	indra/newview/llvlcomposition.cpp
#	indra/newview/llvlcomposition.h
#	indra/newview/llvocache.cpp
#	indra/newview/llvovolume.cpp
#	indra/newview/pipeline.cpp
master
Ansariel 2024-06-11 19:04:21 +02:00
commit 18903f6cac
259 changed files with 12861 additions and 2392 deletions

View File

@ -1934,6 +1934,18 @@
</map> </map>
<key>mikktspace</key> <key>mikktspace</key>
<map> <map>
<key>canonical_repo</key>
<string>https://bitbucket.org/lindenlab/3p-mikktspace</string>
<key>copyright</key>
<string>Copyright (C) 2011 by Morten S. Mikkelsen, Copyright (C) 2022 Blender Authors</string>
<key>description</key>
<string>Mikktspace Tangent Generator</string>
<key>license</key>
<string>Apache 2.0</string>
<key>license_file</key>
<string>mikktspace.txt</string>
<key>name</key>
<string>mikktspace</string>
<key>platforms</key> <key>platforms</key>
<map> <map>
<key>darwin64</key> <key>darwin64</key>
@ -1941,58 +1953,46 @@
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>6cc1585dba85b0226a2e7033a7e2a2ceaae7c983</string> <string>65edf85c36a10001e32bdee582bec4732137208b</string>
<key>hash_algorithm</key> <key>hash_algorithm</key>
<string>sha1</string> <string>sha1</string>
<key>url</key> <key>url</key>
<string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-darwin64-5cee1f4.tar.zst</string> <string>https://github.com/secondlife/3p-mikktspace/releases/download/v2-e967e1b/mikktspace-1-darwin64-8756084692.tar.zst</string>
</map> </map>
<key>name</key> <key>name</key>
<string>darwin64</string> <string>darwin64</string>
</map> </map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>6b7d01ad54e4a88a001f66840c32329cedb28202</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-windows64-5cee1f4.tar.zst</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
<key>linux64</key> <key>linux64</key>
<map> <map>
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>edc9782bf209e17ad1845498b42f16d733582082</string> <string>fa9dcee4584df7e7271fdf69c08e6fd3122a47fc</string>
<key>hash_algorithm</key> <key>hash_algorithm</key>
<string>sha1</string> <string>sha1</string>
<key>url</key> <key>url</key>
<string>https://github.com/secondlife/3p-mikktspace/releases/download/v1-5cee1f4/mikktspace-1-linux64-5cee1f4.tar.zst</string> <string>https://github.com/secondlife/3p-mikktspace/releases/download/v2-e967e1b/mikktspace-1-linux64-8756084692.tar.zst</string>
</map> </map>
<key>name</key> <key>name</key>
<string>linux64</string> <string>linux64</string>
</map> </map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>130b33a70bdb3a8a188376c6a91840bdb61380a8</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-mikktspace/releases/download/v2-e967e1b/mikktspace-1-windows64-8756084692.tar.zst</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map> </map>
<key>license</key>
<string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
<key>license_file</key>
<string>mikktspace.txt</string>
<key>copyright</key>
<string>Copyright (C) 2011 by Morten S. Mikkelsen</string>
<key>version</key> <key>version</key>
<string>1</string> <string>1</string>
<key>name</key>
<string>mikktspace</string>
<key>canonical_repo</key>
<string>https://bitbucket.org/lindenlab/3p-mikktspace</string>
<key>description</key>
<string>Mikktspace Tangent Generator</string>
</map> </map>
<key>minizip-ng</key> <key>minizip-ng</key>
<map> <map>
@ -3175,6 +3175,46 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>description</key> <key>description</key>
<string>zlib data compression library for the next generation systems</string> <string>zlib data compression library for the next generation systems</string>
</map> </map>
<key>tinyexr</key>
<map>
<key>platforms</key>
<map>
<key>common</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>8278a2368136cb12319ca00e7aceb2829bf3ebd8</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-tinyexr/releases/download/v1.0.8-ba4bc64/tinyexr-v1.0.8-common-9373975608.tar.zst</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>license</key>
<string>3-clause BSD</string>
<key>license_file</key>
<string>LICENSES/tinyexr_license.txt</string>
<key>copyright</key>
<string>Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors.</string>
<key>version</key>
<string>v1.0.8</string>
<key>name</key>
<string>tinyexr</string>
<key>vcs_branch</key>
<string>dependabot/github_actions/secondlife/action-autobuild-4</string>
<key>vcs_revision</key>
<string>4dc4d1d90d82a22843e2adf5130f9ecb5ee5769e</string>
<key>vcs_url</key>
<string>https://github.com/secondlife/3p-tinyexr</string>
<key>description</key>
<string>tinyexr import library</string>
<key>source_type</key>
<string>git</string>
</map>
</map> </map>
<key>package_description</key> <key>package_description</key>
<map> <map>

View File

@ -248,6 +248,7 @@ Ansariel Hiller
SL-4126 SL-4126
SL-20224 SL-20224
SL-20524 SL-20524
secondlife/viewer#1051
Aralara Rajal Aralara Rajal
Arare Chantilly Arare Chantilly
CHUIBUG-191 CHUIBUG-191

View File

@ -0,0 +1,16 @@
The Setting RenderMaxTextureResolution controls the maximum resolution of non-boosted textures as displayed by the viewer.
Valid values are 512-2048 (clamped in C++).
![image](https://github.com/secondlife/viewer/assets/23218274/d0f889fc-8135-41d2-9d83-871ad4eebed5)
![image](https://github.com/secondlife/viewer/assets/23218274/19950828-7eb1-4bb2-85d7-f35c63b34294)
![image](https://github.com/secondlife/viewer/assets/23218274/249afc83-4de6-488d-a05e-4877d08573b1)
Test Asset available on beta grid:
Object: 'Damaged Helmet', AssetID 0623e759-11b5-746c-a75e-7ba1caa6eb0e

View File

@ -0,0 +1,21 @@
A resident may swap out their sky for an EXR format HDRI for the purposes of previewing how their object would render in Second Life in an environment that matches the supplied HDRI. This should aid in matching inworld lighting with external tools so artists can know if their content has imported properly.
To load an HDRI, click Develop->Render Tests->HDRI Preview:
![image](https://github.com/secondlife/viewer/assets/23218274/fbdeab5f-dc1f-4406-be19-0c9ee7437b3f)
Choose an EXR image. A library of publicly available HDRIs can be found here: https://polyhaven.com/hdris
The Personal Lighting floater will open, and the sky will be replaced with the HDRI you chose. Reflection Probes will reset, and the scene will be illuminated by the HDRI.
Three debug settings affect how the HDRI is displayed:
RenderHDRIExposure - Exposure adjustment of HDRI when previewing an HDRI. Units are EV. Sane values would be -10 to 10.
RenderHDRIRotation - Rotation (in degrees) of environment when previewing an HDRI.
RenderHDRISplitScreen - What percentage of screen to render using HDRI vs EEP sky.
Exposure and Rotation should behave similarly to the rotation and exposure controls in Substance Painter.
Split Screen can be used to display an EEP sky side-by-side with an HDRI sky to aid in authoring an EEP sky that matches an HDRI sky. It is currently expected that EEP sun disc, moon, clouds, and stars do not render when previewing an HDRI, but that may change in the future.

View File

@ -0,0 +1,83 @@
# Material Preview
## Overview
Material preview is a UI feature which displays a lit spherical preview of a PBR material. It can be found in the following UIs:
- The material picker swatch
- In the build floater, in the Texture tab, when applying a PBR material
- (If the feature is enabled) In the Region/Estate floater, in the Terrain tab, when applying PBR materials to terrain
- In the floater to select a material from inventory, which can be opened by clicking the material picker swatch
## Known Issues
These are known issues that the current implementation of this feature does not address:
- The material preview in the build floater is a preview of the base material ID only, and ignores other properties on the prim face like material overrides (https://github.com/secondlife/viewer/issues/865)
- Alpha mask previews as alpha blend (https://github.com/secondlife/viewer/issues/866)
- Double-sided previews as single-sided (https://github.com/secondlife/viewer/issues/867)
- Material preview inherits some of its lighting from the current environment, and reflections from the default reflection probe (https://github.com/secondlife/viewer/issues/868)
## General Regression Testing
- Check that the material preview swatch looks OK with different materials selected
- Check that the material preview swatch runs reasonably well on different systems, especially when the select material from inventory floater is also open
- In particular: AMD, MacOS, minimum spec machines
- Watch out for regressions in rendering caused by opening a floater with a material preview swatch
## Bug Fixes
### Disappearing Objects Fix Test
This test is recommended for verifying that https://github.com/secondlife/viewer-issues/issues/72 is fixed.
#### Symptoms
When the bug occurs, one or more of following types of objects could randomly disappear in the world, permanently until relog:
- Objects
- Water level in current region
- Adjacent region/void water
Note: Disappearing objects in reflections have a different root cause and are not covered by the fix.
#### Bug Reproduction Steps
Verify the disappearing objects bug does not reproduce, given the following steps:
- Runtime prerequisites: Material preview swatch may not be available in your viewer or region if this feature is still behind a feature flag. It is safe to enable this feature manually by setting, "UIPreviewMaterial" to True in the advanced settings. The setting will persist for the current session.
- Region prerequisites: Unknown, but a region with lots of objects in it seems to increase repro rate. The following locations have been known to easily reproduce the bug, as of 2024-02-16:
- http://maps.secondlife.com/secondlife/LindenWorld%20B/161/75/47
- [secondlife://Aditi/secondlife/Rumpus%20Room%202048/128/128/24](secondlife://Aditi/secondlife/Rumpus%20Room%202048/128/128/24)
- Right click an object and select, "Edit item"
- Go to texture tab, select PBR Metallic Roughness from dropdown, and click the button to select material from inventory
- Ensure "Apply now" is checked in the inventory selection floater
- Alternate between different materials from the inventory selection floater
- Look around the world and check for permanently disappeared objects.
### Dynamic Exposure Influence Fix Test
This test is recommended for verifying that https://github.com/secondlife/viewer-issues/issues/72 is fixed.
#### Symptoms
Dynamic exposure in the world could be influenced by the material preview being displayed. If a material preview was being generated in a given frame, then, depending on the current environment, the user would observe an unpleasant flashing effect in the environment:
- The world view could suddenly get darker and then fade back to normal exposure levels
- The world view could suddenly get brighter and then fade back to normal exposure levels
#### Bug Reproduction Steps
Verify the dynamic exposure influence bug does not reproduce. Test using a few environment presets such as Default Midday, Sunset, and Midnight.
- Right click an object and select, "Edit item"
- Go to texture tab, select PBR Metallic Roughness from dropdown, and click the button to select material from inventory
- Alternate between different materials from the inventory selection floater
#### Regression Testing
Dynamic exposure in the world should continue to work correctly. In particular:
- Exposure should fade gradually from high exposure to low exposure and back as needed
- Exposure should decrease in brighter environments
- Exposure should increase in darker environments

View File

@ -0,0 +1,37 @@
# PBR Terrain Appearance
## Tiling
The southwest corner of a region with PBR materials should exactly match up with the bottom left corner of the material texture(s).
If two adjacent regions have the same PBR terrain settings, then:
- There should not be seams between the two regions at their shared border
- The ground should not suddenly slide beneath the avatar when moving between regions (except due to movement of the avatar, which is not covered by this test plan)
## Feature Gating
PBR terrain should have lower detail on lower graphics settings. PBR terrain will also not show emissive textures on some machines (like Macs) which do not support more than 16 textures.
### Triplanar Mapping
Triplanar mapping improves the texture repeats on the sides of terrain slopes.
Availability of Triplanar mapping:
- Medium-High and below: No triplanar mapping
- High and above: Triplanar mapping
### PBR Textures
At the highest graphics support level, PBR terrain supports all PBR textures.
Availability of PBR textures varies by machine and graphics setting:
- Low: Base color only (looks similar to texture terrain)
- Medium-Low, and machines that do not support greater than 16 textures such as Macs: All PBR textures enabled except emissive textures.
- Medium: All PBR textures enabled
### PBR Alpha
PBR terrain does not support materials with alpha blend or double-sided. In addition, the viewer does not make any guarantees about what will render behind the terrain if alpha is used.

View File

@ -0,0 +1,76 @@
# PBR Terrain Composition
## Feature Availability
PBR Terrain is visible for all viewers with the PBR Terrain feature, regardless of if the feature flag is enabled.
There is only one set of four asset IDs applied to the terrain. In other words, unlike PBR materials on prims, there is no fallback texture set for viewers that do not support PBR terrain. Viewers without support will view terrain as blank (solid grey or white).
## Editing Terrain Composition
All tests in this section assume the PBR terrain feature flag is enabled, and that the user has appropriate permissions to modify the terrain textures.
### Feature Availability
On the client, the advanced setting `RenderTerrainPBREnabled` is the PBR terrain feature flag.
The PBR terrain feature flag should be set automatically when logging in/teleporting to a new region.
- The flag should be enabled on regions where the PBR terrain feature is enabled
- Otherwise the flag should be disabled
When the PBR terrain feature flag is disabled:
- The "PBR Metallic Roughness" checkbox should not be visible
- The user should not be able to apply PBR terrain to the region, only textures.
When the PBR terrain feature flag is enabled:
- The "PBR Metallic Roughness" checkbox should be visible
- The user should be able to apply PBR terrain or textures to the region, depending on if the "PBR Metallic Roughness" checkbox is checked.
### Current Composition Type
When the Region/Estate floater is opened to the terrain Tab, the current terrain should be shown in the four swatches, and the "PBR Metallic Roughness" checkbox should be checked or unchecked accordingly.
- If it is texture terrain, the "PBR Metallic Roughness" checkbox should be unchecked, and the floater should display the four textures applied to the terrain.
- If it is material terrain, the "PBR Metallic Roughness" checkbox should be checked, and the floater should display the four materials applied to the terrain.
In addition, where possible, textual labels and descriptions in the tab should make sense given the current value of the "PBR Metallic Roughness" checkbox. If the checkbox is unchecked, the labels should refer to textures. If the checkbox is checked, the labels should refer to materials.
### Toggling Composition Type
When toggling the "PBR Metallic Roughness" checkbox to the opposite value, which does not correspond to the current terrain type, one of the following sets of four terrain swatches will be displayed:
- The default textures/materials
- For textures, this is the default terrain texture set
- For materials, this is all blank materials, but this is subject to change
- The previously applied texture/material set
- History is available on a best-effort basis only. In particular, the history does not persist on viewer restart.
When toggling back the "PBR Metallic Roughness" checkbox to the original value, assuming nothing else has changed, then the current terrain should be shown in the four swatches again.
### Saving Composition
A user with appropriate permissions can change and save the textures or materials to the terrain. If the "PBR Metallic Roughness" checkbox is checked, the user applies materials, otherwise the user applies textures.
The user should not be allowed to set the texture or material swatches to null.
Saving may fail for the following reasons:
- A terrain or material texture is invalid
- A terrain texture is greater than the max texture upload resolution
If saving the terrain fails for any reason, the terrain should not be updated.
Unlike a viewer without PBR terrain support, the new viewer will no longer treat textures with alpha channels as invalid.
## Graphics Features
Texture terrain with transparency is not permitted to be applied in the viewer.
See [PBR Terrain Appearance](./pbr_terrain_appearance.md) for supported PBR terrain features.
## Minimap
The minimap should display the terrain with appropriate textures and colors.

View File

@ -0,0 +1,29 @@
# Terrain Loading
## Behavior overview
- Texture terrain should load if textures are applied to the region, and no PBR Metallic Roughness materials are applied.
- PBR terrain should load if PBR materials are applied to the region, even if the RenderTerrainPBREnabled feature flag is disabled in debug settings. This setting only disables the display of PBR materials in the Region / Estate > Terrain UI.
- Related subsystem: A change to the PBR terrain loading system may affect the texture terrain loading system and vice-versa
- Related subsystem: Minimap should load if terrain loads
- They may not finish loading at the same time
## Implementation details
This section is provided mainly for clarification of how the terrain loading system works.
The simulator sends 4 terrain composition UUIDs to the viewer for the region. The viewer does not know ahead-of-time if the terrain composition uses textures or materials. Therefore, to expedite terrain loading, the viewer makes up to 8 "top-level" asset requests simultaneously:
- Up to 4 texture asset requests, one for each UUID
- Up to 4 material asset requests, one for each UUID
It is therefore expected that half of these asset lookups will fail.
The viewer inspects the load success of these top-level assets to make the binary decision of whether to render all 4 texture assets or all 4 material assets. This determines the choice of composition for terrain both in-world and on the minimap.
The minimap also attempts to wait for textures to partially load before it can render a tile for a given region:
- When rendering texture terrain, the minimap attempts to wait for top-level texture assets to partially load
- When rendering PBR material terrain, the minimap attempts to wait for any base color/emissive textures in the materials to partially load, if they are present
We don't make guarantees that the minimap tile will render for the region if any aforementioned required textures/materials fail to sufficiently load. However, the minimap may make a best-effort attempt to render the region by ignoring or replacing data.

View File

@ -55,6 +55,8 @@ set(cmake_SOURCE_FILES
PulseAudio.cmake PulseAudio.cmake
Python.cmake Python.cmake
TemplateCheck.cmake TemplateCheck.cmake
TinyEXR.cmake
TinyGLTF.cmake
Tut.cmake Tut.cmake
UI.cmake UI.cmake
UnixInstall.cmake UnixInstall.cmake

View File

@ -0,0 +1,7 @@
# -*- cmake -*-
include(Prebuilt)
use_prebuilt_binary(tinyexr)
set(TINYEXR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinyexr)

View File

@ -484,21 +484,69 @@ void LLAvatarAppearance::computeBodySize()
mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale();
mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition();
F32 old_height = mBodySize.mV[VZ]; LLVector3 pelvis_scale = mPelvisp->getScale();
// some of the joints have not been cached
LLVector3 skull = mSkullp->getPosition();
//LLVector3 skull_scale = mSkullp->getScale();
LLVector3 neck = mNeckp->getPosition();
LLVector3 neck_scale = mNeckp->getScale();
LLVector3 chest = mChestp->getPosition();
LLVector3 chest_scale = mChestp->getScale();
// the rest of the joints have been cached
LLVector3 head = mHeadp->getPosition();
LLVector3 head_scale = mHeadp->getScale();
LLVector3 torso = mTorsop->getPosition();
LLVector3 torso_scale = mTorsop->getScale();
LLVector3 hip = mHipLeftp->getPosition();
LLVector3 hip_scale = mHipLeftp->getScale();
LLVector3 knee = mKneeLeftp->getPosition();
LLVector3 knee_scale = mKneeLeftp->getScale();
LLVector3 ankle = mAnkleLeftp->getPosition();
LLVector3 ankle_scale = mAnkleLeftp->getScale();
LLVector3 foot = mFootLeftp->getPosition();
F32 old_offset = mAvatarOffset.mV[VZ]; F32 old_offset = mAvatarOffset.mV[VZ];
// TODO: Measure the real depth and width
mPelvisToFoot = computePelvisToFoot();
F32 new_height = computeBodyHeight();
mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height);
// [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8) // [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8)
F32 new_offset = getAvatarOffset(); mAvatarOffset.mV[VZ] = getAvatarOffset();
// [/RLVa:KB] // [/RLVa:KB]
// F32 new_offset = getVisualParamWeight(AVATAR_HOVER); // mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER);
mAvatarOffset.set(0, 0, new_offset);
if (mBodySize.mV[VZ] != old_height || new_offset != old_offset) mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] -
knee.mV[VZ] * hip_scale.mV[VZ] -
ankle.mV[VZ] * knee_scale.mV[VZ] -
foot.mV[VZ] * ankle_scale.mV[VZ];
LLVector3 new_body_size;
new_body_size.mV[VZ] = mPelvisToFoot +
// the sqrt(2) correction below is an approximate
// correction to get to the top of the head
F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
head.mV[VZ] * neck_scale.mV[VZ] +
neck.mV[VZ] * chest_scale.mV[VZ] +
chest.mV[VZ] * torso_scale.mV[VZ] +
torso.mV[VZ] * pelvis_scale.mV[VZ];
// TODO -- measure the real depth and width
new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
mAvatarOffset.mV[VX] = 0.0f;
mAvatarOffset.mV[VY] = 0.0f;
if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ])
{ {
mBodySize = new_body_size;
// <FS:Ansariel> [Legacy Bake] // <FS:Ansariel> [Legacy Bake]
bodySizeChanged(); bodySizeChanged();
@ -506,29 +554,6 @@ void LLAvatarAppearance::computeBodySize()
} }
} }
F32 LLAvatarAppearance::computeBodyHeight()
{
F32 result = mPelvisToFoot +
// all these relative positions usually are positive
mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] +
mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] +
mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] +
mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] +
mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2;
return result;
}
F32 LLAvatarAppearance::computePelvisToFoot()
{
F32 result =
// all these relative positions usually are negative
mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] +
mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] +
mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] +
mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2;
return -result;
}
// [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8) // [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8)
F32 LLAvatarAppearance::getAvatarOffset() /*const*/ F32 LLAvatarAppearance::getAvatarOffset() /*const*/
{ {

View File

@ -153,8 +153,6 @@ public:
void compareJointStateMaps(joint_state_map_t& last_state, void compareJointStateMaps(joint_state_map_t& last_state,
joint_state_map_t& curr_state); joint_state_map_t& curr_state);
void computeBodySize(); void computeBodySize();
F32 computeBodyHeight();
F32 computePelvisToFoot();
public: public:
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t; typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;

View File

@ -89,3 +89,4 @@ const LLUUID IMG_USE_BAKED_AUX1 ("9742065b-19b5-297c-858a-29711d539043");
const LLUUID IMG_USE_BAKED_AUX2 ("03642e83-2bd1-4eb9-34b4-4c47ed586d2d"); const LLUUID IMG_USE_BAKED_AUX2 ("03642e83-2bd1-4eb9-34b4-4c47ed586d2d");
const LLUUID IMG_USE_BAKED_AUX3 ("edd51b77-fc10-ce7a-4b3d-011dfc349e4f"); const LLUUID IMG_USE_BAKED_AUX3 ("edd51b77-fc10-ce7a-4b3d-011dfc349e4f");
const LLUUID BLANK_MATERIAL_ASSET_ID ("968cbad0-4dad-d64e-71b5-72bf13ad051a");

View File

@ -240,6 +240,8 @@ LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_SPECULAR;
LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_NORMAL; LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_NORMAL;
LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL; LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL;
LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID;
// radius within which a chat message is fully audible // radius within which a chat message is fully audible
const F32 CHAT_NORMAL_RADIUS = 20.f; const F32 CHAT_NORMAL_RADIUS = 20.f;

View File

@ -37,8 +37,8 @@ template <class Object> class LLStrider
}; };
U32 mSkip; U32 mSkip;
public: public:
LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); } LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); }
LLStrider(Object* first) { mObjectp = first; mSkip = sizeof(Object); }
~LLStrider() { } ~LLStrider() { }
const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;} const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}

View File

@ -31,6 +31,7 @@
#include "llmath.h" #include "llmath.h"
#include "v4coloru.h" #include "v4coloru.h"
#include "v3color.h"
#include "llimagebmp.h" #include "llimagebmp.h"
#include "llimagetga.h" #include "llimagetga.h"
@ -1022,6 +1023,28 @@ void LLImageRaw::verticalFlip()
} }
bool LLImageRaw::checkHasTransparentPixels()
{
if (getComponents() != 4)
{
return false;
}
U8* data = getData();
U32 pixels = getWidth() * getHeight();
// check alpha channel for all 255
for (U32 i = 0; i < pixels; ++i)
{
if (data[i * 4 + 3] != 255)
{
return true;
}
}
return false;
}
bool LLImageRaw::optimizeAwayAlpha() bool LLImageRaw::optimizeAwayAlpha()
{ {
LLImageDataLock lock(this); LLImageDataLock lock(this);
@ -1061,6 +1084,34 @@ bool LLImageRaw::optimizeAwayAlpha()
return false; return false;
} }
bool LLImageRaw::makeAlpha()
{
if (getComponents() == 3)
{
U8* data = getData();
U32 pixels = getWidth() * getHeight();
// alpha channel doesn't exist, make a new copy of data with alpha channel
U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 4);
for (U32 i = 0; i < pixels; ++i)
{
U32 di = i * 4;
U32 si = i * 3;
for (U32 j = 0; j < 3; ++j)
{
new_data[di+j] = data[si+j];
}
}
setDataAndSize(new_data, getWidth(), getHeight(), 3);
return true;
}
return false;
}
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image) void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
{ {
LLImageDataLock lock(this); LLImageDataLock lock(this);
@ -1156,7 +1207,7 @@ void LLImageRaw::composite( const LLImageRaw* src )
} }
// <FS:Beq> These assertions are nonsense. // <FS:Beq> These assertions are nonsense.
// llassert(3 == src->getComponents()); // llassert((3 == src->getComponents()) || (4 == src->getComponents()));
// llassert(3 == dst->getComponents()); // llassert(3 == dst->getComponents());
// </FS:Beq> // </FS:Beq>
if( 3 == dst->getComponents() ) if( 3 == dst->getComponents() )
@ -1345,6 +1396,30 @@ void LLImageRaw::fill( const LLColor4U& color )
} }
} }
void LLImageRaw::tint( const LLColor3& color )
{
llassert( (3 == getComponents()) || (4 == getComponents()) );
if (isBufferInvalid())
{
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
return;
}
S32 pixels = getWidth() * getHeight();
const S32 components = getComponents();
U8* data = getData();
for( S32 i = 0; i < pixels; i++ )
{
const float c0 = data[0] * color.mV[0];
const float c1 = data[1] * color.mV[1];
const float c2 = data[2] * color.mV[2];
data[0] = llclamp((U8)c0, 0, 255);
data[1] = llclamp((U8)c1, 0, 255);
data[2] = llclamp((U8)c2, 0, 255);
data += components;
}
}
LLPointer<LLImageRaw> LLImageRaw::duplicate() LLPointer<LLImageRaw> LLImageRaw::duplicate()
{ {
if(getNumRefs() < 2) if(getNumRefs() < 2)
@ -1895,6 +1970,73 @@ void LLImageRaw::compositeRowScaled4onto3( const U8* in, U8* out, S32 in_pixel_l
} }
} }
void LLImageRaw::addEmissive(LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
if (!validateSrcAndDst(__FUNCTION__, src, dst))
{
return;
}
llassert((3 == src->getComponents()) || (4 == src->getComponents()));
llassert(3 == dst->getComponents());
if( 3 == dst->getComponents() )
{
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
addEmissiveUnscaled(src);
}
else
{
addEmissiveScaled(src);
}
}
}
void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
llassert((3 == src->getComponents()) || (4 == src->getComponents()));
llassert((3 == dst->getComponents()) || (4 == dst->getComponents()));
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
U8* const src_data = src->getData();
U8* const dst_data = dst->getData();
for(S32 y = 0; y < dst->getHeight(); ++y)
{
const S32 src_row_offset = src->getComponents() * src->getWidth() * y;
const S32 dst_row_offset = dst->getComponents() * dst->getWidth() * y;
for (S32 x = 0; x < dst->getWidth(); ++x)
{
const S32 src_offset = src_row_offset + (x * src->getComponents());
const S32 dst_offset = dst_row_offset + (x * dst->getComponents());
U8* const src_pixel = src_data + src_offset;
U8* const dst_pixel = dst_data + dst_offset;
dst_pixel[0] = llmin(255, dst_pixel[0] + src_pixel[0]);
dst_pixel[1] = llmin(255, dst_pixel[1] + src_pixel[1]);
dst_pixel[2] = llmin(255, dst_pixel[2] + src_pixel[2]);
}
}
}
void LLImageRaw::addEmissiveScaled(LLImageRaw* src)
{
LLImageRaw* dst = this; // Just for clarity.
llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
LLImageRaw temp(dst->getWidth(), dst->getHeight(), dst->getComponents());
llassert_always(temp.getDataSize() > 0);
temp.copyScaled(src);
dst->addEmissiveUnscaled(&temp);
}
// static // static
bool LLImageRaw::validateSrcAndDst(std::string func, const LLImageRaw* src, const LLImageRaw* dst) bool LLImageRaw::validateSrcAndDst(std::string func, const LLImageRaw* src, const LLImageRaw* dst)
{ {

View File

@ -33,7 +33,7 @@
#include "lltrace.h" #include "lltrace.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
const S32 MAX_IMAGE_MIP = 11; // 2048x2048 const S32 MAX_IMAGE_MIP = 12; // 4096x4096
// *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number // *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number
// of levels is read from the header's file, not inferred from its size. // of levels is read from the header's file, not inferred from its size.
@ -44,7 +44,7 @@ const S32 MAX_DISCARD_LEVEL = 5;
// and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL. // and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL.
const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec
const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is) const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is)
const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_SIZE const S32 MAX_PRECINCT_SIZE = 4096; // No reason to be bigger than MAX_IMAGE_SIZE
const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE
const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks
const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec
@ -52,11 +52,11 @@ const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (
const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit) const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit)
const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2 const S32 MIN_IMAGE_SIZE = (1<<MIN_IMAGE_MIP); // 4, only used for expand/contract power of 2
const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 2048 const S32 MAX_IMAGE_SIZE = (1<<MAX_IMAGE_MIP); // 4096
const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE; const S32 MIN_IMAGE_AREA = MIN_IMAGE_SIZE * MIN_IMAGE_SIZE;
const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE; const S32 MAX_IMAGE_AREA = MAX_IMAGE_SIZE * MAX_IMAGE_SIZE;
const S32 MAX_IMAGE_COMPONENTS = 8; const S32 MAX_IMAGE_COMPONENTS = 8;
const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //2048 * 2048 * 8 = 16 MB const S32 MAX_IMAGE_DATA_SIZE = MAX_IMAGE_AREA * MAX_IMAGE_COMPONENTS; //4096 * 4096 * 8 = 128 MB
// Note! These CANNOT be changed without modifying simulator code // Note! These CANNOT be changed without modifying simulator code
// *TODO: change both to 1024 when SIM texture fetching is deprecated // *TODO: change both to 1024 when SIM texture fetching is deprecated
@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496;
class LLImageFormatted; class LLImageFormatted;
class LLImageRaw; class LLImageRaw;
class LLColor4U; class LLColor4U;
class LLColor3;
typedef enum e_image_codec typedef enum e_image_codec
{ {
@ -232,9 +233,13 @@ public:
void verticalFlip(); void verticalFlip();
// Returns true if the image is not fully opaque
bool checkHasTransparentPixels();
// if the alpha channel is all 100% opaque, delete it // if the alpha channel is all 100% opaque, delete it
// returns true if alpha channel was deleted // returns true if alpha channel was deleted
bool optimizeAwayAlpha(); bool optimizeAwayAlpha();
// Create an alpha channel if this image doesn't have one
bool makeAlpha();
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
@ -248,6 +253,9 @@ public:
// Fill the buffer with a constant color // Fill the buffer with a constant color
void fill( const LLColor4U& color ); void fill( const LLColor4U& color );
// Multiply this raw image by the given color
void tint( const LLColor3& color );
// Copy operations // Copy operations
//duplicate this raw image if refCount > 1. //duplicate this raw image if refCount > 1.
@ -279,6 +287,12 @@ public:
// Src and dst can be any size. Src and dst can each have 3 or 4 components. // Src and dst can be any size. Src and dst can each have 3 or 4 components.
void composite( const LLImageRaw* src ); void composite( const LLImageRaw* src );
// Emissive operations used by minimap
// Roughly emulates GLTF emissive texture, but is not GLTF-compliant
// *TODO: Remove in favor of shader
void addEmissive(LLImageRaw* src);
void addEmissiveScaled(LLImageRaw* src);
void addEmissiveUnscaled(LLImageRaw* src);
protected: protected:
// Src and dst can be any size. Src has 4 components. Dst has 3 components. // Src and dst can be any size. Src has 4 components. Dst has 3 components.
void compositeScaled4onto3( const LLImageRaw* src ); void compositeScaled4onto3( const LLImageRaw* src );

View File

@ -451,7 +451,7 @@ bool LLImageDXT::convertToDXR()
if (!newdata) if (!newdata)
{ {
LLError::LLUserWarningMsg::showOutOfMemory(); LLError::LLUserWarningMsg::showOutOfMemory();
LL_ERRS() << "Out of memory in LLImageDXT::convertToDXR()" << LL_ENDL; LL_WARNS() << "Out of memory in LLImageDXT::convertToDXR()" << LL_ENDL;
return false; return false;
} }
llassert(total_bytes > 0); llassert(total_bytes > 0);

View File

@ -411,7 +411,6 @@ LLSettingsSky::LLSettingsSky(const LLSD &data) :
mNextRainbowTextureId(), mNextRainbowTextureId(),
mNextHaloTextureId() mNextHaloTextureId()
{ {
mCanAutoAdjust = !data.has(SETTING_REFLECTION_PROBE_AMBIANCE);
} }
LLSettingsSky::LLSettingsSky(): LLSettingsSky::LLSettingsSky():
@ -434,8 +433,6 @@ void LLSettingsSky::replaceSettings(LLSD settings)
mNextBloomTextureId.setNull(); mNextBloomTextureId.setNull();
mNextRainbowTextureId.setNull(); mNextRainbowTextureId.setNull();
mNextHaloTextureId.setNull(); mNextHaloTextureId.setNull();
mCanAutoAdjust = !settings.has(SETTING_REFLECTION_PROBE_AMBIANCE);
} }
void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother)
@ -448,7 +445,6 @@ void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother)
mNextBloomTextureId = pother->mNextBloomTextureId; mNextBloomTextureId = pother->mNextBloomTextureId;
mNextRainbowTextureId = pother->mNextRainbowTextureId; mNextRainbowTextureId = pother->mNextRainbowTextureId;
mNextHaloTextureId = pother->mNextHaloTextureId; mNextHaloTextureId = pother->mNextHaloTextureId;
mCanAutoAdjust = pother->mCanAutoAdjust;
} }
void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf)
@ -1150,7 +1146,6 @@ void LLSettingsSky::setSkyIceLevel(F32 ice_level)
void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance) void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance)
{ {
mCanAutoAdjust = false; // we've now touched this sky in a "new" way, it can no longer auto adjust
setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance); setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance);
} }
@ -1452,24 +1447,6 @@ F32 LLSettingsSky::getReflectionProbeAmbiance(bool auto_adjust) const
return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal(); return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal();
} }
F32 LLSettingsSky::getTotalReflectionProbeAmbiance(F32 cloud_shadow_scale, bool auto_adjust) const
{
#if 0
// feed cloud shadow back into reflection probe ambiance to mimic pre-reflection-probe behavior
// without brightening dark/interior spaces
F32 probe_ambiance = getReflectionProbeAmbiance(auto_adjust);
if (probe_ambiance > 0.f && probe_ambiance < 1.f)
{
probe_ambiance += (1.f - probe_ambiance) * getCloudShadow() * cloud_shadow_scale;
}
return probe_ambiance;
#else
return getReflectionProbeAmbiance(auto_adjust);
#endif
}
F32 LLSettingsSky::getSkyBottomRadius() const F32 LLSettingsSky::getSkyBottomRadius() const
{ {
return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal(); return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal();
@ -1814,3 +1791,8 @@ LLUUID LLSettingsSky::getNextBloomTextureId() const
return mNextBloomTextureId; return mNextBloomTextureId;
} }
// if true, this sky is a candidate for auto-adjustment
bool LLSettingsSky::canAutoAdjust() const
{
return !mSettings.has(SETTING_REFLECTION_PROBE_AMBIANCE);
}

View File

@ -139,10 +139,6 @@ public:
// auto_adjust - if true and canAutoAdjust() is true, return 1.0 // auto_adjust - if true and canAutoAdjust() is true, return 1.0
F32 getReflectionProbeAmbiance(bool auto_adjust = false) const; F32 getReflectionProbeAmbiance(bool auto_adjust = false) const;
// get the probe ambiance setting to use for rendering (adjusted by cloud shadow, aka cloud coverage)
// auto_adjust - if true and canAutoAdjust() is true, return 1.0
F32 getTotalReflectionProbeAmbiance(F32 cloud_shadow_scale, bool auto_adjust = false) const;
// Return first (only) profile layer represented in LLSD // Return first (only) profile layer represented in LLSD
LLSD getRayleighConfig() const; LLSD getRayleighConfig() const;
LLSD getMieConfig() const; LLSD getMieConfig() const;
@ -340,7 +336,7 @@ public:
virtual void updateSettings() SETTINGS_OVERRIDE; virtual void updateSettings() SETTINGS_OVERRIDE;
// if true, this sky is a candidate for auto-adjustment // if true, this sky is a candidate for auto-adjustment
bool canAutoAdjust() const { return mCanAutoAdjust; } bool canAutoAdjust() const;
protected: protected:
static const std::string SETTING_LEGACY_EAST_ANGLE; static const std::string SETTING_LEGACY_EAST_ANGLE;
@ -385,9 +381,6 @@ private:
mutable LLColor4 mTotalAmbient; mutable LLColor4 mTotalAmbient;
mutable LLColor4 mHazeColor; mutable LLColor4 mHazeColor;
// if true, this sky is a candidate for auto adjustment
bool mCanAutoAdjust = true;
typedef std::map<std::string, S32> mapNameToUniformId_t; typedef std::map<std::string, S32> mapNameToUniformId_t;
static mapNameToUniformId_t sNameToUniformMapping; static mapNameToUniformId_t sNameToUniformMapping;

View File

@ -65,7 +65,6 @@ class LLCamera
: public LLCoordFrame : public LLCoordFrame
{ {
public: public:
LLCamera(const LLCamera& rhs) LLCamera(const LLCamera& rhs)
{ {
*this = rhs; *this = rhs;

View File

@ -56,6 +56,16 @@ public:
return (F32*)&mMatrix; return (F32*)&mMatrix;
} }
inline LLMatrix4& asMatrix4()
{
return *(LLMatrix4*)this;
}
inline const LLMatrix4& asMatrix4() const
{
return *(LLMatrix4*)this;
}
inline void clear() inline void clear()
{ {
mMatrix[0].clear(); mMatrix[0].clear();

View File

@ -45,16 +45,15 @@
#include "llmatrix3a.h" #include "llmatrix3a.h"
#include "lloctree.h" #include "lloctree.h"
#include "llvolume.h" #include "llvolume.h"
#include "llvolumeoctree.h"
#include "llstl.h" #include "llstl.h"
#include "llsdserialize.h" #include "llsdserialize.h"
#include "llvector4a.h" #include "llvector4a.h"
#include "llmatrix4a.h" #include "llmatrix4a.h"
#include "llmeshoptimizer.h" #include "llmeshoptimizer.h"
#include "lltimer.h" #include "lltimer.h"
#include "llvolumeoctree.h"
#include "mikktspace/mikktspace.h" #include "mikktspace/mikktspace.hh"
#include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file
#include "meshoptimizer/meshoptimizer.h" #include "meshoptimizer/meshoptimizer.h"
@ -5512,14 +5511,58 @@ struct MikktData
n[i].normalize(); n[i].normalize();
tc[i].set(face->mTexCoords[idx]); tc[i].set(face->mTexCoords[idx]);
if (idx >= face->mNumVertices)
{
// invalid index
// replace with a valid index to avoid crashes
idx = face->mNumVertices - 1;
face->mIndices[i] = idx;
// Needs better logging
LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL;
}
if (face->mWeights) if (face->mWeights)
{ {
w[i].set(face->mWeights[idx].getF32ptr()); w[i].set(face->mWeights[idx].getF32ptr());
} }
} }
} }
};
uint32_t GetNumFaces()
{
return uint32_t(face->mNumIndices / 3);
}
uint32_t GetNumVerticesOfFace(const uint32_t face_num)
{
return 3;
}
mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num)
{
F32* v = p[face_num * 3 + vert_num].mV;
return mikk::float3(v);
}
mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)
{
F32* uv = tc[face_num * 3 + vert_num].mV;
return mikk::float3(uv[0], uv[1], 1.0f);
}
mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num)
{
F32* normal = n[face_num * 3 + vert_num].mV;
return mikk::float3(normal);
}
void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation)
{
S32 i = face_num * 3 + vert_num;
t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f);
}
};
bool LLVolumeFace::cacheOptimize(bool gen_tangents) bool LLVolumeFace::cacheOptimize(bool gen_tangents)
{ //optimize for vertex cache according to Forsyth method: { //optimize for vertex cache according to Forsyth method:
@ -5531,62 +5574,9 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
{ // generate mikkt space tangents before cache optimizing since the index buffer may change { // generate mikkt space tangents before cache optimizing since the index buffer may change
// a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh
// and is executed on a background thread // and is executed on a background thread
SMikkTSpaceInterface ms;
ms.m_getNumFaces = [](const SMikkTSpaceContext* pContext)
{
MikktData* data = (MikktData*)pContext->m_pUserData;
LLVolumeFace* face = data->face;
return face->mNumIndices / 3;
};
ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext* pContext, const int iFace)
{
return 3;
};
ms.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert)
{
MikktData* data = (MikktData*)pContext->m_pUserData;
F32* v = data->p[iFace * 3 + iVert].mV;
fvPosOut[0] = v[0];
fvPosOut[1] = v[1];
fvPosOut[2] = v[2];
};
ms.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert)
{
MikktData* data = (MikktData*)pContext->m_pUserData;
F32* n = data->n[iFace * 3 + iVert].mV;
fvNormOut[0] = n[0];
fvNormOut[1] = n[1];
fvNormOut[2] = n[2];
};
ms.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert)
{
MikktData* data = (MikktData*)pContext->m_pUserData;
F32* tc = data->tc[iFace * 3 + iVert].mV;
fvTexcOut[0] = tc[0];
fvTexcOut[1] = tc[1];
};
ms.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
{
MikktData* data = (MikktData*)pContext->m_pUserData;
S32 i = iFace * 3 + iVert;
data->t[i].set(fvTangent);
data->t[i].mV[3] = fSign;
};
ms.m_setTSpace = nullptr;
MikktData data(this); MikktData data(this);
mikk::Mikktspace ctx(data);
SMikkTSpaceContext ctx = { &ms, &data }; ctx.genTangSpace();
genTangSpaceDefault(&ctx);
//re-weld //re-weld
meshopt_Stream mos[] = meshopt_Stream mos[] =
@ -5607,9 +5597,6 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
if (vert_count < 65535 && vert_count != 0) if (vert_count < 65535 && vert_count != 0)
{ {
std::vector<U32> indices;
indices.resize(mNumIndices);
//copy results back into volume //copy results back into volume
resizeVertices(vert_count); resizeVertices(vert_count);
@ -5699,8 +5686,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
ND_OCTREE_LOG << "Creating octree with scale " << scaler << " mNumIndices " << mNumIndices << ND_OCTREE_LOG_END; ND_OCTREE_LOG << "Creating octree with scale " << scaler << " mNumIndices " << mNumIndices << ND_OCTREE_LOG_END;
llassert(mNumIndices % 3 == 0); llassert(mNumIndices % 3 == 0);
mOctree = new LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, NULL); mOctree = new LLVolumeOctree(center, size);
new LLVolumeOctreeListener(mOctree);
const U32 num_triangles = mNumIndices / 3; const U32 num_triangles = mNumIndices / 3;
// Initialize all the triangles we need // Initialize all the triangles we need
mOctreeTriangles = new LLVolumeTriangle[num_triangles]; mOctreeTriangles = new LLVolumeTriangle[num_triangles];
@ -5763,7 +5749,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
while (!mOctree->balance()) { } while (!mOctree->balance()) { }
//calculate AABB for each node //calculate AABB for each node
LLVolumeOctreeRebound rebound(this); LLVolumeOctreeRebound rebound;
rebound.traverse(mOctree); rebound.traverse(mOctree);
if (gDebugGL) if (gDebugGL)
@ -5776,12 +5762,12 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe
void LLVolumeFace::destroyOctree() void LLVolumeFace::destroyOctree()
{ {
delete mOctree; delete mOctree;
mOctree = NULL; mOctree = nullptr;
delete[] mOctreeTriangles; delete[] mOctreeTriangles;
mOctreeTriangles = NULL; mOctreeTriangles = nullptr;
} }
const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* LLVolumeFace::getOctree() const const LLVolumeOctree* LLVolumeFace::getOctree() const
{ {
return mOctree; return mOctree;
} }
@ -6496,9 +6482,6 @@ bool LLVolumeFace::createCap(LLVolume* volume, bool partial_build)
return true; return true;
} }
void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent);
void LLVolumeFace::createTangents() void LLVolumeFace::createTangents()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
@ -6516,7 +6499,7 @@ void LLVolumeFace::createTangents()
(*ptr++).clear(); (*ptr++).clear();
} }
CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents); LLCalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents);
//normalize normals //normalize normals
for (S32 i = 0; i < mNumVertices; i++) for (S32 i = 0; i < mNumVertices; i++)
@ -7244,7 +7227,7 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
} }
//adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html //adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME

View File

@ -41,6 +41,7 @@ template <class T, typename T_PTR> class LLOctreeNode;
class LLVolumeFace; class LLVolumeFace;
class LLVolume; class LLVolume;
class LLVolumeTriangle; class LLVolumeTriangle;
class LLVolumeOctree;
#include "lluuid.h" #include "lluuid.h"
#include "v4color.h" #include "v4color.h"
@ -916,7 +917,7 @@ public:
void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
void destroyOctree(); void destroyOctree();
// Get a reference to the octree, which may be null // Get a reference to the octree, which may be null
const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* getOctree() const; const LLVolumeOctree* getOctree() const;
enum enum
{ {
@ -990,7 +991,7 @@ public:
LLVector3 mNormalizedScale = LLVector3(1,1,1); LLVector3 mNormalizedScale = LLVector3(1,1,1);
private: private:
LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* mOctree; LLVolumeOctree* mOctree;
LLVolumeTriangle* mOctreeTriangles; LLVolumeTriangle* mOctreeTriangles;
bool createUnCutCubeCap(LLVolume* volume, bool partial_build = false); bool createUnCutCubeCap(LLVolume* volume, bool partial_build = false);
@ -1155,6 +1156,8 @@ private:
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent);
bool LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size); bool LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
bool LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); bool LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
bool LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); bool LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size);

View File

@ -91,15 +91,15 @@ void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode<LLVolumeTria
} }
LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
const LLVolumeFace* face, F32* closest_t, LLVolumeFace* face, F32* closest_t,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent)
: mFace(face), : mStart(start),
mStart(start),
mDir(dir), mDir(dir),
mIntersection(intersection), mIntersection(intersection),
mTexCoord(tex_coord), mTexCoord(tex_coord),
mNormal(normal), mNormal(normal),
mTangent(tangent), mTangent(tangent),
mFace(face),
mClosestT(closest_t), mClosestT(closest_t),
mHitFace(false) mHitFace(false)
{ {
@ -138,7 +138,7 @@ void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode<LLVolumeTriangle, LL
{ {
*mClosestT = t; *mClosestT = t;
mHitFace = true; mHitFace = true;
mHitTriangle = tri;
if (mIntersection != NULL) if (mIntersection != NULL)
{ {
LLVector4a intersect = mDir; LLVector4a intersect = mDir;

View File

@ -62,7 +62,7 @@ public:
LL_ALIGN_16(LLVector4a mPositionGroup); LL_ALIGN_16(LLVector4a mPositionGroup);
const LLVector4a* mV[3]; const LLVector4a* mV[3];
U16 mIndex[3]; U32 mIndex[3];
F32 mRadius; F32 mRadius;
mutable S32 mBinIndex; mutable S32 mBinIndex;
@ -112,7 +112,6 @@ public:
class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*> class LLOctreeTriangleRayIntersect : public LLOctreeTraveler<LLVolumeTriangle, LLVolumeTriangle*>
{ {
public: public:
const LLVolumeFace* mFace;
LLVector4a mStart; LLVector4a mStart;
LLVector4a mDir; LLVector4a mDir;
LLVector4a mEnd; LLVector4a mEnd;
@ -121,10 +120,13 @@ public:
LLVector4a* mNormal; LLVector4a* mNormal;
LLVector4a* mTangent; LLVector4a* mTangent;
F32* mClosestT; F32* mClosestT;
LLVolumeFace* mFace;
bool mHitFace; bool mHitFace;
const LLVolumeTriangle* mHitTriangle = nullptr;
LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir,
const LLVolumeFace* face, F32* closest_t, LLVolumeFace* face,
F32* closest_t,
LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent);
void traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node); void traverse(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* node);
@ -137,4 +139,91 @@ class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle, LLVolum
virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch); virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch);
}; };
class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst<LLVolumeTriangle, LLVolumeTriangle*>
{
public:
LLVolumeOctreeRebound()
{
}
virtual void visit(const LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>* branch)
{ //this is a depth first traversal, so it's safe to assum all children have complete
//bounding data
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME
LLVolumeOctreeListener* node = (LLVolumeOctreeListener*)branch->getListener(0);
LLVector4a& min = node->mExtents[0];
LLVector4a& max = node->mExtents[1];
if (!branch->isEmpty())
{ //node has data, find AABB that binds data set
const LLVolumeTriangle* tri = *(branch->getDataBegin());
//initialize min/max to first available vertex
min = *(tri->mV[0]);
max = *(tri->mV[0]);
for (LLOctreeNode<LLVolumeTriangle, LLVolumeTriangle*>::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter)
{ //for each triangle in node
//stretch by triangles in node
tri = *iter;
min.setMin(min, *tri->mV[0]);
min.setMin(min, *tri->mV[1]);
min.setMin(min, *tri->mV[2]);
max.setMax(max, *tri->mV[0]);
max.setMax(max, *tri->mV[1]);
max.setMax(max, *tri->mV[2]);
}
}
else if (branch->getChildCount() > 0)
{ //no data, but child nodes exist
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(0)->getListener(0);
//initialize min/max to extents of first child
min = child->mExtents[0];
max = child->mExtents[1];
}
else
{
llassert(!branch->isLeaf()); // Empty leaf
}
for (S32 i = 0; i < branch->getChildCount(); ++i)
{ //stretch by child extents
LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(i)->getListener(0);
min.setMin(min, child->mExtents[0]);
max.setMax(max, child->mExtents[1]);
}
node->mBounds[0].setAdd(min, max);
node->mBounds[0].mul(0.5f);
node->mBounds[1].setSub(max, min);
node->mBounds[1].mul(0.5f);
}
};
class LLVolumeOctree : public LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>, public LLRefCount
{
public:
LLVolumeOctree(const LLVector4a& center, const LLVector4a& size)
:
LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(center, size, nullptr),
LLRefCount()
{
new LLVolumeOctreeListener(this);
}
LLVolumeOctree()
: LLOctreeRoot<LLVolumeTriangle, LLVolumeTriangle*>(LLVector4a::getZero(), LLVector4a(1.f,1.f,1.f), nullptr),
LLRefCount()
{
new LLVolumeOctreeListener(this);
}
};
#endif #endif

View File

@ -601,7 +601,7 @@ void LLPluginProcessParent::idle(void)
params.args.add("-e"); params.args.add("-e");
params.args.add("tell application \"Terminal\""); params.args.add("tell application \"Terminal\"");
params.args.add("-e"); params.args.add("-e");
params.args.add(STRINGIZE("set win to do script \"gdb -pid " params.args.add(STRINGIZE("set win to do script \"lldb -pid "
<< mProcess->getProcessID() << "\"")); << mProcess->getProcessID() << "\""));
params.args.add("-e"); params.args.add("-e");
params.args.add("do script \"continue\" in win"); params.args.add("do script \"continue\" in win");

View File

@ -233,10 +233,17 @@ protected:
void updateLocalTexDataDigest(); void updateLocalTexDataDigest();
public: public:
// *TODO: If/when we implement additional GLTF extensions, they may not be
// compatible with our GLTF terrain implementation. We may want to disallow
// materials with some features from being set on terrain, if their
// implementation on terrain is not compliant with the spec:
// - KHR_materials_transmission: Probably OK?
// - KHR_materials_ior: Probably OK?
// - KHR_materials_volume: Likely incompatible, as our terrain
// heightmaps cannot currently be described as finite enclosed
// volumes.
// See also LLPanelRegionTerrainInfo::validateMaterials
// These fields are local to viewer and are a part of local bitmap support // These fields are local to viewer and are a part of local bitmap support
// IMPORTANT: do not move this member down (and do not move
// mLocalTexDataDigest either): the getHash() method does rely on the
// current ordering. HB
typedef std::map<LLUUID, LLUUID> local_tex_map_t; typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture; local_tex_map_t mTrackingIdToLocalTexture;

View File

@ -1948,6 +1948,19 @@ void LLReflectionProbeParams::setIsDynamic(bool is_dynamic)
} }
} }
void LLReflectionProbeParams::setIsMirror(bool is_mirror)
{
if (is_mirror)
{
mFlags |= FLAG_MIRROR;
}
else
{
mFlags &= ~FLAG_MIRROR;
}
}
//============================================================================ //============================================================================
LLFlexibleObjectData::LLFlexibleObjectData() LLFlexibleObjectData::LLFlexibleObjectData()
{ {

View File

@ -194,6 +194,7 @@ public:
{ {
FLAG_BOX_VOLUME = 0x01, // use a box influence volume FLAG_BOX_VOLUME = 0x01, // use a box influence volume
FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe
FLAG_MIRROR = 0x04, // This probe is used for reflections on realtime mirrors.
}; };
protected: protected:
@ -217,11 +218,13 @@ public:
void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); } void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); }
void setIsBox(bool is_box); void setIsBox(bool is_box);
void setIsDynamic(bool is_dynamic); void setIsDynamic(bool is_dynamic);
void setIsMirror(bool is_mirror);
F32 getAmbiance() const { return mAmbiance; } F32 getAmbiance() const { return mAmbiance; }
F32 getClipDistance() const { return mClipDistance; } F32 getClipDistance() const { return mClipDistance; }
bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; } bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; }
bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; } bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; }
bool getIsMirror() const { return (mFlags & FLAG_MIRROR) != 0; }
}; };
//------------------------------------------------- //-------------------------------------------------

View File

@ -685,6 +685,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
mMaterialUpdatePending = true; mMaterialUpdatePending = true;
} }
mMaterial = pMaterialParams; mMaterial = pMaterialParams;
return TEM_CHANGE_TEXTURE; return TEM_CHANGE_TEXTURE;
} }

View File

@ -1190,6 +1190,8 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1; return -1;
} }
S32 index = mTexture[uniform]; S32 index = mTexture[uniform];
if (index != -1) if (index != -1)
{ {

View File

@ -49,13 +49,14 @@ public:
bool hasShadows = false; bool hasShadows = false;
bool hasAmbientOcclusion = false; bool hasAmbientOcclusion = false;
bool hasSrgb = false; bool hasSrgb = false;
bool encodesNormal = false; // include: shaders\class1\environment\encodeNormF.glsl
bool isDeferred = false; bool isDeferred = false;
bool hasScreenSpaceReflections = false; bool hasScreenSpaceReflections = false;
bool disableTextureIndex = false; bool disableTextureIndex = false;
bool hasAlphaMask = false; bool hasAlphaMask = false;
bool hasReflectionProbes = false; bool hasReflectionProbes = false;
bool attachNothing = false; bool attachNothing = false;
bool hasHeroProbes = false;
bool isPBRTerrain = false;
}; };
// ============= Structure for caching shader uniforms =============== // ============= Structure for caching shader uniforms ===============

View File

@ -49,6 +49,10 @@ LLGLTexture::LLGLTexture(const LLImageRaw* raw, bool usemipmaps)
mUseMipMaps = usemipmaps ; mUseMipMaps = usemipmaps ;
// Create an empty image of the specified size and width // Create an empty image of the specified size and width
mGLTexturep = new LLImageGL(raw, usemipmaps) ; mGLTexturep = new LLImageGL(raw, usemipmaps) ;
mFullWidth = mGLTexturep->getCurrentWidth();
mFullHeight = mGLTexturep->getCurrentHeight();
mComponents = mGLTexturep->getComponents();
setTexelsPerImage();
} }
LLGLTexture::~LLGLTexture() LLGLTexture::~LLGLTexture()
@ -95,7 +99,8 @@ void LLGLTexture::setBoostLevel(S32 level)
mBoostLevel = level ; mBoostLevel = level ;
if(mBoostLevel != LLGLTexture::BOOST_NONE if(mBoostLevel != LLGLTexture::BOOST_NONE
&& mBoostLevel != LLGLTexture::BOOST_ICON && mBoostLevel != LLGLTexture::BOOST_ICON
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL) && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL
&& mBoostLevel != LLGLTexture::BOOST_TERRAIN)
{ {
setNoDelete() ; setNoDelete() ;
} }

View File

@ -42,7 +42,7 @@ class LLGLTexture : public LLTexture
public: public:
enum enum
{ {
MAX_IMAGE_SIZE_DEFAULT = 1024, MAX_IMAGE_SIZE_DEFAULT = 2048,
INVALID_DISCARD_LEVEL = 0x7fff INVALID_DISCARD_LEVEL = 0x7fff
}; };
@ -52,10 +52,11 @@ public:
BOOST_AVATAR , BOOST_AVATAR ,
BOOST_AVATAR_BAKED , BOOST_AVATAR_BAKED ,
BOOST_SCULPTED , BOOST_SCULPTED ,
BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
BOOST_HIGH = 10, BOOST_HIGH = 10,
BOOST_BUMP , BOOST_BUMP ,
BOOST_TERRAIN , // has to be high priority for minimap / low detail BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
BOOST_SELECTED , BOOST_SELECTED ,
BOOST_AVATAR_BAKED_SELF , BOOST_AVATAR_BAKED_SELF ,
BOOST_AVATAR_SELF , // needed for baking avatar BOOST_AVATAR_SELF , // needed for baking avatar

View File

@ -2124,10 +2124,6 @@ void LLRender::diffuseColor3f(F32 r, F32 g, F32 b)
{ {
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f); shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f);
} }
else
{
glColor3f(r,g,b);
}
} }
void LLRender::diffuseColor3fv(const F32* c) void LLRender::diffuseColor3fv(const F32* c)
@ -2139,10 +2135,6 @@ void LLRender::diffuseColor3fv(const F32* c)
{ {
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f); shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f);
} }
else
{
glColor3fv(c);
}
} }
void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a)
@ -2154,10 +2146,6 @@ void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a)
{ {
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a); shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a);
} }
else
{
glColor4f(r,g,b,a);
}
} }
void LLRender::diffuseColor4fv(const F32* c) void LLRender::diffuseColor4fv(const F32* c)
@ -2169,10 +2157,6 @@ void LLRender::diffuseColor4fv(const F32* c)
{ {
shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c); shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c);
} }
else
{
glColor4fv(c);
}
} }
void LLRender::diffuseColor4ubv(const U8* c) void LLRender::diffuseColor4ubv(const U8* c)
@ -2184,10 +2168,6 @@ void LLRender::diffuseColor4ubv(const U8* c)
{ {
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f);
} }
else
{
glColor4ubv(c);
}
} }
void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
@ -2199,10 +2179,6 @@ void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
{ {
shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
} }
else
{
glColor4ub(r,g,b,a);
}
} }

View File

@ -567,4 +567,31 @@ bool LLRenderTarget::isBoundInStack() const
return cur == this; return cur == this;
} }
void LLRenderTarget::swapFBORefs(LLRenderTarget& other)
{
// Must be initialized
llassert(mFBO);
llassert(other.mFBO);
// Must be unbound
// *NOTE: mPreviousRT can be non-null even if this target is unbound - presumably for debugging purposes?
llassert(sCurFBO != mFBO);
llassert(sCurFBO != other.mFBO);
llassert(!isBoundInStack());
llassert(!other.isBoundInStack());
// Must be same type
llassert(sUseFBO == other.sUseFBO);
llassert(mResX == other.mResX);
llassert(mResY == other.mResY);
llassert(mInternalFormat == other.mInternalFormat);
llassert(mTex.size() == other.mTex.size());
llassert(mDepth == other.mDepth);
llassert(mUseDepth == other.mUseDepth);
llassert(mGenerateMipMaps == other.mGenerateMipMaps);
llassert(mMipLevels == other.mMipLevels);
llassert(mUsage == other.mUsage);
std::swap(mFBO, other.mFBO);
std::swap(mTex, other.mTex);
}

View File

@ -169,6 +169,9 @@ public:
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
// *HACK
void swapFBORefs(LLRenderTarget& other);
protected: protected:
U32 mResX; U32 mResX;
U32 mResY; U32 mResY;

View File

@ -44,6 +44,7 @@ using std::make_pair;
using std::string; using std::string;
LLShaderMgr * LLShaderMgr::sInstance = NULL; LLShaderMgr * LLShaderMgr::sInstance = NULL;
bool LLShaderMgr::sMirrorsEnabled = false;
LLShaderMgr::LLShaderMgr() LLShaderMgr::LLShaderMgr()
{ {
@ -183,7 +184,13 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
// Attach Fragment Shader Features Next // Attach Fragment Shader Features Next
/////////////////////////////////////// ///////////////////////////////////////
// NOTE order of shader object attaching is VERY IMPORTANT!!! // NOTE order of shader object attaching is VERY IMPORTANT!!!
if (!shader->attachFragmentObject("deferred/globalF.glsl"))
{
return false;
}
if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred) if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred)
{ {
if (!shader->attachFragmentObject("environment/srgbF.glsl")) if (!shader->attachFragmentObject("environment/srgbF.glsl"))
@ -257,14 +264,6 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
} }
} }
if (features->encodesNormal)
{
if (!shader->attachFragmentObject("environment/encodeNormF.glsl"))
{
return false;
}
}
if (features->hasAtmospherics || features->isDeferred) if (features->hasAtmospherics || features->isDeferred)
{ {
if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) { if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {
@ -277,6 +276,14 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
} }
} }
if (features->isPBRTerrain)
{
if (!shader->attachFragmentObject("deferred/pbrterrainUtilF.glsl"))
{
return false;
}
}
// NOTE order of shader object attaching is VERY IMPORTANT!!! // NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->hasAtmospherics) if (features->hasAtmospherics)
{ {
@ -321,7 +328,7 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return false; return false;
} }
} }
shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels, 1);
} }
} }
@ -577,6 +584,16 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
} }
} }
else else
{
if (type == GL_GEOMETRY_SHADER)
{
//set version to 1.50
shader_code_text[shader_code_count++] = strdup("#version 150\n");
//some implementations of GLSL 1.30 require integer precision be explicitly declared
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
}
else
{ {
//set version to 1.40 //set version to 1.40
shader_code_text[shader_code_count++] = strdup("#version 140\n"); shader_code_text[shader_code_count++] = strdup("#version 140\n");
@ -584,15 +601,22 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
} }
}
extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
} }
if (sMirrorsEnabled)
{
extra_code_text[extra_code_count++] = strdup("#define HERO_PROBES 1\n");
}
// Use alpha float to store bit flags // Use alpha float to store bit flags
// See: C++: addDeferredAttachment(), shader: frag_data[2] // 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_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_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 GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_HDRI 1.0\n"); // bit 2
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n"); extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
if (defines) if (defines)
@ -1198,6 +1222,9 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("emissiveColor"); mReservedUniforms.push_back("emissiveColor");
mReservedUniforms.push_back("metallicFactor"); mReservedUniforms.push_back("metallicFactor");
mReservedUniforms.push_back("roughnessFactor"); mReservedUniforms.push_back("roughnessFactor");
mReservedUniforms.push_back("mirror_flag");
mReservedUniforms.push_back("clipPlane");
mReservedUniforms.push_back("clipSign");
mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap"); mReservedUniforms.push_back("altDiffuseMap");
@ -1210,6 +1237,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sceneDepth"); mReservedUniforms.push_back("sceneDepth");
mReservedUniforms.push_back("reflectionProbes"); mReservedUniforms.push_back("reflectionProbes");
mReservedUniforms.push_back("irradianceProbes"); mReservedUniforms.push_back("irradianceProbes");
mReservedUniforms.push_back("heroProbes");
mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture");
mReservedUniforms.push_back("cloud_noise_texture_next"); mReservedUniforms.push_back("cloud_noise_texture_next");
mReservedUniforms.push_back("fullbright"); mReservedUniforms.push_back("fullbright");
@ -1392,8 +1420,32 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("detail_1"); mReservedUniforms.push_back("detail_1");
mReservedUniforms.push_back("detail_2"); mReservedUniforms.push_back("detail_2");
mReservedUniforms.push_back("detail_3"); mReservedUniforms.push_back("detail_3");
mReservedUniforms.push_back("alpha_ramp"); mReservedUniforms.push_back("alpha_ramp");
mReservedUniforms.push_back("detail_0_base_color");
mReservedUniforms.push_back("detail_1_base_color");
mReservedUniforms.push_back("detail_2_base_color");
mReservedUniforms.push_back("detail_3_base_color");
mReservedUniforms.push_back("detail_0_normal");
mReservedUniforms.push_back("detail_1_normal");
mReservedUniforms.push_back("detail_2_normal");
mReservedUniforms.push_back("detail_3_normal");
mReservedUniforms.push_back("detail_0_metallic_roughness");
mReservedUniforms.push_back("detail_1_metallic_roughness");
mReservedUniforms.push_back("detail_2_metallic_roughness");
mReservedUniforms.push_back("detail_3_metallic_roughness");
mReservedUniforms.push_back("detail_0_emissive");
mReservedUniforms.push_back("detail_1_emissive");
mReservedUniforms.push_back("detail_2_emissive");
mReservedUniforms.push_back("detail_3_emissive");
mReservedUniforms.push_back("baseColorFactors");
mReservedUniforms.push_back("metallicFactors");
mReservedUniforms.push_back("roughnessFactors");
mReservedUniforms.push_back("emissiveColors");
mReservedUniforms.push_back("minimum_alphas");
mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("origin");
mReservedUniforms.push_back("display_gamma"); mReservedUniforms.push_back("display_gamma");
@ -1415,6 +1467,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("cloud_variance"); mReservedUniforms.push_back("cloud_variance");
mReservedUniforms.push_back("reflection_probe_ambiance"); mReservedUniforms.push_back("reflection_probe_ambiance");
mReservedUniforms.push_back("max_probe_lod"); mReservedUniforms.push_back("max_probe_lod");
mReservedUniforms.push_back("probe_strength");
mReservedUniforms.push_back("sh_input_r"); mReservedUniforms.push_back("sh_input_r");
mReservedUniforms.push_back("sh_input_g"); mReservedUniforms.push_back("sh_input_g");
@ -1425,6 +1478,8 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sun_up_factor"); mReservedUniforms.push_back("sun_up_factor");
mReservedUniforms.push_back("moonlight_color"); mReservedUniforms.push_back("moonlight_color");
mReservedUniforms.push_back("debug_normal_draw_length");
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
std::set<std::string> dupe_check; std::set<std::string> dupe_check;

View File

@ -85,6 +85,9 @@ public:
EMISSIVE_COLOR, // "emissiveColor" EMISSIVE_COLOR, // "emissiveColor"
METALLIC_FACTOR, // "metallicFactor" METALLIC_FACTOR, // "metallicFactor"
ROUGHNESS_FACTOR, // "roughnessFactor" ROUGHNESS_FACTOR, // "roughnessFactor"
MIRROR_FLAG, // "mirror_flag"
CLIP_PLANE, // "clipPlane"
CLIP_SIGN, // "clipSign"
DIFFUSE_MAP, // "diffuseMap" DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap" ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap" SPECULAR_MAP, // "specularMap"
@ -96,6 +99,7 @@ public:
SCENE_DEPTH, // "sceneDepth" SCENE_DEPTH, // "sceneDepth"
REFLECTION_PROBES, // "reflectionProbes" REFLECTION_PROBES, // "reflectionProbes"
IRRADIANCE_PROBES, // "irradianceProbes" IRRADIANCE_PROBES, // "irradianceProbes"
HERO_PROBE, // "heroProbes"
CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP, // "cloud_noise_texture"
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
FULLBRIGHT, // "fullbright" FULLBRIGHT, // "fullbright"
@ -264,8 +268,32 @@ public:
TERRAIN_DETAIL1, // "detail_1" TERRAIN_DETAIL1, // "detail_1"
TERRAIN_DETAIL2, // "detail_2" TERRAIN_DETAIL2, // "detail_2"
TERRAIN_DETAIL3, // "detail_3" TERRAIN_DETAIL3, // "detail_3"
TERRAIN_ALPHARAMP, // "alpha_ramp" TERRAIN_ALPHARAMP, // "alpha_ramp"
TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF)
TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF)
TERRAIN_DETAIL2_BASE_COLOR, // "detail_2_base_color" (GLTF)
TERRAIN_DETAIL3_BASE_COLOR, // "detail_3_base_color" (GLTF)
TERRAIN_DETAIL0_NORMAL, // "detail_0_normal" (GLTF)
TERRAIN_DETAIL1_NORMAL, // "detail_1_normal" (GLTF)
TERRAIN_DETAIL2_NORMAL, // "detail_2_normal" (GLTF)
TERRAIN_DETAIL3_NORMAL, // "detail_3_normal" (GLTF)
TERRAIN_DETAIL0_METALLIC_ROUGHNESS, // "detail_0_metallic_roughness" (GLTF)
TERRAIN_DETAIL1_METALLIC_ROUGHNESS, // "detail_1_metallic_roughness" (GLTF)
TERRAIN_DETAIL2_METALLIC_ROUGHNESS, // "detail_2_metallic_roughness" (GLTF)
TERRAIN_DETAIL3_METALLIC_ROUGHNESS, // "detail_3_metallic_roughness" (GLTF)
TERRAIN_DETAIL0_EMISSIVE, // "detail_0_emissive" (GLTF)
TERRAIN_DETAIL1_EMISSIVE, // "detail_1_emissive" (GLTF)
TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF)
TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF)
TERRAIN_BASE_COLOR_FACTORS, // "baseColorFactors" (GLTF)
TERRAIN_METALLIC_FACTORS, // "metallicFactors" (GLTF)
TERRAIN_ROUGHNESS_FACTORS, // "roughnessFactors" (GLTF)
TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF)
TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF)
SHINY_ORIGIN, // "origin" SHINY_ORIGIN, // "origin"
DISPLAY_GAMMA, // "display_gamma" DISPLAY_GAMMA, // "display_gamma"
@ -292,6 +320,7 @@ public:
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance" REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
REFLECTION_PROBE_MAX_LOD, // "max_probe_lod" REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
REFLECTION_PROBE_STRENGTH, // "probe_strength"
SH_INPUT_L1R, // "sh_input_r" SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g" SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b" SH_INPUT_L1B, // "sh_input_b"
@ -300,6 +329,9 @@ public:
WATER_EDGE_FACTOR, // "water_edge" WATER_EDGE_FACTOR, // "water_edge"
SUN_UP_FACTOR, // "sun_up_factor" SUN_UP_FACTOR, // "sun_up_factor"
MOONLIGHT_COLOR, // "moonlight_color" MOONLIGHT_COLOR, // "moonlight_color"
DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length"
END_RESERVED_UNIFORMS END_RESERVED_UNIFORMS
} eGLSLReservedUniforms; } eGLSLReservedUniforms;
// clang-format on // clang-format on
@ -349,6 +381,7 @@ public:
bool mShaderCacheInitialized = false; bool mShaderCacheInitialized = false;
bool mShaderCacheEnabled = false; bool mShaderCacheEnabled = false;
std::string mShaderCacheDir; std::string mShaderCacheDir;
static bool sMirrorsEnabled;
protected: protected:

View File

@ -674,7 +674,7 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
U16 idx = indicesp[i]; U16 idx = indicesp[i];
gGL.vertex3fv(pos[idx].getF32ptr()); gGL.vertex3fv(pos[idx].getF32ptr());
} }
} }
gGL.end(); gGL.end();
gGL.flush(); gGL.flush();
} }
@ -756,8 +756,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLBuffer == sGLRenderBuffer);
llassert(mGLIndices == sGLRenderIndices); llassert(mGLIndices == sGLRenderIndices);
gGL.syncMatrices(); gGL.syncMatrices();
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType,
(GLvoid*) (indices_offset * sizeof(U16))); (GLvoid*) (indices_offset * (size_t) mIndicesStride));
} }
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
@ -1154,7 +1154,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
} }
// flush the given byte range // flush the given byte range
// target -- "targret" parameter for glBufferSubData // target -- "target" parameter for glBufferSubData
// start -- first byte to copy // start -- first byte to copy
// end -- last byte to copy (NOT last byte + 1) // end -- last byte to copy (NOT last byte + 1)
// data -- mMappedData or mMappedIndexData // data -- mMappedData or mMappedIndexData
@ -1316,6 +1316,8 @@ bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, U32 index,
} }
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, U32 index, S32 count) bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, U32 index, S32 count)
{ {
llassert(mIndicesStride == 2); // cannot access 32-bit indices with U16 strider
llassert(mIndicesType == GL_UNSIGNED_SHORT);
return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count); return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count);
} }
bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index, S32 count) bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
@ -1334,6 +1336,10 @@ bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index,
{ {
return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count); return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
} }
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
return VertexBufferStrider<LLVector4a, TYPE_NORMAL>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count) bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{ {
return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count); return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);
@ -1529,4 +1535,39 @@ void LLVertexBuffer::setColorData(const LLColor4U* data)
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data); flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data);
} }
void LLVertexBuffer::setNormalData(const LLVector4a* data)
{
llassert(sGLRenderBuffer == mGLBuffer);
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data);
}
void LLVertexBuffer::setTangentData(const LLVector4a* data)
{
llassert(sGLRenderBuffer == mGLBuffer);
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data);
}
void LLVertexBuffer::setWeight4Data(const LLVector4a* data)
{
llassert(sGLRenderBuffer == mGLBuffer);
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data);
}
void LLVertexBuffer::setIndexData(const U16* data)
{
llassert(sGLRenderIndices == mGLIndices);
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data);
}
void LLVertexBuffer::setIndexData(const U32* data)
{
llassert(sGLRenderIndices == mGLIndices);
if (mIndicesType != GL_UNSIGNED_INT)
{ // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices
mIndicesType = GL_UNSIGNED_INT;
mIndicesStride = 4;
mNumIndices /= 2;
}
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data);
}

View File

@ -180,6 +180,7 @@ public:
bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1); bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1); bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1); bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getNormalStrider(LLStrider<LLVector4a>& strider, U32 index = 0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1); bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1); bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1); bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
@ -191,15 +192,15 @@ public:
bool getWeight4Strider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1); bool getWeight4Strider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
bool getClothWeightStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1); bool getClothWeightStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
// </FS:Ansariel> // </FS:Ansariel>
bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
void setPositionData(const LLVector4a* data); void setPositionData(const LLVector4a* data);
void setNormalData(const LLVector4a* data);
void setTangentData(const LLVector4a* data);
void setWeight4Data(const LLVector4a* data);
void setTexCoordData(const LLVector2* data); void setTexCoordData(const LLVector2* data);
void setColorData(const LLColor4U* data); void setColorData(const LLColor4U* data);
void setIndexData(const U16* data);
void setIndexData(const U32* data);
U32 getNumVerts() const { return mNumVerts; } U32 getNumVerts() const { return mNumVerts; }
U32 getNumIndices() const { return mNumIndices; } U32 getNumIndices() const { return mNumIndices; }
@ -231,6 +232,8 @@ protected:
U32 mGLIndices = 0; // GL IBO handle U32 mGLIndices = 0; // GL IBO handle
U32 mNumVerts = 0; // Number of vertices allocated U32 mNumVerts = 0; // Number of vertices allocated
U32 mNumIndices = 0; // Number of indices allocated U32 mNumIndices = 0; // Number of indices allocated
U32 mIndicesType = GL_UNSIGNED_SHORT; // type of indices in index buffer
U32 mIndicesStride = 2; // size of each index in bytes
U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped) U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)

View File

@ -103,20 +103,34 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c
if (mHelperHandle.isDead()) if (mHelperHandle.isDead())
{ {
LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER);
// <FS:Beq> Try to prevent failed build of emoji picker from killing the viewer.
if(!pHelperFloater)
{
LL_WARNS() << "Cannot show emoji helper, reason unknown." << LL_ENDL;
return;
}
// </FS:Beq>
mHelperHandle = pHelperFloater->getHandle(); mHelperHandle = pHelperFloater->getHandle();
mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2));
} }
setHostCtrl(hostctrl_p); setHostCtrl(hostctrl_p);
mEmojiCommitCb = cb; mEmojiCommitCb = cb;
S32 floater_x, floater_y; S32 floater_x=0, floater_y=0;// <FS:Beq/> initialise to avoid warnings
if (!hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView)) if (hostctrl_p && !hostctrl_p->localPointToOtherView(local_x, local_y, &floater_x, &floater_y, gFloaterView))// <FS:Beq/> another unchecked pointer access
{ {
LL_ERRS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL; LL_WARNS() << "Cannot show emoji helper for non-floater controls." << LL_ENDL; // <FS:Beq/> Is this really worth crashing over?
return; return;
} }
LLFloater* pHelperFloater = mHelperHandle.get(); LLFloater* pHelperFloater = mHelperHandle.get();
// <FS:Beq> Be a bit paranoid - the previous code should have ensured this or returned.
if (!pHelperFloater)
{
LL_WARNS() << "Helper floater unexpectedly null." << LL_ENDL;
return;
}
// </FS:Beq>
LLRect rect = pHelperFloater->getRect(); LLRect rect = pHelperFloater->getRect();
S32 left = floater_x - HELPER_FLOATER_OFFSET_X; S32 left = floater_x - HELPER_FLOATER_OFFSET_X;
S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight(); S32 top = floater_y - HELPER_FLOATER_OFFSET_Y + rect.getHeight();

View File

@ -50,7 +50,7 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::set<s
"contact https://www.firestormviewer.org/support if issue persists after reinstall."; "contact https://www.firestormviewer.org/support if issue persists after reinstall.";
LLError::LLUserWarningMsg::show(error_string); LLError::LLUserWarningMsg::show(error_string);
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL; LL_ERRS() << "Couldn't load string table " << xml_filename << ". Please reinstall viewer from https://www.firestormviewer.org/download and contact https://www.firestormviewer.org/support if issue persists after reinstall." << LL_ENDL;
return false; return false;
} }

View File

@ -37,6 +37,7 @@ include(OpenGL)
include(OpenSSL) include(OpenSSL)
include(PNG) include(PNG)
include(TemplateCheck) include(TemplateCheck)
include(TinyEXR)
include(ThreeJS) include(ThreeJS)
include(Tracy) include(Tracy)
include(UI) include(UI)
@ -167,7 +168,6 @@ set(viewer_SOURCE_FILES
fsscrolllistctrl.cpp fsscrolllistctrl.cpp
fsslurlcommand.cpp fsslurlcommand.cpp
fsworldmapmessage.cpp fsworldmapmessage.cpp
groupchatlistener.cpp
lggbeamcolormapfloater.cpp lggbeamcolormapfloater.cpp
lggbeammapfloater.cpp lggbeammapfloater.cpp
lggbeammaps.cpp lggbeammaps.cpp
@ -183,6 +183,12 @@ set(viewer_SOURCE_FILES
vjfloaterlocalmesh.cpp vjfloaterlocalmesh.cpp
vjlocalmeshimportdae.cpp vjlocalmeshimportdae.cpp
gltfscenemanager.cpp
gltf/asset.cpp
gltf/accessor.cpp
gltf/primitive.cpp
gltf/animation.cpp
groupchatlistener.cpp
llaccountingcostmanager.cpp llaccountingcostmanager.cpp
llaisapi.cpp llaisapi.cpp
llagent.cpp llagent.cpp
@ -424,6 +430,7 @@ set(viewer_SOURCE_FILES
llgiveinventory.cpp llgiveinventory.cpp
llglsandbox.cpp llglsandbox.cpp
llgltfmateriallist.cpp llgltfmateriallist.cpp
llgltfmaterialpreviewmgr.cpp
llgroupactions.cpp llgroupactions.cpp
llgroupiconctrl.cpp llgroupiconctrl.cpp
llgrouplist.cpp llgrouplist.cpp
@ -633,6 +640,7 @@ set(viewer_SOURCE_FILES
llrecentpeople.cpp llrecentpeople.cpp
llreflectionmap.cpp llreflectionmap.cpp
llreflectionmapmanager.cpp llreflectionmapmanager.cpp
llheroprobemanager.cpp
llregioninfomodel.cpp llregioninfomodel.cpp
llregionposition.cpp llregionposition.cpp
llremoteparcelrequest.cpp llremoteparcelrequest.cpp
@ -958,8 +966,6 @@ set(viewer_HEADER_FILES
fsslurl.h fsslurl.h
fsslurlcommand.h fsslurlcommand.h
fsworldmapmessage.h fsworldmapmessage.h
groupchatlistener.h
llaccountingcost.h
lggbeamcolormapfloater.h lggbeamcolormapfloater.h
lggbeammapfloater.h lggbeammapfloater.h
lggbeammaps.h lggbeammaps.h
@ -974,6 +980,14 @@ set(viewer_HEADER_FILES
vjfloaterlocalmesh.h vjfloaterlocalmesh.h
vjlocalmeshimportdae.h vjlocalmeshimportdae.h
gltfscenemanager.h
groupchatlistener.h
gltf/asset.h
gltf/accessor.h
gltf/buffer_util.h
gltf/primitive.h
gltf/animation.h
llaccountingcost.h
llaccountingcostmanager.h llaccountingcostmanager.h
llaisapi.h llaisapi.h
llagent.h llagent.h
@ -1218,6 +1232,7 @@ set(viewer_HEADER_FILES
llgesturemgr.h llgesturemgr.h
llgiveinventory.h llgiveinventory.h
llgltfmateriallist.h llgltfmateriallist.h
llgltfmaterialpreviewmgr.h
llgroupactions.h llgroupactions.h
llgroupiconctrl.h llgroupiconctrl.h
llgrouplist.h llgrouplist.h
@ -1413,6 +1428,7 @@ set(viewer_HEADER_FILES
llrecentpeople.h llrecentpeople.h
llreflectionmap.h llreflectionmap.h
llreflectionmapmanager.h llreflectionmapmanager.h
llheroprobemanager.h
llregioninfomodel.h llregioninfomodel.h
llregionposition.h llregionposition.h
llremoteparcelrequest.h llremoteparcelrequest.h

View File

@ -1 +1 @@
7.1.8 7.1.9

View File

@ -25,6 +25,8 @@
<string>RenderDeferredSSAO</string> <string>RenderDeferredSSAO</string>
<string>RenderDepthOfField</string> <string>RenderDepthOfField</string>
<string>RenderDepthOfFieldInEditMode</string> <string>RenderDepthOfFieldInEditMode</string>
<string>RenderDesaturateIrradiance</string>
<string>RenderDiffuseLuminanceScale</string>
<string>RenderDisablePostProcessing</string> <string>RenderDisablePostProcessing</string>
<string>RenderPostProcessingHDR</string> <string>RenderPostProcessingHDR</string>
<string>RenderDefaultProbeUpdatePeriod</string> <string>RenderDefaultProbeUpdatePeriod</string>
@ -38,9 +40,18 @@
<string>RenderGlowIterations</string> <string>RenderGlowIterations</string>
<string>RenderGlowNoise</string> <string>RenderGlowNoise</string>
<string>RenderGlowResolutionPow</string> <string>RenderGlowResolutionPow</string>
<string>RenderHDRIExposure</string>
<string>RenderHDRIRotation</string>
<string>RenderHDRISplitScreen</string>
<string>RenderHDRIIrradianceOnly</string>
<string>RenderHeroProbeResolution</string>
<string>RenderHeroProbeDistance</string>
<string>RenderHeroProbeUpdateRate</string>
<string>RenderHeroProbeConservativeUpdateMultiplier</string>
<string>RenderLocalLightCount</string> <string>RenderLocalLightCount</string>
<string>RenderMaxPartCount</string> <string>RenderMaxPartCount</string>
<string>RenderMaxVRAMBudget</string> <string>RenderMaxVRAMBudget</string>
<string>RenderMirrors</string>
<string>RenderQualityPerformance</string> <string>RenderQualityPerformance</string>
<string>RenderReflectionsEnabled</string> <string>RenderReflectionsEnabled</string>
<string>RenderReflectionProbeAmbiance</string> <string>RenderReflectionProbeAmbiance</string>
@ -74,7 +85,12 @@
<string>RenderSunDynamicRange</string> <string>RenderSunDynamicRange</string>
<string>RenderTerrainDetail</string> <string>RenderTerrainDetail</string>
<string>RenderTerrainLODFactor</string> <string>RenderTerrainLODFactor</string>
<string>RenderTerrainPBRDetail</string>
<string>RenderTerrainPBRScale</string>
<string>RenderTerrainPBRPlanarSampleCount</string>
<string>RenderTerrainPBRTriplanarBlendFactor</string>
<string>RenderTerrainScale</string> <string>RenderTerrainScale</string>
<string>RenderMaxTextureResolution</string>
<string>RenderTreeLODFactor</string> <string>RenderTreeLODFactor</string>
<string>RenderTransparentWater</string> <string>RenderTransparentWater</string>
<string>RenderUnloadedAvatar</string> <string>RenderUnloadedAvatar</string>

View File

@ -10360,7 +10360,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>OctreeAlphaDistanceFactor</key> <key>OctreeAlphaDistanceFactor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Multiplier on alpha object distance for determining octree node size </string> <string>Multiplier on alpha object distance for determining octree node size. First two parameters are currently unused. Third parameter is distance at which to perform detailed alpha sorting.</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@ -10369,7 +10369,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<array> <array>
<real>0.1</real> <real>0.1</real>
<real>0.0</real> <real>0.0</real>
<real>0.0</real> <real>64.0</real>
</array> </array>
<key>Backup</key> <key>Backup</key>
<integer>0</integer> <integer>0</integer>
@ -10473,17 +10473,6 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key> <key>Value</key>
<real>32.0</real> <real>32.0</real>
</map> </map>
<key>RenderCloudShadowAmbianceFactor</key>
<map>
<key>Comment</key>
<string>Amount that cloud shadow (aka cloud coverage) contributes to reflection probe ambiance</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.1</real>
</map>
<key>RenderCPUBasis</key> <key>RenderCPUBasis</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -10818,6 +10807,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Backup</key> <key>Backup</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>RenderMirrors</key>
<map>
<key>Comment</key>
<string>Renders realtime mirrors.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderScreenSpaceReflections</key> <key>RenderScreenSpaceReflections</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -10947,6 +10947,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Backup</key> <key>Backup</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>RenderDesaturateIrradiance</key>
<map>
<key>Comment</key>
<string>Desaturate irradiance to remove blue tint</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderDebugAlphaMask</key> <key>RenderDebugAlphaMask</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -11030,6 +11041,50 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>RenderHDRIExposure</key>
<map>
<key>Comment</key>
<string>Exposure adjustment of HDRI when previewing an HDRI. Units are EV. Sane values would be -10 to 10.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.0</real>
</map>
<key>RenderHDRIRotation</key>
<map>
<key>Comment</key>
<string>Rotation (in degrees) of environment when previewing an HDRI.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.0</real>
</map>
<key>RenderHDRISplitScreen</key>
<map>
<key>Comment</key>
<string>What percentage of screen to render using HDRI vs EEP sky.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>RenderHDRIIrradianceOnly</key>
<map>
<key>Comment</key>
<string>Only use HDRI sky for irradiance map when RenderHDRISplitScreen is 0</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderMaxOpenGLVersion</key> <key>RenderMaxOpenGLVersion</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -11062,6 +11117,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>U32</string> <string>U32</string>
<key>Value</key> <key>Value</key>
<integer>16</integer> <integer>16</integer>
</map>
<key>RenderMaxTextureResolution</key>
<map>
<key>Comment</key>
<string>Maximum texture resolution to download for non-boosted textures.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>2048</integer>
</map> </map>
<key>RenderDebugTextureBind</key> <key>RenderDebugTextureBind</key>
<map> <map>
@ -12173,6 +12239,50 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map>
<key>RenderHeroProbeResolution</key>
<map>
<key>Comment</key>
<string>Resolution to render hero probes used for mirrors, water, etc.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>1024</integer>
</map>
<key>RenderHeroProbeDistance</key>
<map>
<key>Comment</key>
<string>Distance in meters for hero probes to render out to.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>8</real>
</map>
<key>RenderHeroProbeUpdateRate</key>
<map>
<key>Comment</key>
<string>How many frames to wait for until it's time to render the probe. E.g., every other frame (1), every two frames (2), every three frames (3) etc.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>RenderHeroProbeConservativeUpdateMultiplier</key>
<map>
<key>Comment</key>
<string>How many probe updates to wait until it's time to update faces that are not directly facing the camera. Acts as a multiplier. E.g., frames to the periphery of the camera updating once every 3 updates, vs ones directly facing the camera updating every update.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>16</integer>
</map> </map>
<key>RenderReflectionProbeVolumes</key> <key>RenderReflectionProbeVolumes</key>
<map> <map>
@ -12400,6 +12510,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key> <key>Value</key>
<integer>64</integer> <integer>64</integer>
</map> </map>
<key>RenderReservedTextureIndices</key>
<map>
<key>Comment</key>
<string>Count of texture indices to reserve for shadow and reflection maps when using indexed texture rendering. Probably only want to set from the login screen.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>14</integer>
</map>
<key>RenderResolutionDivisor</key> <key>RenderResolutionDivisor</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -12556,6 +12677,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>F32</string> <string>F32</string>
<key>Value</key> <key>Value</key>
<real>0.5</real> <real>0.5</real>
</map>
<key>RenderDiffuseLuminanceScale</key>
<map>
<key>Comment</key>
<string>Luminance adjustment for diffuse surfaces to aid auto-exposure behavior</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.5</real>
</map> </map>
<key>RenderShaderLODThreshold</key> <key>RenderShaderLODThreshold</key>
<map> <map>
@ -12621,7 +12753,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>RenderTerrainScale</key> <key>RenderTerrainScale</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Terrain detail texture scale</string> <string>Terrain detail texture scale (meters)</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@ -12629,6 +12761,83 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key> <key>Value</key>
<real>12.0</real> <real>12.0</real>
</map> </map>
<key>RenderTerrainPBREnabled</key>
<map>
<key>Comment</key>
<string>EXPERIMENTAL: Enable PBR Terrain features.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderTerrainPBRForce</key>
<map>
<key>Comment</key>
<string>Force-load PBR terrain if enabled</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderTerrainPBRDetail</key>
<map>
<key>Comment</key>
<string>Detail level for PBR terrain. 0 is full detail. Negative values drop rendering features, in accordance with the GLTF specification when possible, which reduces the number of texture binds.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderTerrainPBRScale</key>
<map>
<key>Comment</key>
<string>PBR terrain detail texture scale (meters)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>8.0</real>
</map>
<key>RenderTerrainPBRPlanarSampleCount</key>
<map>
<key>Comment</key>
<string>How many UV planes to sample PBR terrain textures from. 1 is "flat", 3 is triplanar mapping (aka box mapping)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>3</real>
</map>
<key>RenderTerrainPBRTriplanarBlendFactor</key>
<map>
<key>Comment</key>
<string>Higher values create sharper transitions, but are more likely to produce artifacts.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>8.0</real>
</map>
<key>RenderTerrainPBRNormalsEnabled</key>
<map>
<key>Comment</key>
<string>EXPERIMENTAL: Change normal gen for PBR Terrain.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderTrackerBeacon</key> <key>RenderTrackerBeacon</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -15563,6 +15772,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key> <key>Value</key>
<integer>2</integer> <integer>2</integer>
</map> </map>
<key>UIPreviewMaterial</key>
<map>
<key>Comment</key>
<string>Whether or not PBR material swatch is enabled</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
</map>
<key>UIResizeBarHeight</key> <key>UIResizeBarHeight</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -17881,7 +18101,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key> <key>Type</key>
<string>S32</string> <string>S32</string>
<key>Value</key> <key>Value</key>
<integer>2048</integer> <integer>1024</integer>
</map> </map>
<key>max_texture_dimension_Y</key> <key>max_texture_dimension_Y</key>
<map> <map>
@ -17892,7 +18112,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Type</key> <key>Type</key>
<string>S32</string> <string>S32</string>
<key>Value</key> <key>Value</key>
<integer>2048</integer> <integer>1024</integer>
</map> </map>
<!-- End of back compatibility settings --> <!-- End of back compatibility settings -->
<key>teleport_offer_invitation_max_length</key> <key>teleport_offer_invitation_max_length</key>
@ -19352,6 +19572,50 @@ Change of this parameter will affect the layout of buttons in notification toast
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map>
<key>LocalTerrainAsset1</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset2</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset3</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map>
<key>LocalTerrainAsset4</key>
<map>
<key>Comment</key>
<string>If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>00000000-0000-0000-0000-000000000000</string>
</map> </map>
<key>PathfindingRetrieveNeighboringRegion</key> <key>PathfindingRetrieveNeighboringRegion</key>
<map> <map>

View File

@ -26,6 +26,7 @@
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
uniform mat4 modelview_matrix;
in vec3 position; in vec3 position;
in vec3 normal; in vec3 normal;
@ -35,10 +36,12 @@ in vec2 texcoord0;
out vec3 vary_normal; out vec3 vary_normal;
out vec4 vertex_color; out vec4 vertex_color;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec3 vary_position;
void main() void main()
{ {
//transform vertex //transform vertex
vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;

View File

@ -25,7 +25,7 @@
/*[EXTRA_CODE_HERE]*/ /*[EXTRA_CODE_HERE]*/
out vec4 frag_data[3]; out vec4 frag_data[4];
uniform sampler2D diffuseMap; uniform sampler2D diffuseMap;
@ -33,11 +33,14 @@ uniform float minimum_alpha;
in vec3 vary_normal; in vec3 vary_normal;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec3 vary_position;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec4 diff = texture(diffuseMap, vary_texcoord0.xy); vec4 diff = texture(diffuseMap, vary_texcoord0.xy);
if (diff.a < minimum_alpha) if (diff.a < minimum_alpha)
@ -48,6 +51,7 @@ void main()
frag_data[0] = vec4(diff.rgb, 0.0); frag_data[0] = vec4(diff.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0);
} }

View File

@ -35,6 +35,7 @@ in vec4 weight;
out vec3 vary_normal; out vec3 vary_normal;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec3 vary_position;
void main() void main()
{ {
@ -57,6 +58,7 @@ void main()
vary_normal = norm; vary_normal = norm;
vary_position = pos.xyz;
gl_Position = projection_matrix * pos; gl_Position = projection_matrix * pos;
} }

View File

@ -40,12 +40,12 @@ uniform float kern_scale;
in vec2 vary_fragcoord; in vec2 vary_fragcoord;
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
vec3 getNorm(vec2 pos_screen); vec4 getNorm(vec2 pos_screen);
void main() void main()
{ {
vec2 tc = vary_fragcoord.xy; vec2 tc = vary_fragcoord.xy;
vec3 norm = getNorm(tc); vec4 norm = getNorm(tc);
vec3 pos = getPosition(tc).xyz; vec3 pos = getPosition(tc).xyz;
vec4 ccol = texture(lightMap, tc).rgba; vec4 ccol = texture(lightMap, tc).rgba;

View File

@ -37,11 +37,13 @@ in vec3 vary_mat2;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec3 vary_position;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec4 col = texture(diffuseMap, vary_texcoord0.xy); vec4 col = texture(diffuseMap, vary_texcoord0.xy);
if(col.a < minimum_alpha) if(col.a < minimum_alpha)
@ -60,6 +62,6 @@ void main()
frag_data[1] = vertex_color.aaaa; // spec 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 //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); vec3 nvn = normalize(tnorm);
frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(vertex_color.a, 0, 0, 0);
} }

View File

@ -23,6 +23,7 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
uniform mat4 modelview_matrix;
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
@ -38,11 +39,11 @@ out vec3 vary_mat1;
out vec3 vary_mat2; out vec3 vary_mat2;
out vec4 vertex_color; out vec4 vertex_color;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec3 vary_position;
#ifdef HAS_SKIN #ifdef HAS_SKIN
mat4 getObjectSkinnedTransform(); mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix; uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
#endif #endif
void main() void main()
@ -52,11 +53,13 @@ void main()
mat4 mat = getObjectSkinnedTransform(); mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat; mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
vary_position = pos;
gl_Position = projection_matrix*vec4(pos, 1.0); gl_Position = projection_matrix*vec4(pos, 1.0);
vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz);
vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz);
#else #else
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vec3 n = normalize(normal_matrix * normal); vec3 n = normalize(normal_matrix * normal);
vec3 t = normalize(normal_matrix * tangent.xyz); vec3 t = normalize(normal_matrix * tangent.xyz);

View File

@ -50,6 +50,7 @@ SOFTWARE.
uniform sampler2D normalMap; uniform sampler2D normalMap;
uniform sampler2D depthMap; uniform sampler2D depthMap;
uniform sampler2D emissiveRect;
uniform sampler2D projectionMap; // rgba uniform sampler2D projectionMap; // rgba
uniform sampler2D brdfLut; uniform sampler2D brdfLut;
@ -140,40 +141,11 @@ vec2 getScreenCoordinate(vec2 screenpos)
return sc - vec2(1.0, 1.0); return sc - vec2(1.0, 1.0);
} }
// See: https://aras-p.info/texts/CompactNormalStorage.html vec4 getNorm(vec2 screenpos)
// Method #4: Spheremap Transform, Lambert Azimuthal Equal-Area projection
vec3 getNorm(vec2 screenpos)
{ {
vec2 enc = texture(normalMap, screenpos.xy).xy; vec4 norm = texture(normalMap, screenpos.xy);
vec2 fenc = enc*4-2; norm.xyz = normalize(norm.xyz);
float f = dot(fenc,fenc); return norm;
float g = sqrt(1-f/4);
vec3 n;
n.xy = fenc*g;
n.z = 1-f/2;
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 = texture(normalMap, screenpos.xy);
n = getNormalFromPacked( packedNormalEnvIntensityFlags );
envIntensity = packedNormalEnvIntensityFlags.z;
return packedNormalEnvIntensityFlags;
} }
// get linear depth value given a depth buffer sample d and znear and zfar values // get linear depth value given a depth buffer sample d and znear and zfar values

View File

@ -31,14 +31,18 @@ uniform float minimum_alpha;
uniform sampler2D diffuseMap; uniform sampler2D diffuseMap;
in vec3 vary_position;
in vec3 vary_normal; in vec3 vary_normal;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color; vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color;
if (col.a < minimum_alpha) if (col.a < minimum_alpha)
@ -49,7 +53,7 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0); frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -28,16 +28,19 @@
out vec4 frag_data[4]; out vec4 frag_data[4];
in vec3 vary_normal; in vec3 vary_normal;
in vec3 vary_position;
uniform float minimum_alpha; uniform float minimum_alpha;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color; vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color;
if (col.a < minimum_alpha) if (col.a < minimum_alpha)
@ -48,6 +51,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0); frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -34,8 +34,6 @@ uniform sampler2D diffuseMap;
in vec3 vary_normal; in vec3 vary_normal;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n);
void main() void main()
{ {
vec4 col = texture(diffuseMap, vary_texcoord0.xy); vec4 col = texture(diffuseMap, vary_texcoord0.xy);
@ -48,7 +46,7 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0); frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); // spec frag_data[1] = vec4(0,0,0,0); // spec
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -32,17 +32,19 @@ uniform sampler2D diffuseMap;
in vec3 vary_normal; in vec3 vary_normal;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec3 vary_position;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb; vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb;
frag_data[0] = vec4(col, 0.0); frag_data[0] = vec4(col, 0.0);
frag_data[1] = vertex_color.aaaa; // spec 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 //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); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(vertex_color.a, 0, 0, 0);
} }

View File

@ -30,12 +30,14 @@ out vec4 frag_data[4];
in vec3 vary_normal; in vec3 vary_normal;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec3 vary_position;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
vec3 linear_to_srgb(vec3 c); vec3 linear_to_srgb(vec3 c);
void main() void main()
{ {
mirrorClip(vary_position);
vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
vec3 spec; vec3 spec;
@ -44,6 +46,6 @@ void main()
frag_data[0] = vec4(col, 0.0); frag_data[0] = vec4(col, 0.0);
frag_data[1] = vec4(spec, vertex_color.a); // spec frag_data[1] = vec4(spec, vertex_color.a); // spec
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(vertex_color.a, 0, 0, 0);
} }

View File

@ -36,13 +36,16 @@ out vec3 vary_normal;
out vec4 vertex_color; out vec4 vertex_color;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec3 vary_position;
void passTextureIndex(); void passTextureIndex();
uniform mat4 modelview_matrix;
#ifdef HAS_SKIN #ifdef HAS_SKIN
mat4 getObjectSkinnedTransform(); mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix; uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
#endif #endif
void main() void main()
@ -51,9 +54,11 @@ void main()
mat4 mat = getObjectSkinnedTransform(); mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat; mat = modelview_matrix * mat;
vec4 pos = mat * vec4(position.xyz, 1.0); vec4 pos = mat * vec4(position.xyz, 1.0);
vary_position = pos.xyz;
gl_Position = projection_matrix * pos; gl_Position = projection_matrix * pos;
vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
#else #else
vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_normal = normalize(normal_matrix * normal); vary_normal = normalize(normal_matrix * normal);
#endif #endif

View File

@ -28,7 +28,9 @@
out vec4 frag_color; out vec4 frag_color;
uniform sampler2D emissiveRect; uniform sampler2D emissiveRect;
#ifdef USE_LAST_EXPOSURE
uniform sampler2D exposureMap; uniform sampler2D exposureMap;
#endif
uniform float dt; uniform float dt;
uniform vec2 noiseVec; uniform vec2 noiseVec;
@ -52,9 +54,11 @@ void main()
L = pow(L, 2.0); L = pow(L, 2.0);
float s = mix(dynamic_exposure_params.z, dynamic_exposure_params.y, L); float s = mix(dynamic_exposure_params.z, dynamic_exposure_params.y, L);
#ifdef USE_LAST_EXPOSURE
float prev = texture(exposureMap, vec2(0.5,0.5)).r; float prev = texture(exposureMap, vec2(0.5,0.5)).r;
s = mix(prev, s, min(dt*2.0*abs(prev-s), 0.04)); s = mix(prev, s, min(dt*2.0*abs(prev-s), 0.04));
#endif
frag_color = max(vec4(s, s, s, dt), vec4(0.0)); frag_color = max(vec4(s, s, s, dt), vec4(0.0));
} }

View File

@ -50,9 +50,11 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
#endif #endif
void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
#ifdef IS_ALPHA #ifdef IS_ALPHA
waterClip(vary_position.xyz); waterClip(vary_position.xyz);
#endif #endif

View File

@ -0,0 +1,45 @@
/**
* @file class1/deferred/globalF.glsl
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2024, 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$
*/
// Global helper functions included in every fragment shader
// DO NOT declare sampler uniforms here as OS X doesn't compile
// them out
uniform float mirror_flag;
uniform vec4 clipPlane;
uniform float clipSign;
void mirrorClip(vec3 pos)
{
if (mirror_flag > 0)
{
if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0)
{
discard;
}
}
}

View File

@ -37,7 +37,6 @@ uniform sampler2D specularMap;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
vec3 linear_to_srgb(vec3 c); vec3 linear_to_srgb(vec3 c);
vec2 encode_normal (vec3 n);
void main() void main()
{ {
@ -53,6 +52,6 @@ void main()
frag_data[0] = vec4(col.rgb, 0.0); frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = spec; frag_data[1] = spec;
frag_data[2] = vec4(encode_normal(norm.xyz),0,GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(norm.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -34,6 +34,8 @@ in vec2 vary_fragcoord;
uniform sampler2D diffuseRect; uniform sampler2D diffuseRect;
uniform sampler2D emissiveRect; uniform sampler2D emissiveRect;
uniform sampler2D normalMap;
uniform float diffuse_luminance_scale;
float lum(vec3 col) float lum(vec3 col)
{ {
@ -45,7 +47,21 @@ void main()
{ {
vec2 tc = vary_fragcoord*0.6+0.2; vec2 tc = vary_fragcoord*0.6+0.2;
tc.y -= 0.1; // HACK - nudge exposure sample down a little bit to favor ground over sky tc.y -= 0.1; // HACK - nudge exposure sample down a little bit to favor ground over sky
vec3 c = texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb; vec3 c = texture(diffuseRect, tc).rgb;
vec4 norm = texture(normalMap, tc);
if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI) &&
!GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS))
{
// Apply the diffuse luminance scale to objects but not the sky
// Prevents underexposing when looking at bright environments
// while still allowing for realistically bright skies.
c *= diffuse_luminance_scale;
}
c += texture(emissiveRect, tc).rgb;
float L = lum(c); float L = lum(c);
frag_color = vec4(max(L, 0.0)); frag_color = vec4(max(L, 0.0));
} }

View File

@ -28,25 +28,18 @@
#define DIFFUSE_ALPHA_MODE_MASK 2 #define DIFFUSE_ALPHA_MODE_MASK 2
#define DIFFUSE_ALPHA_MODE_EMISSIVE 3 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3
#ifdef HAS_SKIN
uniform mat4 modelview_matrix; uniform mat4 modelview_matrix;
uniform mat4 projection_matrix; uniform mat4 projection_matrix;
uniform mat4 modelview_projection_matrix;
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform(); mat4 getObjectSkinnedTransform();
#else #else
uniform mat3 normal_matrix; 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 #endif
out vec3 vary_position; out vec3 vary_position;
#endif
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
in vec3 position; in vec3 position;
@ -85,9 +78,7 @@ void main()
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
vary_position = pos; vary_position = pos;
#endif
gl_Position = projection_matrix*vec4(pos,1.0); gl_Position = projection_matrix*vec4(pos,1.0);
@ -133,10 +124,8 @@ void main()
vertex_color = diffuse_color; vertex_color = diffuse_color;
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
#if !defined(HAS_SKIN) #if !defined(HAS_SKIN)
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
#endif #endif
#endif
} }

View File

@ -55,7 +55,7 @@ void main()
frag_data[0] = vec4(0); frag_data[0] = vec4(0);
frag_data[1] = vec4(0.0); frag_data[1] = vec4(0.0);
frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS);
frag_data[3] = vec4(c.rgb, c.a); frag_data[3] = vec4(c.rgb, c.a);
// Added and commented out for a ground truth. Do not uncomment - Geenz // Added and commented out for a ground truth. Do not uncomment - Geenz

View File

@ -35,7 +35,7 @@ uniform float minimum_alpha;
void main() void main()
{ {
float alpha = texture(diffuseMap,vary_texcoord0.xy).a; float alpha = texture(diffuseMap,vary_texcoord0.xy).a * vertex_color.a;
if (alpha < minimum_alpha) if (alpha < minimum_alpha)
{ {

View File

@ -54,21 +54,31 @@ in vec2 emissive_texcoord;
uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
vec2 encode_normal(vec3 n);
vec3 linear_to_srgb(vec3 c); vec3 linear_to_srgb(vec3 c);
vec3 srgb_to_linear(vec3 c); vec3 srgb_to_linear(vec3 c);
uniform vec4 clipPlane;
uniform float clipSign;
void mirrorClip(vec3 pos);
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
void main() void main()
{ {
mirrorClip(vary_position);
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
basecolor.rgb = srgb_to_linear(basecolor.rgb);
basecolor *= vertex_color;
if (basecolor.a < minimum_alpha) if (basecolor.a < minimum_alpha)
{ {
discard; discard;
} }
vec3 col = vertex_color.rgb * srgb_to_linear(basecolor.rgb); vec3 col = basecolor.rgb;
// from mikktspace.com // from mikktspace.com
vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0; vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0;
@ -102,8 +112,8 @@ void main()
//emissive = tnorm*0.5+0.5; //emissive = tnorm*0.5+0.5;
// See: C++: addDeferredAttachments(), GLSL: softenLightF // See: C++: addDeferredAttachments(), GLSL: softenLightF
frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse
frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[1] = max(vec4(spec.rgb,0.0), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal.
frag_data[2] = max(vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags
frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive
} }

View File

@ -28,8 +28,9 @@
//deferred opaque implementation //deferred opaque implementation
#ifdef HAS_SKIN
uniform mat4 modelview_matrix; uniform mat4 modelview_matrix;
#ifdef HAS_SKIN
uniform mat4 projection_matrix; uniform mat4 projection_matrix;
mat4 getObjectSkinnedTransform(); mat4 getObjectSkinnedTransform();
#else #else
@ -59,6 +60,7 @@ out vec4 vertex_color;
out vec3 vary_tangent; out vec3 vary_tangent;
flat out float vary_sign; flat out float vary_sign;
out vec3 vary_normal; out vec3 vary_normal;
out vec3 vary_position;
vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
@ -71,10 +73,11 @@ void main()
mat = modelview_matrix * mat; mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; vec3 pos = (mat*vec4(position.xyz,1.0)).xyz;
vary_position = pos;
gl_Position = projection_matrix*vec4(pos,1.0); gl_Position = projection_matrix*vec4(pos,1.0);
#else #else
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
//transform vertex //transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
#endif #endif

View File

@ -0,0 +1,347 @@
/**
* @file class1\deferred\terrainF.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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 TERRAIN_PBR_DETAIL_EMISSIVE 0
#define TERRAIN_PBR_DETAIL_OCCLUSION -1
#define TERRAIN_PBR_DETAIL_NORMAL -2
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
#define TerrainCoord vec4[2]
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
#define TerrainCoord vec2
#endif
#define MIX_X 1 << 3
#define MIX_Y 1 << 4
#define MIX_Z 1 << 5
#define MIX_W 1 << 6
struct TerrainMix
{
vec4 weight;
int type;
};
TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal);
struct PBRMix
{
vec4 col; // RGB color with alpha, linear space
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
vec3 orm; // Occlusion, roughness, metallic
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
vec2 rm; // Roughness, metallic
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
vec3 vNt; // Unpacked normal texture sample, vector
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
vec3 emissive; // RGB emissive color, linear space
#endif
};
PBRMix init_pbr_mix();
PBRMix terrain_sample_and_multiply_pbr(
TerrainCoord terrain_coord
, sampler2D tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, sampler2D tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, sampler2D tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
, vec4 factor_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, vec3 factor_orm
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, vec2 factor_rm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
);
PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight);
out vec4 frag_data[4];
uniform sampler2D alpha_ramp;
// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures
uniform sampler2D detail_0_base_color;
uniform sampler2D detail_1_base_color;
uniform sampler2D detail_2_base_color;
uniform sampler2D detail_3_base_color;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
uniform sampler2D detail_0_normal;
uniform sampler2D detail_1_normal;
uniform sampler2D detail_2_normal;
uniform sampler2D detail_3_normal;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
uniform sampler2D detail_0_metallic_roughness;
uniform sampler2D detail_1_metallic_roughness;
uniform sampler2D detail_2_metallic_roughness;
uniform sampler2D detail_3_metallic_roughness;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
uniform sampler2D detail_0_emissive;
uniform sampler2D detail_1_emissive;
uniform sampler2D detail_2_emissive;
uniform sampler2D detail_3_emissive;
#endif
uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
uniform vec4 metallicFactors;
uniform vec4 roughnessFactors;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
uniform vec3[4] emissiveColors;
#endif
uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff()
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
in vec4[2] vary_coords;
#endif
in vec3 vary_position;
in vec3 vary_normal;
in vec3 vary_tangent;
flat in float vary_sign;
in vec4 vary_texcoord0;
in vec4 vary_texcoord1;
void mirrorClip(vec3 position);
float terrain_mix(TerrainMix tm, vec4 tms4);
void main()
{
// Make sure we clip the terrain if we're in a mirror.
mirrorClip(vary_position);
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
TerrainCoord terrain_texcoord = vary_coords;
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
TerrainCoord terrain_texcoord = vary_texcoord0.xy;
#endif
float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a;
float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a;
float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a;
TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
// RGB = Occlusion, Roughness, Metal
// default values, see LLViewerTexture::sDefaultPBRORMImagep
// occlusion 1.0
// roughness 0.0
// metal 0.0
vec3[4] orm_factors;
orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x);
orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y);
orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z);
orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w);
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
vec2[4] rm_factors;
rm_factors[0] = vec2(roughnessFactors.x, metallicFactors.x);
rm_factors[1] = vec2(roughnessFactors.y, metallicFactors.y);
rm_factors[2] = vec2(roughnessFactors.z, metallicFactors.z);
rm_factors[3] = vec2(roughnessFactors.w, metallicFactors.w);
#endif
PBRMix pbr_mix = init_pbr_mix();
PBRMix mix2;
switch (tm.type & MIX_X)
{
case MIX_X:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_0_base_color
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, detail_0_metallic_roughness
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, detail_0_normal
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_0_emissive
#endif
, baseColorFactors[0]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, orm_factors[0]
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, rm_factors[0]
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[0]
#endif
);
pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.x);
break;
default:
break;
}
switch (tm.type & MIX_Y)
{
case MIX_Y:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_1_base_color
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, detail_1_metallic_roughness
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, detail_1_normal
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_1_emissive
#endif
, baseColorFactors[1]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, orm_factors[1]
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, rm_factors[1]
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[1]
#endif
);
pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.y);
break;
default:
break;
}
switch (tm.type & MIX_Z)
{
case MIX_Z:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_2_base_color
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, detail_2_metallic_roughness
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, detail_2_normal
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_2_emissive
#endif
, baseColorFactors[2]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, orm_factors[2]
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, rm_factors[2]
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[2]
#endif
);
pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.z);
break;
default:
break;
}
switch (tm.type & MIX_W)
{
case MIX_W:
mix2 = terrain_sample_and_multiply_pbr(
terrain_texcoord
, detail_3_base_color
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, detail_3_metallic_roughness
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, detail_3_normal
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, detail_3_emissive
#endif
, baseColorFactors[3]
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, orm_factors[3]
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, rm_factors[3]
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, emissiveColors[3]
#endif
);
pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.w);
break;
default:
break;
}
float minimum_alpha = terrain_mix(tm, minimum_alphas);
if (pbr_mix.col.a < minimum_alpha)
{
discard;
}
float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z));
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
// from mikktspace.com
vec3 vNt = pbr_mix.vNt;
vec3 vN = vary_normal;
vec3 vT = vary_tangent.xyz;
vec3 vB = vary_sign * cross(vN, vT);
vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN );
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
#else
vec3 tnorm = vary_normal;
tnorm *= gl_FrontFacing ? 1.0 : -1.0;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
#define mix_emissive pbr_mix.emissive
#else
#define mix_emissive vec3(0)
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
#define mix_orm pbr_mix.orm
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
#define mix_orm vec3(1.0, pbr_mix.rm)
#else
// Matte plastic potato terrain
#define mix_orm vec3(1.0, 1.0, 0.0)
#endif
frag_data[0] = max(vec4(pbr_mix.col.xyz, 0.0), vec4(0)); // Diffuse
frag_data[1] = max(vec4(mix_orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal.
frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, flags
frag_data[3] = max(vec4(mix_emissive,0), vec4(0)); // PBR sRGB Emissive
}

View File

@ -0,0 +1,473 @@
/**
* @file class1\deferred\pbrterrainUtilF.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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]*/
/**
* Triplanar mapping implementation adapted from Inigo Quilez' example shader,
* MIT license.
* https://www.shadertoy.com/view/MtsGWH
* Copyright © 2015 Inigo Quilez
* 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 TERRAIN_PBR_DETAIL_EMISSIVE 0
#define TERRAIN_PBR_DETAIL_OCCLUSION -1
#define TERRAIN_PBR_DETAIL_NORMAL -2
#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3
in vec3 vary_vertex_normal;
vec3 srgb_to_linear(vec3 c);
// A relatively agressive threshold for terrain material mixing sampling
// cutoff. This ensures that only one or two materials are used in most places,
// making PBR terrain blending more performant. Should be greater than 0 to work.
#define TERRAIN_RAMP_MIX_THRESHOLD 0.1
// A small threshold for triplanar mapping sampling cutoff. This and
// TERRAIN_TRIPLANAR_BLEND_FACTOR together ensures that only one or two samples
// per texture are used in most places, making triplanar mapping more
// performant. Should be greater than 0 to work.
// There's also an artistic design choice in the use of these factors, and the
// use of triplanar generally. Don't take these triplanar constants for granted.
#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01
#define SAMPLE_X 1 << 0
#define SAMPLE_Y 1 << 1
#define SAMPLE_Z 1 << 2
#define MIX_X 1 << 3
#define MIX_Y 1 << 4
#define MIX_Z 1 << 5
#define MIX_W 1 << 6
struct PBRMix
{
vec4 col; // RGB color with alpha, linear space
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
vec3 orm; // Occlusion, roughness, metallic
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
vec2 rm; // Roughness, metallic
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
vec3 vNt; // Unpacked normal texture sample, vector
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
vec3 emissive; // RGB emissive color, linear space
#endif
};
PBRMix init_pbr_mix()
{
PBRMix mix;
mix.col = vec4(0);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
mix.orm = vec3(0);
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
mix.rm = vec2(0);
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
mix.vNt = vec3(0);
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = vec3(0);
#endif
return mix;
}
// Usage example, for two weights:
// vec2 weights = ... // Weights must add up to 1
// PBRMix mix = init_pbr_mix();
// PBRMix mix1 = ...
// mix = mix_pbr(mix, mix1, weights.x);
// PBRMix mix2 = ...
// mix = mix_pbr(mix, mix2, weights.y);
PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight)
{
PBRMix mix;
mix.col = mix1.col + (mix2.col * mix2_weight);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
mix.orm = mix1.orm + (mix2.orm * mix2_weight);
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
mix.rm = mix1.rm + (mix2.rm * mix2_weight);
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight);
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = mix1.emissive + (mix2.emissive * mix2_weight);
#endif
return mix;
}
PBRMix sample_pbr(
vec2 uv
, sampler2D tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, sampler2D tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, sampler2D tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
)
{
PBRMix mix;
mix.col = texture(tex_col, uv);
mix.col.rgb = srgb_to_linear(mix.col.rgb);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
mix.orm = texture(tex_orm, uv).xyz;
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
mix.rm = texture(tex_orm, uv).yz;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive = srgb_to_linear(texture(tex_emissive, uv).xyz);
#endif
return mix;
}
struct TerrainTriplanar
{
vec3 weight;
int type;
};
struct TerrainMix
{
vec4 weight;
int type;
};
#define TerrainMixSample vec4[4]
#define TerrainMixSample3 vec3[4]
TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal)
{
TerrainMix tm;
vec4 sample_x = vec4(1,0,0,0);
vec4 sample_y = vec4(0,1,0,0);
vec4 sample_z = vec4(0,0,1,0);
vec4 sample_w = vec4(0,0,0,1);
tm.weight = mix( mix(sample_w, sample_z, alpha2), mix(sample_y, sample_x, alpha1), alphaFinal );
tm.weight -= TERRAIN_RAMP_MIX_THRESHOLD;
ivec4 usage = max(ivec4(0), ivec4(ceil(tm.weight)));
// Prevent negative weights and keep weights balanced
tm.weight = tm.weight*vec4(usage);
tm.weight /= (tm.weight.x + tm.weight.y + tm.weight.z + tm.weight.w);
tm.type = (usage.x * MIX_X) |
(usage.y * MIX_Y) |
(usage.z * MIX_Z) |
(usage.w * MIX_W);
return tm;
}
TerrainTriplanar _t_triplanar()
{
float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR;
float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD;
vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness));
weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z);
weight_signed -= vec3(threshold);
TerrainTriplanar tw;
// *NOTE: Make sure the threshold doesn't affect the materials
tw.weight = max(vec3(0), weight_signed);
tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z);
ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed))));
tw.type = ((usage.x) * SAMPLE_X) |
((usage.y) * SAMPLE_Y) |
((usage.z) * SAMPLE_Z);
return tw;
}
// Assume weights add to 1
float terrain_mix(TerrainMix tm, vec4 tms4)
{
return (tm.weight.x * tms4[0]) +
(tm.weight.y * tms4[1]) +
(tm.weight.z * tms4[2]) +
(tm.weight.w * tms4[3]);
}
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
// Triplanar mapping
// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused)
#define TerrainCoord vec4[2]
vec2 _t_uv(vec2 uv_unflipped, float sign_or_zero)
{
// Handle case where sign is 0
float sign = (2.0*sign_or_zero) + 1.0;
sign /= abs(sign);
// If the vertex normal is negative, flip the texture back
// right-side up.
vec2 uv = uv_unflipped * vec2(sign, 1);
return uv;
}
vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero)
{
// Assume normal is unpacked
vec3 vNt1 = vNt0;
// Get sign
float sign = sign_or_zero;
// Handle case where sign is 0
sign = (2.0*sign) + 1.0;
sign /= abs(sign);
// If the sign is negative, rotate normal by 180 degrees
vNt1.xy = (min(0, sign) * vNt1.xy) + (min(0, -sign) * -vNt1.xy);
return vNt1;
}
// Triplanar-specific normal texture fixes
vec3 _t_normal_post_x(vec3 vNt0)
{
vec3 vNt_x = _t_normal_post_1(vNt0, sign(vary_vertex_normal.x));
// *HACK: Transform normals according to orientation of the UVs
vNt_x.xy = vec2(-vNt_x.y, vNt_x.x);
return vNt_x;
}
vec3 _t_normal_post_y(vec3 vNt0)
{
vec3 vNt_y = _t_normal_post_1(vNt0, sign(vary_vertex_normal.y));
// *HACK: Transform normals according to orientation of the UVs
vNt_y.xy = -vNt_y.xy;
return vNt_y;
}
vec3 _t_normal_post_z(vec3 vNt0)
{
vec3 vNt_z = _t_normal_post_1(vNt0, sign(vary_vertex_normal.z));
return vNt_z;
}
PBRMix terrain_sample_pbr(
TerrainCoord terrain_coord
, TerrainTriplanar tw
, sampler2D tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, sampler2D tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, sampler2D tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
)
{
PBRMix mix = init_pbr_mix();
#define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x))
#define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y))
#define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z))
switch (tw.type & SAMPLE_X)
{
case SAMPLE_X:
PBRMix mix_x = sample_pbr(
get_uv_x()
, tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
// Triplanar-specific normal texture fix
mix_x.vNt = _t_normal_post_x(mix_x.vNt);
#endif
mix = mix_pbr(mix, mix_x, tw.weight.x);
break;
default:
break;
}
switch (tw.type & SAMPLE_Y)
{
case SAMPLE_Y:
PBRMix mix_y = sample_pbr(
get_uv_y()
, tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
// Triplanar-specific normal texture fix
mix_y.vNt = _t_normal_post_y(mix_y.vNt);
#endif
mix = mix_pbr(mix, mix_y, tw.weight.y);
break;
default:
break;
}
switch (tw.type & SAMPLE_Z)
{
case SAMPLE_Z:
PBRMix mix_z = sample_pbr(
get_uv_z()
, tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
// Triplanar-specific normal texture fix
// *NOTE: Bottom face has not been tested
mix_z.vNt = _t_normal_post_z(mix_z.vNt);
#endif
mix = mix_pbr(mix, mix_z, tw.weight.z);
break;
default:
break;
}
return mix;
}
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
#define TerrainCoord vec2
#define terrain_sample_pbr sample_pbr
#endif
PBRMix multiply_factors_pbr(
PBRMix mix_in
, vec4 factor_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, vec3 factor_orm
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, vec2 factor_rm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
)
{
PBRMix mix = mix_in;
mix.col *= factor_col;
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
mix.orm *= factor_orm;
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
mix.rm *= factor_rm;
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
mix.emissive *= factor_emissive;
#endif
return mix;
}
PBRMix terrain_sample_and_multiply_pbr(
TerrainCoord terrain_coord
, sampler2D tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, sampler2D tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, sampler2D tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, sampler2D tex_emissive
#endif
, vec4 factor_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, vec3 factor_orm
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, vec2 factor_rm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, vec3 factor_emissive
#endif
)
{
PBRMix mix = terrain_sample_pbr(
terrain_coord
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
, _t_triplanar()
#endif
, tex_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, tex_orm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL)
, tex_vNt
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, tex_emissive
#endif
);
mix = multiply_factors_pbr(mix
, factor_col
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION)
, factor_orm
#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS)
, factor_rm
#endif
#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE)
, factor_emissive
#endif
);
return mix;
}

View File

@ -0,0 +1,96 @@
/**
* @file class1\environment\pbrterrainV.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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 mat3 normal_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
in vec3 position;
in vec3 normal;
in vec4 tangent;
in vec4 diffuse_color;
in vec2 texcoord1;
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
out vec4[2] vary_coords;
#endif
out vec3 vary_vertex_normal; // Used by pbrterrainUtilF.glsl
out vec3 vary_normal;
out vec3 vary_tangent;
flat out float vary_sign;
out vec4 vary_texcoord0;
out vec4 vary_texcoord1;
out vec3 vary_position;
// *HACK: tangent_space_transform should use texture_normal_transform, or maybe
// we shouldn't use tangent_space_transform at all. See the call to
// tangent_space_transform below.
uniform vec4[2] texture_base_color_transform;
vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform);
vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform);
void main()
{
//transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
vec3 n = normal_matrix * normal;
vary_vertex_normal = normal;
vec3 t = normal_matrix * tangent.xyz;
vary_tangent = normalize(t);
// *TODO: Decide if we want this. It may be better to just calculate the
// tangents on-the-fly in the fragment shader, due to the subtleties of the
// effect of triplanar mapping on UVs.
// *HACK: Should be using texture_normal_transform here. The KHR texture
// transform spec requires handling texture transforms separately for each
// individual texture.
vary_tangent = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform));
vary_sign = tangent.w;
vary_normal = normalize(n);
// Transform and pass tex coords
// *HACK: texture_base_color_transform is used for all of these here, but
// the KHR texture transform spec requires handling texture transforms
// separately for each individual texture.
#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3
// xy
vary_coords[0].xy = terrain_texture_transform(position.xy, texture_base_color_transform);
// yz
vary_coords[0].zw = terrain_texture_transform(position.yz, texture_base_color_transform);
// (-x)z
vary_coords[1].xy = terrain_texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform);
#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1
vary_texcoord0.xy = terrain_texture_transform(position.xy, texture_base_color_transform);
#endif
vec4 tc = vec4(texcoord1,0,1);
vary_texcoord0.zw = tc.xy;
vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0);
vary_texcoord1.zw = tc.xy-vec2(1.0, 0.0);
}

View File

@ -97,6 +97,7 @@ vec3 toneMapACES_Hill(vec3 color)
uniform float exposure; uniform float exposure;
uniform float gamma; uniform float gamma;
uniform float aces_mix;
vec3 toneMap(vec3 color) vec3 toneMap(vec3 color)
{ {
@ -106,7 +107,7 @@ vec3 toneMap(vec3 color)
color *= exposure * exp_scale; color *= exposure * exp_scale;
// mix ACES and Linear here as a compromise to avoid over-darkening legacy content // mix ACES and Linear here as a compromise to avoid over-darkening legacy content
color = mix(toneMapACES_Hill(color), color, 0.3); color = mix(toneMapACES_Hill(color), color, aces_mix);
#endif #endif
return color; return color;
@ -152,6 +153,15 @@ float noise(vec2 x) {
//============================= //=============================
void debugExposure(inout vec3 color)
{
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
exp_scale *= 0.5;
if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1)
{
color = vec3(1,0,0);
}
}
vec3 legacyGamma(vec3 color) vec3 legacyGamma(vec3 color)
{ {
@ -181,6 +191,7 @@ void main()
vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb)); vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
diff.rgb += nz*0.003; diff.rgb += nz*0.003;
//debugExposure(diff.rgb);
frag_color = max(diff, vec4(0)); frag_color = max(diff, vec4(0));
} }

View File

@ -27,6 +27,15 @@
in vec3 vary_HazeColor; in vec3 vary_HazeColor;
in float vary_LightNormPosDot; in float vary_LightNormPosDot;
#ifdef HAS_HDRI
in vec4 vary_position;
in vec3 vary_rel_pos;
uniform float sky_hdr_scale;
uniform float hdri_split_screen;
uniform mat3 env_mat;
uniform sampler2D environmentMap;
#endif
uniform sampler2D rainbow_map; uniform sampler2D rainbow_map;
uniform sampler2D halo_map; uniform sampler2D halo_map;
@ -37,6 +46,9 @@ uniform float ice_level;
out vec4 frag_data[4]; out vec4 frag_data[4];
vec3 srgb_to_linear(vec3 c); vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c);
#define PI 3.14159265
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// The fragment shader for the sky // The fragment shader for the sky
@ -71,12 +83,28 @@ vec3 halo22(float d)
void main() void main()
{ {
vec3 color;
#ifdef HAS_HDRI
vec3 frag_coord = vary_position.xyz/vary_position.w;
if (-frag_coord.x > ((1.0-hdri_split_screen)*2.0-1.0))
{
vec3 pos = normalize(vary_rel_pos);
pos = env_mat * pos;
vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI);
color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale;
color = min(color, vec3(8192*8192*16)); // stupidly large value arrived at by binary search -- avoids framebuffer corruption from some HDRIs
frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_HAS_HDRI);
}
else
#endif
{
// Potential Fill-rate optimization. Add cloud calculation // Potential Fill-rate optimization. Add cloud calculation
// back in and output alpha of 0 (so that alpha culling kills // back in and output alpha of 0 (so that alpha culling kills
// the fragment) if the sky wouldn't show up because the clouds // the fragment) if the sky wouldn't show up because the clouds
// are fully opaque. // are fully opaque.
vec3 color = vary_HazeColor; color = vary_HazeColor;
float rel_pos_lightnorm = vary_LightNormPosDot; float rel_pos_lightnorm = vary_LightNormPosDot;
float optic_d = rel_pos_lightnorm; float optic_d = rel_pos_lightnorm;
@ -86,9 +114,11 @@ void main()
color.rgb *= 2.; color.rgb *= 2.;
color.rgb = clamp(color.rgb, vec3(0), vec3(5)); color.rgb = clamp(color.rgb, vec3(0), vec3(5));
frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS);
}
frag_data[0] = vec4(0); frag_data[0] = vec4(0);
frag_data[1] = vec4(0); frag_data[1] = vec4(0);
frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog
frag_data[3] = vec4(color.rgb, 1.0); frag_data[3] = vec4(color.rgb, 1.0);
} }

View File

@ -35,6 +35,11 @@ in vec3 position;
out vec3 vary_HazeColor; out vec3 vary_HazeColor;
out float vary_LightNormPosDot; out float vary_LightNormPosDot;
#ifdef HAS_HDRI
out vec4 vary_position;
out vec3 vary_rel_pos;
#endif
// Inputs // Inputs
uniform vec3 camPosLocal; uniform vec3 camPosLocal;
@ -72,6 +77,11 @@ void main()
// Get relative position // Get relative position
vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
#ifdef HAS_HDRI
vary_rel_pos = rel_pos;
vary_position = pos;
#endif
// Adj position vector to clamp altitude // Adj position vector to clamp altitude
if (rel_pos.y > 0.) if (rel_pos.y > 0.)
{ {
@ -98,7 +108,7 @@ void main()
vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y); vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights // Calculate relative weights
vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density)); vec3 combined_haze = max(abs(blue_density) + vec3(abs(haze_density)), vec3(1e-6));
vec3 blue_weight = blue_density / combined_haze; vec3 blue_weight = blue_density / combined_haze;
vec3 haze_weight = haze_density / combined_haze; vec3 haze_weight = haze_density / combined_haze;

View File

@ -38,10 +38,11 @@ in vec3 vary_normal;
in vec4 vary_texcoord0; in vec4 vary_texcoord0;
in vec4 vary_texcoord1; in vec4 vary_texcoord1;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 position);
void main() void main()
{ {
mirrorClip(pos);
/// Note: This should duplicate the blending functionality currently used for the terrain rendering. /// Note: This should duplicate the blending functionality currently used for the terrain rendering.
vec4 color0 = texture(detail_0, vary_texcoord0.xy); vec4 color0 = texture(detail_0, vary_texcoord0.xy);
@ -59,7 +60,7 @@ void main()
frag_data[0] = outColor; frag_data[0] = outColor;
frag_data[1] = vec4(0.0,0.0,0.0,-1.0); frag_data[1] = vec4(0.0,0.0,0.0,-1.0);
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -25,12 +25,12 @@
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
in vec3 position; in vec3 position;
in vec3 normal; in vec3 normal;
in vec4 diffuse_color; in vec4 diffuse_color;
in vec2 texcoord0;
in vec2 texcoord1; in vec2 texcoord1;
out vec3 pos; out vec3 pos;
@ -41,18 +41,18 @@ out vec4 vary_texcoord1;
uniform vec4 object_plane_s; uniform vec4 object_plane_s;
uniform vec4 object_plane_t; uniform vec4 object_plane_t;
vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) vec2 texgen_object(vec4 vpos, mat4 mat, vec4 tp0, vec4 tp1)
{ {
vec4 tcoord; vec4 tcoord;
tcoord.x = dot(vpos, tp0); tcoord.x = dot(vpos, tp0);
tcoord.y = dot(vpos, tp1); tcoord.y = dot(vpos, tp1);
tcoord.z = tc.z; tcoord.z = 0;
tcoord.w = tc.w; tcoord.w = 1;
tcoord = mat * tcoord; tcoord = mat * tcoord;
return tcoord; return tcoord.xy;
} }
void main() void main()
@ -62,12 +62,12 @@ void main()
vec4 t_pos = modelview_projection_matrix * pre_pos; vec4 t_pos = modelview_projection_matrix * pre_pos;
gl_Position = t_pos; gl_Position = t_pos;
pos = t_pos.xyz; pos = (modelview_matrix*pre_pos).xyz;
vary_normal = normalize(normal_matrix * normal); vary_normal = normalize(normal_matrix * normal);
// Transform and pass tex coords // Transform and pass tex coords
vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; vary_texcoord0.xy = texgen_object(vec4(position, 1.0), texture_matrix0, object_plane_s, object_plane_t);
vec4 t = vec4(texcoord1,0,1); vec4 t = vec4(texcoord1,0,1);

View File

@ -65,7 +65,7 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl
// Apply texture animation first to avoid shearing and other artifacts // Apply texture animation first to avoid shearing and other artifacts
texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy; texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy;
// Convert to left-handed coordinate system. The offset of 1 is necessary // Convert to left-handed coordinate system. The offset of 1 is necessary
// for rotations to be applied correctly. // for rotation and scale to be applied correctly.
texcoord.y = 1.0 - texcoord.y; texcoord.y = 1.0 - texcoord.y;
texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy); texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy);
// Convert back to right-handed coordinate system // Convert back to right-handed coordinate system
@ -77,6 +77,19 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl
return texcoord; return texcoord;
} }
// Similar to texture_transform but no offset during coordinate system
// conversion, and no texture animation support.
vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform)
{
vec2 texcoord = vertex_texcoord;
texcoord.y = -texcoord.y;
texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy);
texcoord.y = -texcoord.y;
return texcoord;
}
// Take the rotation only from both transforms and apply to the tangent. This // Take the rotation only from both transforms and apply to the tangent. This
// accounts for the change of the topology of the normal texture when a texture // accounts for the change of the topology of the normal texture when a texture
// rotation is applied to it. // rotation is applied to it.
@ -120,3 +133,25 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
} }
// Similar to tangent_space_transform but no no texture animation support.
vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform)
{
// Immediately convert to left-handed coordinate system ((0,1) -> (0, -1))
vec2 weights = vec2(0, -1);
// Apply KHR_texture_transform (rotation only)
float khr_rotation = khr_gltf_transform[0].z;
mat2 khr_rotation_mat = mat2(
cos(khr_rotation),-sin(khr_rotation),
sin(khr_rotation), cos(khr_rotation)
);
weights = khr_rotation_mat * weights;
// Convert back to right-handed coordinate system
weights.y = -weights.y;
vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz);
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
}

View File

@ -32,13 +32,14 @@ uniform sampler2D diffuseMap;
in vec4 vertex_color; in vec4 vertex_color;
in vec3 vary_normal; in vec3 vary_normal;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec3 vary_position;
uniform float minimum_alpha; uniform float minimum_alpha;
vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
vec4 col = texture(diffuseMap, vary_texcoord0.xy); vec4 col = texture(diffuseMap, vary_texcoord0.xy);
if (col.a < minimum_alpha) if (col.a < minimum_alpha)
{ {
@ -48,6 +49,6 @@ void main()
frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0);
frag_data[1] = vec4(0,0,0,0); frag_data[1] = vec4(0,0,0,0);
vec3 nvn = normalize(vary_normal); vec3 nvn = normalize(vary_normal);
frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS);
frag_data[3] = vec4(0); frag_data[3] = vec4(0);
} }

View File

@ -24,6 +24,7 @@
*/ */
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
uniform mat3 normal_matrix; uniform mat3 normal_matrix;
@ -34,11 +35,14 @@ in vec2 texcoord0;
out vec3 vary_normal; out vec3 vary_normal;
out vec4 vertex_color; out vec4 vertex_color;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec3 vary_position;
void main() void main()
{ {
//transform vertex //transform vertex
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
vary_normal = normalize(normal_matrix * normal); vary_normal = normalize(normal_matrix * normal);

View File

@ -1,9 +1,9 @@
/** /**
* @file encodeNormF.glsl * @file normaldebugF.glsl
* *
* $LicenseInfo:firstyear=2018&license=viewerlgpl$ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2018, Linden Research, Inc. * Copyright (C) 2023, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -23,12 +23,11 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
// Lambert Azimuthal Equal-Area projection out vec4 frag_color;
// See: https://aras-p.info/texts/CompactNormalStorage.html
// Also see: A_bit_more_deferred_-_CryEngine3.ppt
vec2 encode_normal(vec3 n)
{
float f = sqrt(8 * n.z + 8);
return n.xy / f + 0.5;
}
in vec4 vertex_color;
void main()
{
frag_color = max(vertex_color, vec4(0));
}

View File

@ -0,0 +1,76 @@
/**
* @file normaldebugG.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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$
*/
// *NOTE: Geometry shaders have a reputation for being slow. Consider using
// compute shaders instead, which have a reputation for being fast. This
// geometry shader in particular seems to run fine on my machine, but I won't
// vouch for this in performance-critical areas.
// -Cosmic,2023-09-28
out vec4 vertex_color;
in vec4 normal_g[];
#ifdef HAS_ATTRIBUTE_TANGENT
in vec4 tangent_g[];
#endif
layout(triangles) in;
#ifdef HAS_ATTRIBUTE_TANGENT
layout(line_strip, max_vertices = 12) out;
#else
layout(line_strip, max_vertices = 6) out;
#endif
void triangle_normal_debug(int i)
{
// Normal
vec4 normal_color = vec4(1.0, 1.0, 0.0, 1.0);
gl_Position = gl_in[i].gl_Position;
vertex_color = normal_color;
EmitVertex();
gl_Position = normal_g[i];
vertex_color = normal_color;
EmitVertex();
EndPrimitive();
#ifdef HAS_ATTRIBUTE_TANGENT
// Tangent
vec4 tangent_color = vec4(0.0, 1.0, 1.0, 1.0);
gl_Position = gl_in[i].gl_Position;
vertex_color = tangent_color;
EmitVertex();
gl_Position = tangent_g[i];
vertex_color = tangent_color;
EmitVertex();
EndPrimitive();
#endif
}
void main()
{
triangle_normal_debug(0);
triangle_normal_debug(1);
triangle_normal_debug(2);
}

View File

@ -0,0 +1,74 @@
/**
* @file normaldebugV.glsl
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, 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$
*/
in vec3 position;
in vec3 normal;
out vec4 normal_g;
#ifdef HAS_ATTRIBUTE_TANGENT
in vec4 tangent;
out vec4 tangent_g;
#endif
uniform float debug_normal_draw_length;
#ifdef HAS_SKIN
mat4 getObjectSkinnedTransform();
#else
uniform mat3 normal_matrix;
#endif
uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
// *NOTE: Should use the modelview_projection_matrix here in the non-skinned
// case for efficiency, but opting for the simplier implementation for now as
// this is debug code. Also, the skinned version hasn't beeen tested yet.
// world_pos = mat * vec4(position.xyz, 1.0)
vec4 get_screen_normal(vec3 position, vec4 world_pos, vec3 normal, mat4 mat)
{
vec4 world_norm = mat * vec4((position + normal), 1.0);
world_norm.xyz -= world_pos.xyz;
world_norm.xyz = debug_normal_draw_length * normalize(world_norm.xyz);
world_norm.xyz += world_pos.xyz;
return projection_matrix * world_norm;
}
void main()
{
#ifdef HAS_SKIN
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
#else
#define mat modelview_matrix
#endif
vec4 world_pos = mat * vec4(position.xyz,1.0);
gl_Position = projection_matrix * world_pos;
normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat);
#ifdef HAS_ATTRIBUTE_TANGENT
tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat);
#endif
}

View File

@ -38,6 +38,7 @@ in vec3 vary_dir;
uniform float mipLevel; uniform float mipLevel;
uniform int u_width; uniform int u_width;
uniform float max_probe_lod; uniform float max_probe_lod;
uniform float probe_strength;
// ============================================================================================================= // =============================================================================================================
@ -129,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R)
float totalWeight = 0.0; float totalWeight = 0.0;
float envMapDim = float(textureSize(reflectionProbes, 0).s); float envMapDim = float(textureSize(reflectionProbes, 0).s);
float roughness = mipLevel/max_probe_lod; float roughness = mipLevel/max_probe_lod;
int numSamples = max(int(32*roughness), 1); int numSamples = max(int(PROBE_FILTER_SAMPLES*roughness), 1);
float numMips = max_probe_lod+1; float numMips = max_probe_lod+1;
@ -163,5 +164,6 @@ void main()
{ {
vec3 N = normalize(vary_dir); vec3 N = normalize(vary_dir);
frag_color = max(prefilterEnvMap(N), vec4(0)); frag_color = max(prefilterEnvMap(N), vec4(0));
frag_color.a *= probe_strength;
} }
// ============================================================================================================= // =============================================================================================================

View File

@ -30,9 +30,13 @@ uniform sampler2D texture1;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
in vec2 vary_texcoord1; in vec2 vary_texcoord1;
in vec3 vary_position;
void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
float tex0 = texture(texture0, vary_texcoord0.xy).a; float tex0 = texture(texture0, vary_texcoord0.xy).a;
float tex1 = texture(texture1, vary_texcoord1.xy).a; float tex1 = texture(texture1, vary_texcoord1.xy).a;

View File

@ -23,6 +23,7 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
uniform mat4 modelview_matrix;
uniform mat4 texture_matrix0; uniform mat4 texture_matrix0;
uniform mat4 modelview_projection_matrix; uniform mat4 modelview_projection_matrix;
@ -32,11 +33,11 @@ in vec2 texcoord1;
out vec2 vary_texcoord0; out vec2 vary_texcoord0;
out vec2 vary_texcoord1; out vec2 vary_texcoord1;
out vec3 vary_position;
#ifdef HAS_SKIN #ifdef HAS_SKIN
mat4 getObjectSkinnedTransform(); mat4 getObjectSkinnedTransform();
uniform mat4 projection_matrix; uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
#endif #endif
void main() void main()
@ -46,8 +47,10 @@ void main()
mat4 mat = getObjectSkinnedTransform(); mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat; mat = modelview_matrix * mat;
vec4 pos = mat * vec4(position.xyz, 1.0); vec4 pos = mat * vec4(position.xyz, 1.0);
vary_position = pos.xyz;
gl_Position = projection_matrix * pos; gl_Position = projection_matrix * pos;
#else #else
vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz;
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
#endif #endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;

View File

@ -66,7 +66,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
// I had thought blue_density and haze_density should have equal weighting, // I had thought blue_density and haze_density should have equal weighting,
// but attenuation due to haze_density tends to seem too strong // but attenuation due to haze_density tends to seem too strong
vec3 combined_haze = blue_density + vec3(haze_density); vec3 combined_haze = max(blue_density + vec3(haze_density), vec3(1e-6));
vec3 blue_weight = blue_density / combined_haze; vec3 blue_weight = blue_density / combined_haze;
vec3 haze_weight = vec3(haze_density) / combined_haze; vec3 haze_weight = vec3(haze_density) / combined_haze;
@ -98,7 +98,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
haze_glow *= glow.x; haze_glow *= glow.x;
// higher glow.x gives dimmer glow (because next step is 1 / "angle") // higher glow.x gives dimmer glow (because next step is 1 / "angle")
haze_glow = pow(haze_glow, glow.z); haze_glow = clamp(pow(haze_glow, glow.z), -100000, 100000);
// glow.z should be negative, so we're doing a sort of (1 / "angle") function // glow.z should be negative, so we're doing a sort of (1 / "angle") function
// add "minimum anti-solar illumination" // add "minimum anti-solar illumination"

View File

@ -68,7 +68,6 @@ void waterClip(vec3 pos);
vec3 srgb_to_linear(vec3 c); vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c); vec3 linear_to_srgb(vec3 c);
vec2 encode_normal (vec3 n);
vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
@ -78,6 +77,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
float getAmbientClamp(); float getAmbientClamp();
void mirrorClip(vec3 pos);
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear);
@ -167,6 +168,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
void main() void main()
{ {
mirrorClip(vary_position);
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
vec4 pos = vec4(vary_position, 1.0); vec4 pos = vec4(vary_position, 1.0);

View File

@ -90,6 +90,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear);
void mirrorClip(vec3 pos);
void waterClip(vec3 pos); void waterClip(vec3 pos);
void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor); void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor);
@ -156,6 +157,8 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor,
void main() void main()
{ {
mirrorClip(vary_position);
vec3 color = vec3(0,0,0); vec3 color = vec3(0,0,0);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;

View File

@ -35,7 +35,7 @@ in vec2 vary_fragcoord;
uniform vec3 sun_dir; uniform vec3 sun_dir;
uniform float shadow_bias; uniform float shadow_bias;
vec3 getNorm(vec2 pos_screen); vec4 getNorm(vec2 pos_screen);
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
@ -45,13 +45,13 @@ void main()
{ {
vec2 pos_screen = vary_fragcoord.xy; vec2 pos_screen = vary_fragcoord.xy;
vec4 pos = getPosition(pos_screen); vec4 pos = getPosition(pos_screen);
vec3 norm = getNorm(pos_screen); vec4 norm = getNorm(pos_screen);
vec4 col; vec4 col;
col.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen); col.r = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
col.g = 1.0f; col.g = 1.0f;
col.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen); col.b = sampleSpotShadow(pos.xyz, norm.xyz, 0, pos_screen);
col.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen); col.a = sampleSpotShadow(pos.xyz, norm.xyz, 1, pos_screen);
frag_color = clamp(col, vec4(0), vec4(1)); frag_color = clamp(col, vec4(0), vec4(1));
} }

View File

@ -32,7 +32,7 @@ out vec4 frag_color;
in vec2 vary_fragcoord; in vec2 vary_fragcoord;
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
vec3 getNorm(vec2 pos_screen); vec4 getNorm(vec2 pos_screen);
float sampleDirectionalShadow(vec3 shadow_pos, vec3 norm, vec2 pos_screen); float sampleDirectionalShadow(vec3 shadow_pos, vec3 norm, vec2 pos_screen);
float sampleSpotShadow(vec3 shadow_pos, vec3 norm, int index, vec2 pos_screen); float sampleSpotShadow(vec3 shadow_pos, vec3 norm, int index, vec2 pos_screen);
@ -42,13 +42,13 @@ void main()
{ {
vec2 pos_screen = vary_fragcoord.xy; vec2 pos_screen = vary_fragcoord.xy;
vec4 pos = getPosition(pos_screen); vec4 pos = getPosition(pos_screen);
vec3 norm = getNorm(pos_screen); vec4 norm = getNorm(pos_screen);
vec4 col; vec4 col;
col.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen); col.r = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
col.g = calcAmbientOcclusion(pos, norm, pos_screen); col.g = calcAmbientOcclusion(pos, norm.xyz, pos_screen);
col.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen); col.b = sampleSpotShadow(pos.xyz, norm.xyz, 0, pos_screen);
col.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen); col.a = sampleSpotShadow(pos.xyz, norm.xyz, 1, pos_screen);
frag_color = clamp(col, vec4(0), vec4(1)); frag_color = clamp(col, vec4(0), vec4(1));
} }

View File

@ -53,8 +53,11 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
void mirrorClip(vec3 pos);
void main() void main()
{ {
mirrorClip(vary_position);
#ifdef HAS_DIFFUSE_LOOKUP #ifdef HAS_DIFFUSE_LOOKUP
vec4 color = diffuseLookup(vary_texcoord0.xy); vec4 color = diffuseLookup(vary_texcoord0.xy);
#else #else

View File

@ -33,7 +33,7 @@ uniform vec3 moon_dir;
uniform int sun_up_factor; uniform int sun_up_factor;
in vec2 vary_fragcoord; in vec2 vary_fragcoord;
vec3 getNorm(vec2 pos_screen); vec4 getNorm(vec2 pos_screen);
vec4 getPositionWithDepth(vec2 pos_screen, float depth); vec4 getPositionWithDepth(vec2 pos_screen, float depth);
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
@ -53,8 +53,7 @@ void main()
vec2 tc = vary_fragcoord.xy; vec2 tc = vary_fragcoord.xy;
float depth = getDepth(tc.xy); float depth = getDepth(tc.xy);
vec4 pos = getPositionWithDepth(tc, depth); vec4 pos = getPositionWithDepth(tc, depth);
vec4 norm = texture(normalMap, tc); vec4 norm = getNorm(tc);
norm.xyz = getNorm(tc);
vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
vec3 color = vec3(0); vec3 color = vec3(0);

View File

@ -45,6 +45,13 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
vec3 srgb_to_linear(vec3 cs); vec3 srgb_to_linear(vec3 cs);
vec3 linear_to_srgb(vec3 cs); vec3 linear_to_srgb(vec3 cs);
uniform mat4 modelview_matrix;
uniform mat3 normal_matrix;
in vec3 vary_position;
void mirrorClip(vec3 pos);
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
out vec4 frag_color; out vec4 frag_color;
@ -66,12 +73,12 @@ uniform vec4 morphFactor;
uniform vec3 camPosLocal; uniform vec3 camPosLocal;
uniform mat3 env_mat; uniform mat3 env_mat;
uniform float is_mirror;
uniform vec3 sun_dir; uniform vec3 sun_dir;
uniform vec3 moon_dir; uniform vec3 moon_dir;
in vec2 vary_fragcoord; in vec2 vary_fragcoord;
in vec3 vary_position;
uniform mat4 proj_mat; uniform mat4 proj_mat;
uniform mat4 inv_proj; uniform mat4 inv_proj;
uniform vec2 screen_res; uniform vec2 screen_res;
@ -209,8 +216,6 @@ in vec3 vary_normal;
in vec4 vertex_color; in vec4 vertex_color;
in vec2 vary_texcoord0; in vec2 vary_texcoord0;
vec2 encode_normal(vec3 n);
// get the transformed normal and apply glossiness component from normal map // get the transformed normal and apply glossiness component from normal map
vec3 getNormal(inout float glossiness) vec3 getNormal(inout float glossiness)
{ {
@ -285,12 +290,12 @@ float getShadow(vec3 pos, vec3 norm)
void main() void main()
{ {
mirrorClip(vary_position);
waterClip(); waterClip();
// diffcol == diffuse map combined with vertex color // diffcol == diffuse map combined with vertex color
vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy); vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy);
diffcol.rgb *= vertex_color.rgb; diffcol.rgb *= vertex_color.rgb;
alphaMask(diffcol.a); alphaMask(diffcol.a);
// spec == specular map combined with specular color // spec == specular map combined with specular color
@ -299,8 +304,6 @@ void main()
float glossiness = specular_color.a; float glossiness = specular_color.a;
vec3 norm = getNormal(glossiness); vec3 norm = getNormal(glossiness);
vec2 abnormal = encode_normal(norm.xyz);
float emissive = getEmissive(diffcol); float emissive = getEmissive(diffcol);
#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
@ -407,10 +410,15 @@ void main()
#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer #else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
// deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl
frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials
frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. float flag = GBUFFER_FLAG_HAS_ATMOS;
frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
frag_data[3] = vec4(0); frag_data[0] = max(vec4(diffcol.rgb, emissive), vec4(0)); // gbuffer is sRGB for legacy materials
frag_data[1] = max(vec4(spec.rgb, glossiness), vec4(0)); // XYZ = Specular color. W = Specular exponent.
frag_data[2] = vec4(norm, flag); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog)
frag_data[3] = vec4(env, 0, 0, 0);
#endif #endif
} }

View File

@ -48,7 +48,7 @@ in vec4 vary_fragcoord;
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); 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);
float calcLegacyDistanceAttenuation(float distance, float falloff); float calcLegacyDistanceAttenuation(float distance, float falloff);
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); vec4 getNorm(vec2 screenpos);
vec2 getScreenXY(vec4 clip); vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip); vec2 getScreenCoord(vec4 clip);
vec3 srgb_to_linear(vec3 c); vec3 srgb_to_linear(vec3 c);
@ -74,9 +74,8 @@ void main()
discard; discard;
} }
float envIntensity; // not used for this shader vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 n; vec3 n = norm.xyz;
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
vec4 spec = texture(specularRect, tc); vec4 spec = texture(specularRect, tc);
vec3 diffuse = texture(diffuseRect, tc).rgb; vec3 diffuse = texture(diffuseRect, tc).rgb;

View File

@ -52,7 +52,7 @@ uniform vec4 viewport;
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); 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);
float calcLegacyDistanceAttenuation(float distance, float falloff); float calcLegacyDistanceAttenuation(float distance, float falloff);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); vec4 getNorm(vec2 screenpos);
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
vec2 getScreenXY(vec4 clip); vec2 getScreenXY(vec4 clip);
vec2 getScreenCoord(vec4 clip); vec2 getScreenCoord(vec4 clip);
@ -72,9 +72,8 @@ void main()
vec2 tc = getScreenCoord(vary_fragcoord); vec2 tc = getScreenCoord(vary_fragcoord);
vec3 pos = getPosition(tc).xyz; vec3 pos = getPosition(tc).xyz;
float envIntensity; vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 n; vec3 n = norm.xyz;
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 diffuse = texture(diffuseRect, tc).rgb; vec3 diffuse = texture(diffuseRect, tc).rgb;
vec4 spec = texture(specularRect, tc); vec4 spec = texture(specularRect, tc);

View File

@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n,
uniform samplerCubeArray reflectionProbes; uniform samplerCubeArray reflectionProbes;
uniform samplerCubeArray irradianceProbes; uniform samplerCubeArray irradianceProbes;
uniform sampler2D sceneMap; uniform sampler2D sceneMap;
uniform int cube_snapshot; uniform int cube_snapshot;
uniform float max_probe_lod; uniform float max_probe_lod;
@ -47,6 +48,7 @@ layout (std140) uniform ReflectionProbes
/// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation
// box[3][0..2] - plane thickness // box[3][0..2] - plane thickness
mat4 refBox[MAX_REFMAP_COUNT]; mat4 refBox[MAX_REFMAP_COUNT];
mat4 heroBox;
// list of bounding spheres for reflection probes sorted by distance to camera (closest first) // list of bounding spheres for reflection probes sorted by distance to camera (closest first)
vec4 refSphere[MAX_REFMAP_COUNT]; vec4 refSphere[MAX_REFMAP_COUNT];
// extra parameters // extra parameters
@ -55,6 +57,7 @@ layout (std140) uniform ReflectionProbes
// z - fade in // z - fade in
// w - znear // w - znear
vec4 refParams[MAX_REFMAP_COUNT]; vec4 refParams[MAX_REFMAP_COUNT];
vec4 heroSphere;
// index of cube map in reflectionProbes for a corresponding reflection probe // index of cube map in reflectionProbes for a corresponding reflection probe
// e.g. cube map channel of refSphere[2] is stored in refIndex[2] // e.g. cube map channel of refSphere[2] is stored in refIndex[2]
// refIndex.x - cubemap channel in reflectionProbes // refIndex.x - cubemap channel in reflectionProbes
@ -70,6 +73,10 @@ layout (std140) uniform ReflectionProbes
// number of reflection probes present in refSphere // number of reflection probes present in refSphere
int refmapCount; int refmapCount;
int heroShape;
int heroMipCount;
int heroProbeCount;
}; };
// Inputs // Inputs
@ -365,11 +372,11 @@ return texCUBE(envMap, ReflDirectionWS);
// i - probe index in refBox/refSphere // i - probe index in refBox/refSphere
// d - distance to nearest wall in clip space // d - distance to nearest wall in clip space
// scale - scale of box, default 1.0 // scale - scale of box, default 1.0
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale) vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d, float scale)
{ {
// Intersection with OBB convert to unit box space // Intersection with OBB convert to unit box space
// Transform in local unit parallax cube space (scaled and rotated) // Transform in local unit parallax cube space (scaled and rotated)
mat4 clipToLocal = refBox[i]; mat4 clipToLocal = i;
vec3 RayLS = mat3(clipToLocal) * dir; vec3 RayLS = mat3(clipToLocal) * dir;
vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
@ -388,7 +395,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale)
return IntersectPositionCS; return IntersectPositionCS;
} }
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d) vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d)
{ {
return boxIntersect(origin, dir, i, d, 1.0); return boxIntersect(origin, dir, i, d, 1.0);
} }
@ -443,9 +450,9 @@ void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col)
} }
void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col) void boxIntersectDebug(vec3 origin, vec3 pos, mat4 i, inout vec4 col)
{ {
mat4 clipToLocal = refBox[i]; mat4 clipToLocal = i;
// transform into unit cube space // transform into unit cube space
origin = (clipToLocal * vec4(origin, 1.0)).xyz; origin = (clipToLocal * vec4(origin, 1.0)).xyz;
@ -462,7 +469,7 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
// r - radius of probe influence volume // r - radius of probe influence volume
// i - index of probe in refSphere // i - index of probe in refSphere
// dw - distance weight // dw - distance weight
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw) float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, vec4 i, out float dw)
{ {
float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - origin; vec3 delta = pos.xyz - origin;
@ -471,7 +478,7 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw
float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001); float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001);
float w = 1.0 / d2; float w = 1.0 / d2;
w *= refParams[i].z; w *= i.z;
dw = w * atten * max(r, 1.0)*4; dw = w * atten * max(r, 1.0)*4;
@ -497,7 +504,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
if (refIndex[i].w < 0) if (refIndex[i].w < 0)
{ // box probe { // box probe
float d = 0; float d = 0;
v = boxIntersect(pos, dir, i, d); v = boxIntersect(pos, dir, refBox[i], d);
w = max(d, 0.001); w = max(d, 0.001);
} }
@ -511,7 +518,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c,
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr); rr);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw); w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
} }
v -= c; v -= c;
@ -537,7 +544,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
if (refIndex[i].w < 0) if (refIndex[i].w < 0)
{ {
float d = 0.0; float d = 0.0;
v = boxIntersect(pos, dir, i, d, 3.0); v = boxIntersect(pos, dir, refBox[i], d, 3.0);
w = max(d, 0.001); w = max(d, 0.001);
} }
else else
@ -551,7 +558,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int
refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr); rr);
w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw); w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw);
} }
v -= c; v -= c;
@ -681,6 +688,49 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit)
return col[1]+col[0]; return col[1]+col[0];
} }
#if defined(HERO_PROBES)
uniform vec4 clipPlane;
uniform samplerCubeArray heroProbes;
void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
{
float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w;
float w = 0;
float dw = 0;
float falloffMult = 10;
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
if (heroShape < 1)
{
float d = 0;
boxIntersect(pos, norm, heroBox, d, 1.0);
w = max(d, 0);
}
else
{
float r = heroSphere.w;
w = sphereWeight(pos, refnormpersp, heroSphere.xyz, r, vec4(1), dw);
}
clipDist = clipDist * 0.95 + 0.05;
clipDist = clamp(clipDist * falloffMult, 0, 1);
w = clamp(w * falloffMult * clipDist, 0, 1);
w = mix(0, w, clamp(glossiness - 0.75, 0, 1) * 4); // We only generate a quarter of the mips for the hero probes. Linearly interpolate between normal probes and hero probes based upon glossiness.
glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w);
}
#else
void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness)
{
}
#endif
void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit) vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit)
{ {
@ -712,6 +762,8 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv,
glossenv = mix(glossenv, ssr.rgb, ssr.a); glossenv = mix(glossenv, ssr.rgb, ssr.a);
} }
#endif #endif
tapHeroProbe(glossenv, pos, norm, glossiness);
} }
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
@ -747,7 +799,7 @@ void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
{ {
if (refIndex[i].w < 0) if (refIndex[i].w < 0)
{ {
boxIntersectDebug(origin, pos, i, col); boxIntersectDebug(origin, pos, refBox[i], col);
} }
else else
{ {
@ -799,6 +851,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
{ {
float lod = (1.0-glossiness)*reflection_lods; float lod = (1.0-glossiness)*reflection_lods;
glossenv = sampleProbes(pos, normalize(refnormpersp), lod); glossenv = sampleProbes(pos, normalize(refnormpersp), lod);
} }
if (envIntensity > 0.0) if (envIntensity > 0.0)
@ -826,6 +879,9 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
} }
#endif #endif
tapHeroProbe(glossenv, pos, norm, glossiness);
tapHeroProbe(legacyenv, pos, norm, 1.0);
glossenv = clamp(glossenv, vec3(0), vec3(10)); glossenv = clamp(glossenv, vec3(0), vec3(10));
} }

View File

@ -40,14 +40,13 @@ uniform sampler2D specularRect;
uniform sampler2D diffuseRect; uniform sampler2D diffuseRect;
uniform sampler2D diffuseMap; uniform sampler2D diffuseMap;
vec3 getNorm(vec2 screenpos); vec4 getNorm(vec2 screenpos);
float getDepth(vec2 pos_screen); float getDepth(vec2 pos_screen);
float linearDepth(float d, float znear, float zfar); float linearDepth(float d, float znear, float zfar);
float linearDepth01(float d, float znear, float zfar); float linearDepth01(float d, float znear, float zfar);
vec4 getPositionWithDepth(vec2 pos_screen, float depth); vec4 getPositionWithDepth(vec2 pos_screen, float depth);
vec4 getPosition(vec2 pos_screen); vec4 getPosition(vec2 pos_screen);
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
float random (vec2 uv); float random (vec2 uv);
@ -57,9 +56,7 @@ void main()
{ {
vec2 tc = vary_fragcoord.xy; vec2 tc = vary_fragcoord.xy;
float depth = linearDepth01(getDepth(tc), zNear, zFar); float depth = linearDepth01(getDepth(tc), zNear, zFar);
float envIntensity; vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 n;
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz; vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz;
vec4 spec = texture(specularRect, tc); vec4 spec = texture(specularRect, tc);
vec2 hitpixel; vec2 hitpixel;
@ -84,7 +81,7 @@ void main()
vec4 collectedColor = vec4(0); vec4 collectedColor = vec4(0);
float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap, 0); float w = tapScreenSpaceReflection(4, tc, pos, norm.xyz, collectedColor, diffuseMap, 0);
collectedColor.rgb *= specCol.rgb; collectedColor.rgb *= specCol.rgb;

Some files were not shown because too many files have changed in this diff Show More