├── .gitignore ├── Editor.meta ├── Editor ├── Component.meta ├── Component │ ├── VirtualTextureVolumeEditor.cs │ └── VirtualTextureVolumeEditor.cs.meta ├── Infinity.Rendering.VirtualTexture.Editor.asmdef └── Infinity.Rendering.VirtualTexture.Editor.asmdef.meta ├── LICENSE ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── Component.meta ├── Component │ ├── RuntimeCompress.cs │ ├── RuntimeCompress.cs.meta │ ├── VirtualTextureVolume.cs │ └── VirtualTextureVolume.cs.meta ├── Infinity.Rendering.VirtualTexture.Runtime.asmdef ├── Infinity.Rendering.VirtualTexture.Runtime.asmdef.meta ├── Material.meta ├── Material │ ├── M_TerrainLit-VT.mat │ ├── M_TerrainLit-VT.mat.meta │ ├── M_TerrainLit.mat │ └── M_TerrainLit.mat.meta ├── Prefab.meta ├── Prefab │ ├── FeedbackCamera.prefab │ └── FeedbackCamera.prefab.meta ├── Profile.meta ├── Profile │ ├── PipelineSettings.meta │ ├── PipelineSettings │ │ ├── PlayerRenderer.asset │ │ ├── PlayerRenderer.asset.meta │ │ ├── VTPipelineAsset.asset │ │ └── VTPipelineAsset.asset.meta │ ├── RuntimeVirtualTexture.asset │ └── RuntimeVirtualTexture.asset.meta ├── Renderer.meta ├── Renderer │ ├── FeedbackRenderer.cs │ └── FeedbackRenderer.cs.meta ├── Source.meta └── Source │ ├── LruCache.cs │ ├── LruCache.cs.meta │ ├── NativeExtensions.cs │ ├── NativeExtensions.cs.meta │ ├── VirtualTextureAsset.cs │ ├── VirtualTextureAsset.cs.meta │ ├── VirtualTextureFeedback.cs │ ├── VirtualTextureFeedback.cs.meta │ ├── VirtualTextureJob.cs │ ├── VirtualTextureJob.cs.meta │ ├── VirtualTexturePage.cs │ ├── VirtualTexturePage.cs.meta │ ├── VirtualTextureProducer.cs │ ├── VirtualTextureProducer.cs.meta │ ├── VirtualTextureRenderer.cs │ ├── VirtualTextureRenderer.cs.meta │ ├── VirtualTextureUtility.cs │ └── VirtualTextureUtility.cs.meta ├── Shaders.meta ├── Shaders ├── Common.meta ├── Common │ ├── StochasticSampling.hlsl │ └── StochasticSampling.hlsl.meta ├── Compress.meta ├── Compress │ ├── BCCompress.hlsl │ ├── BCCompress.hlsl.meta │ ├── ComputeCompress.compute │ ├── ComputeCompress.compute.meta │ ├── ETCCompress.hlsl │ └── ETCCompress.hlsl.meta ├── DummyVirtualTextureShaderLibrary.cs ├── DummyVirtualTextureShaderLibrary.cs.meta ├── Infinity.Rendering.VirtualTexture.Shader.asmdef ├── Infinity.Rendering.VirtualTexture.Shader.asmdef.meta ├── PageTable.meta ├── PageTable │ ├── DrawPageColor.shader │ ├── DrawPageColor.shader.meta │ ├── DrawPageTable.shader │ ├── DrawPageTable.shader.meta │ ├── DrwaPageCommon.hlsl │ └── DrwaPageCommon.hlsl.meta ├── Terrain.meta └── Terrain │ ├── FeedbackCommon.hlsl │ ├── FeedbackCommon.hlsl.meta │ ├── TerrainLit.shader │ ├── TerrainLit.shader.meta │ ├── TerrainLitAdd.shader │ ├── TerrainLitAdd.shader.meta │ ├── TerrainLitInclude.hlsl │ ├── TerrainLitInclude.hlsl.meta │ ├── TerrainLit_VT.shader │ └── TerrainLit_VT.shader.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | [Ll]ibrary/ 3 | [Tt]emp/ 4 | [Oo]bj/ 5 | [Bb]uild/ 6 | [Bb]uilds/ 7 | [Ll]ogs/ 8 | Assets/TemporalFolder* 9 | 10 | # Visual Studio cache directory 11 | .vs/ 12 | .vscode/ 13 | 14 | # Autogenerated VS/MD/Consulo solution and project files 15 | ExportedObj/ 16 | .consulo/ 17 | *.csproj 18 | *.unityproj 19 | *.sln 20 | *.suo 21 | *.tmp 22 | *.user 23 | *.userprefs 24 | *.pidb 25 | *.booproj 26 | *.svd 27 | *.pdb 28 | *.opendb 29 | 30 | # Unity3D generated meta files 31 | *.pidb.meta 32 | *.pdb.meta 33 | 34 | # Unity3D Generated File On Crash Reports 35 | sysinfo.txt 36 | 37 | # Builds 38 | *.apk 39 | *.unitypackage 40 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16fd6f8f46e422c42a44600072bc2daa 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Component.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 63a98c444053a4b47a60a3c9ebb1fdd9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Component/VirtualTextureVolumeEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace Landscape.RuntimeVirtualTexture.Editor 5 | { 6 | [CustomEditor(typeof(VirtualTextureVolume))] 7 | public class VirtualTextureVolumeEditor : UnityEditor.Editor 8 | { 9 | public Bounds volumeBound; 10 | VirtualTextureVolume volumeTarget { get { return target as VirtualTextureVolume; } } 11 | 12 | 13 | void OnEnable() 14 | { 15 | 16 | } 17 | 18 | void OnValidate() 19 | { 20 | 21 | } 22 | 23 | void OnSceneGUI() 24 | { 25 | volumeBound = new Bounds(volumeTarget.transform.position, volumeTarget.transform.localScale); 26 | DrawBound(volumeBound, new Color(0.5f, 1, 0.25f)); 27 | } 28 | 29 | public override void OnInspectorGUI() 30 | { 31 | base.OnInspectorGUI(); 32 | serializedObject.Update(); 33 | serializedObject.ApplyModifiedProperties(); 34 | 35 | volumeTarget.transform.localScale = new Vector3(volumeTarget.VolumeSize, volumeTarget.transform.localScale.y, volumeTarget.VolumeSize); 36 | } 37 | 38 | protected void DrawBound(Bounds b, Color DebugColor) 39 | { 40 | // bottom 41 | var p1 = new Vector3(b.min.x, b.min.y, b.min.z); 42 | var p2 = new Vector3(b.max.x, b.min.y, b.min.z); 43 | var p3 = new Vector3(b.max.x, b.min.y, b.max.z); 44 | var p4 = new Vector3(b.min.x, b.min.y, b.max.z); 45 | 46 | Debug.DrawLine(p1, p2, DebugColor); 47 | Debug.DrawLine(p2, p3, DebugColor); 48 | Debug.DrawLine(p3, p4, DebugColor); 49 | Debug.DrawLine(p4, p1, DebugColor); 50 | 51 | // top 52 | var p5 = new Vector3(b.min.x, b.max.y, b.min.z); 53 | var p6 = new Vector3(b.max.x, b.max.y, b.min.z); 54 | var p7 = new Vector3(b.max.x, b.max.y, b.max.z); 55 | var p8 = new Vector3(b.min.x, b.max.y, b.max.z); 56 | 57 | Debug.DrawLine(p5, p6, DebugColor); 58 | Debug.DrawLine(p6, p7, DebugColor); 59 | Debug.DrawLine(p7, p8, DebugColor); 60 | Debug.DrawLine(p8, p5, DebugColor); 61 | 62 | // sides 63 | Debug.DrawLine(p1, p5, DebugColor); 64 | Debug.DrawLine(p2, p6, DebugColor); 65 | Debug.DrawLine(p3, p7, DebugColor); 66 | Debug.DrawLine(p4, p8, DebugColor); 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Editor/Component/VirtualTextureVolumeEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f845fde9d7406b94494419b48bd8be74 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Infinity.Rendering.VirtualTexture.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Infinity.Rendering.VirtualTexture.Editor", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:66802a45437b7bf498aa44b38d6f769e" 6 | ], 7 | "includePlatforms": [ 8 | "Editor" 9 | ], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": true, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Editor/Infinity.Rendering.VirtualTexture.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b7bcd7c875e4f284fbdea67f1902a674 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InfinityVirtualTexture 2 | Runtime Procedural Virtual Texture for Unity Terrain in Universal Render Pipeline(URP). 3 | 4 | ![image](https://user-images.githubusercontent.com/12471727/170739477-57cf2c46-94d5-4372-a751-c435f6439f86.png) 5 | 6 | ![image](https://user-images.githubusercontent.com/12471727/170739453-89b2d440-26fa-484a-9f0a-368b42729a14.png) 7 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91ee06da78c91694fa7c667d17b054bf 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3307411f78a9ea144bb818b8c9ecd48d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Component.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c2f44e34562fe8d4b8a3aa81479eb3c3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Component/RuntimeCompress.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Experimental.Rendering; 3 | 4 | public class RuntimeCompress : MonoBehaviour 5 | { 6 | public int Size = 256; 7 | private int m_QuadSize 8 | { 9 | get 10 | { 11 | return Size / 4; 12 | } 13 | } 14 | 15 | Material m_Material; 16 | Texture2D m_DecodeTexture; 17 | GraphicsFormat m_DscFormat; 18 | RenderTexture m_CompressTexture; 19 | public Texture2D NoneCompressTexture; 20 | public ComputeShader shader; 21 | 22 | 23 | void OnEnable() 24 | { 25 | #if UNITY_ANDROID && !UNITY_EDITOR 26 | m_DscFormat = GraphicsFormat.RGBA_ETC2_UNorm; 27 | shader.DisableKeyword("_COMPRESS_BC3"); 28 | shader.EnableKeyword("_COMPRESS_ETC2"); 29 | #else 30 | m_DscFormat = GraphicsFormat.RGBA_DXT5_UNorm; 31 | shader.DisableKeyword("_COMPRESS_ETC2"); 32 | shader.EnableKeyword("_COMPRESS_BC3"); 33 | #endif 34 | m_CompressTexture = new RenderTexture(m_QuadSize, m_QuadSize, 0) 35 | { 36 | graphicsFormat = GraphicsFormat.R32G32B32A32_UInt, 37 | enableRandomWrite = true, 38 | }; 39 | m_CompressTexture.Create(); 40 | m_DecodeTexture = new Texture2D(Size, Size, m_DscFormat, TextureCreationFlags.None); 41 | 42 | m_Material = GetComponent().sharedMaterial; 43 | } 44 | 45 | void Update() 46 | { 47 | shader.SetInt("_Size", Size); 48 | shader.SetTexture(0, "_SrcTexture", NoneCompressTexture); 49 | shader.SetTexture(0, "_DscTexture", m_CompressTexture); 50 | shader.Dispatch(0, (m_QuadSize + 7) / 8, (m_QuadSize + 7) / 8, 1); 51 | 52 | Graphics.CopyTexture(m_CompressTexture, 0, 0, 0, 0, m_QuadSize, m_QuadSize, m_DecodeTexture, 0, 0, 0, 0); 53 | m_Material.mainTexture = m_DecodeTexture; 54 | } 55 | } -------------------------------------------------------------------------------- /Runtime/Component/RuntimeCompress.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e26713dab4885d64c9d2d814ee103a0f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Component/VirtualTextureVolume.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Unity.Mathematics; 3 | 4 | namespace Landscape.RuntimeVirtualTexture 5 | { 6 | public enum EVirtualTextureVolumeSize 7 | { 8 | X128 = 128, 9 | X256 = 256, 10 | X512 = 512, 11 | X1024 = 1024, 12 | X2048 = 2048, 13 | X4096 = 4096, 14 | } 15 | 16 | public unsafe class VirtualTextureVolume : MonoBehaviour 17 | { 18 | [HideInInspector] 19 | public Material m_material; 20 | private Terrain[] m_terrainList; 21 | 22 | [Header("Texture")] 23 | public EVirtualTextureVolumeSize volumeScale; 24 | public VirtualTextureAsset virtualTexture; 25 | 26 | private float m_CellSize 27 | { 28 | get 29 | { 30 | return VolumeSize / virtualTexture.pageSize; 31 | } 32 | } 33 | public float VolumeSize 34 | { 35 | get 36 | { 37 | return (int)volumeScale; 38 | } 39 | } 40 | private float m_VolumeRadius 41 | { 42 | get 43 | { 44 | return VolumeSize * 0.5f; 45 | } 46 | } 47 | 48 | internal FRect volumeRect; 49 | internal FPageProducer pageProducer; 50 | internal FPageRenderer pageRenderer; 51 | internal static VirtualTextureVolume s_VirtualTextureVolume; 52 | 53 | void OnEnable() 54 | { 55 | SetTerrainMaterial(); 56 | 57 | virtualTexture.Initialize(); 58 | s_VirtualTextureVolume = this; 59 | 60 | int2 fixedCenter = GetFixedCenter(GetFixedPos(transform.position)); 61 | volumeRect = new FRect(fixedCenter.x - m_VolumeRadius, fixedCenter.y - m_VolumeRadius, VolumeSize, VolumeSize); 62 | Shader.SetGlobalInt("_VTMipCount", virtualTexture.NumMip); 63 | Shader.SetGlobalVector("_VTVolumeRect", new Vector4(volumeRect.xMin, volumeRect.yMin, volumeRect.width, volumeRect.height)); 64 | Shader.SetGlobalVector("_VTVolumeBound", new Vector4(transform.position.x, transform.position.y, transform.position.z, VolumeSize)); 65 | 66 | pageRenderer = new FPageRenderer(virtualTexture.pageSize, 6); 67 | pageProducer = new FPageProducer(virtualTexture.tileNum, virtualTexture.pageSize, virtualTexture.NumMip); 68 | } 69 | 70 | void OnDisable() 71 | { 72 | pageProducer.Dispose(); 73 | pageRenderer.Dispose(); 74 | virtualTexture.Dispose(); 75 | } 76 | 77 | void SetTerrainMaterial() 78 | { 79 | m_terrainList = FindObjectsByType(FindObjectsSortMode.InstanceID); 80 | if (m_terrainList.Length == 0) { return; } 81 | 82 | for (int i = 0; i < m_terrainList.Length; ++i) 83 | { 84 | m_terrainList[i].materialTemplate = m_material; 85 | } 86 | } 87 | 88 | int2 GetFixedCenter(int2 pos) 89 | { 90 | return new int2((int)Mathf.Floor(pos.x / m_VolumeRadius + 0.5f) * (int)m_VolumeRadius, (int)Mathf.Floor(pos.y / m_VolumeRadius + 0.5f) * (int)m_VolumeRadius); 91 | } 92 | 93 | int2 GetFixedPos(Vector3 pos) 94 | { 95 | return new int2((int)Mathf.Floor(pos.x / m_CellSize + 0.5f) * (int)m_CellSize, (int)Mathf.Floor(pos.z / m_CellSize + 0.5f) * (int)m_CellSize); 96 | } 97 | 98 | internal FDrawPageParameter GetDrawPageParamter() 99 | { 100 | FDrawPageParameter drawPageParameter; 101 | drawPageParameter.volumeRect = volumeRect; 102 | drawPageParameter.terrainList = m_terrainList; 103 | return drawPageParameter; 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /Runtime/Component/VirtualTextureVolume.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8a6b7895b4876434aa05edc7c337e905 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_material: {fileID: 2100000, guid: 3a2c150cfa00c9140826163693691a0f, type: 2} 8 | - virtualTexture: {fileID: 11400000, guid: b8650e03683bb0844a15d265c3b49a85, type: 2} 9 | executionOrder: 100 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Runtime/Infinity.Rendering.VirtualTexture.Runtime.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Infinity.Rendering.VirtualTexture.Runtime", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:8a2eafa29b15f444eb6d74f94a930e1d", 6 | "GUID:2665a8d13d1b3f18800f46e256720795", 7 | "GUID:e0cd26848372d4e5c891c569017e11f1", 8 | "GUID:d8b63aba1907145bea998dd612889d6b", 9 | "GUID:df380645f10b7bc4b97d4f5eb6303d95", 10 | "GUID:15fc0a57446b3144c949da3e2b9737a9" 11 | ], 12 | "includePlatforms": [], 13 | "excludePlatforms": [], 14 | "allowUnsafeCode": true, 15 | "overrideReferences": false, 16 | "precompiledReferences": [], 17 | "autoReferenced": true, 18 | "defineConstraints": [], 19 | "versionDefines": [], 20 | "noEngineReferences": false 21 | } -------------------------------------------------------------------------------- /Runtime/Infinity.Rendering.VirtualTexture.Runtime.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 66802a45437b7bf498aa44b38d6f769e 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Material.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2639154e1ee39c4fb8ccedef4995cd8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Material/M_TerrainLit-VT.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: M_TerrainLit-VT 11 | m_Shader: {fileID: 4800000, guid: 04691e96727abdd4ebed0762df75cc74, type: 3} 12 | m_ShaderKeywords: _NORMALMAP _RVT _TERRAIN_INSTANCED_PERPIXEL_NORMAL 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BaseMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _BumpMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _Control: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailAlbedoMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _DetailMask: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _DetailNormalMap: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _EmissionMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _MainTex: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _Mask0: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | - _Mask1: 59 | m_Texture: {fileID: 0} 60 | m_Scale: {x: 1, y: 1} 61 | m_Offset: {x: 0, y: 0} 62 | - _Mask2: 63 | m_Texture: {fileID: 0} 64 | m_Scale: {x: 1, y: 1} 65 | m_Offset: {x: 0, y: 0} 66 | - _Mask3: 67 | m_Texture: {fileID: 0} 68 | m_Scale: {x: 1, y: 1} 69 | m_Offset: {x: 0, y: 0} 70 | - _MetallicGlossMap: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | - _Normal0: 75 | m_Texture: {fileID: 0} 76 | m_Scale: {x: 1, y: 1} 77 | m_Offset: {x: 0, y: 0} 78 | - _Normal1: 79 | m_Texture: {fileID: 0} 80 | m_Scale: {x: 1, y: 1} 81 | m_Offset: {x: 0, y: 0} 82 | - _Normal2: 83 | m_Texture: {fileID: 0} 84 | m_Scale: {x: 1, y: 1} 85 | m_Offset: {x: 0, y: 0} 86 | - _Normal3: 87 | m_Texture: {fileID: 0} 88 | m_Scale: {x: 1, y: 1} 89 | m_Offset: {x: 0, y: 0} 90 | - _OcclusionMap: 91 | m_Texture: {fileID: 0} 92 | m_Scale: {x: 1, y: 1} 93 | m_Offset: {x: 0, y: 0} 94 | - _ParallaxMap: 95 | m_Texture: {fileID: 0} 96 | m_Scale: {x: 1, y: 1} 97 | m_Offset: {x: 0, y: 0} 98 | - _SpecGlossMap: 99 | m_Texture: {fileID: 0} 100 | m_Scale: {x: 1, y: 1} 101 | m_Offset: {x: 0, y: 0} 102 | - _Splat0: 103 | m_Texture: {fileID: 0} 104 | m_Scale: {x: 1, y: 1} 105 | m_Offset: {x: 0, y: 0} 106 | - _Splat1: 107 | m_Texture: {fileID: 0} 108 | m_Scale: {x: 1, y: 1} 109 | m_Offset: {x: 0, y: 0} 110 | - _Splat2: 111 | m_Texture: {fileID: 0} 112 | m_Scale: {x: 1, y: 1} 113 | m_Offset: {x: 0, y: 0} 114 | - _Splat3: 115 | m_Texture: {fileID: 0} 116 | m_Scale: {x: 1, y: 1} 117 | m_Offset: {x: 0, y: 0} 118 | - _TerrainHolesTexture: 119 | m_Texture: {fileID: 0} 120 | m_Scale: {x: 1, y: 1} 121 | m_Offset: {x: 0, y: 0} 122 | - unity_Lightmaps: 123 | m_Texture: {fileID: 0} 124 | m_Scale: {x: 1, y: 1} 125 | m_Offset: {x: 0, y: 0} 126 | - unity_LightmapsInd: 127 | m_Texture: {fileID: 0} 128 | m_Scale: {x: 1, y: 1} 129 | m_Offset: {x: 0, y: 0} 130 | - unity_ShadowMasks: 131 | m_Texture: {fileID: 0} 132 | m_Scale: {x: 1, y: 1} 133 | m_Offset: {x: 0, y: 0} 134 | m_Floats: 135 | - _AlphaClip: 0 136 | - _Blend: 0 137 | - _BumpScale: 1 138 | - _ClearCoatMask: 0 139 | - _ClearCoatSmoothness: 0 140 | - _Cull: 2 141 | - _Cutoff: 0.5 142 | - _DetailAlbedoMapScale: 1 143 | - _DetailNormalMapScale: 1 144 | - _DstBlend: 0 145 | - _EnableHeightBlend: 0 146 | - _EnableInstancedPerPixelNormal: 1 147 | - _EnvironmentReflections: 1 148 | - _GlossMapScale: 0 149 | - _Glossiness: 0 150 | - _GlossyReflections: 0 151 | - _HeightTransition: 0 152 | - _Metallic: 0 153 | - _Metallic0: 0 154 | - _Metallic1: 0 155 | - _Metallic2: 0 156 | - _Metallic3: 0 157 | - _NumLayersCount: 8 158 | - _OcclusionStrength: 1 159 | - _Parallax: 0.005 160 | - _QueueOffset: 0 161 | - _ReceiveShadows: 1 162 | - _Smoothness: 0.5 163 | - _Smoothness0: 0.5 164 | - _Smoothness1: 0.5 165 | - _Smoothness2: 0.5 166 | - _Smoothness3: 0.5 167 | - _SmoothnessTextureChannel: 0 168 | - _SpecularHighlights: 1 169 | - _SrcBlend: 1 170 | - _Surface: 0 171 | - _WorkflowMode: 1 172 | - _ZWrite: 1 173 | m_Colors: 174 | - _BaseColor: {r: 1, g: 1, b: 1, a: 1} 175 | - _Color: {r: 1, g: 1, b: 1, a: 1} 176 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 177 | - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} 178 | m_BuildTextureStacks: [] 179 | --- !u!114 &6531466961274570969 180 | MonoBehaviour: 181 | m_ObjectHideFlags: 11 182 | m_CorrespondingSourceObject: {fileID: 0} 183 | m_PrefabInstance: {fileID: 0} 184 | m_PrefabAsset: {fileID: 0} 185 | m_GameObject: {fileID: 0} 186 | m_Enabled: 1 187 | m_EditorHideFlags: 0 188 | m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} 189 | m_Name: 190 | m_EditorClassIdentifier: 191 | version: 3 192 | -------------------------------------------------------------------------------- /Runtime/Material/M_TerrainLit-VT.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3a2c150cfa00c9140826163693691a0f 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Material/M_TerrainLit.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInstance: {fileID: 0} 9 | m_PrefabAsset: {fileID: 0} 10 | m_Name: M_TerrainLit 11 | m_Shader: {fileID: 4800000, guid: a5c8edbfb27e9bf4cb5010201278f04f, type: 3} 12 | m_ShaderKeywords: _NORMALMAP _RVT _TERRAIN_INSTANCED_PERPIXEL_NORMAL 13 | m_LightmapFlags: 4 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BaseMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _BumpMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _Control: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailAlbedoMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _DetailMask: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _DetailNormalMap: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _EmissionMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _MainTex: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _Mask0: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | - _Mask1: 59 | m_Texture: {fileID: 0} 60 | m_Scale: {x: 1, y: 1} 61 | m_Offset: {x: 0, y: 0} 62 | - _Mask2: 63 | m_Texture: {fileID: 0} 64 | m_Scale: {x: 1, y: 1} 65 | m_Offset: {x: 0, y: 0} 66 | - _Mask3: 67 | m_Texture: {fileID: 0} 68 | m_Scale: {x: 1, y: 1} 69 | m_Offset: {x: 0, y: 0} 70 | - _MetallicGlossMap: 71 | m_Texture: {fileID: 0} 72 | m_Scale: {x: 1, y: 1} 73 | m_Offset: {x: 0, y: 0} 74 | - _Normal0: 75 | m_Texture: {fileID: 0} 76 | m_Scale: {x: 1, y: 1} 77 | m_Offset: {x: 0, y: 0} 78 | - _Normal1: 79 | m_Texture: {fileID: 0} 80 | m_Scale: {x: 1, y: 1} 81 | m_Offset: {x: 0, y: 0} 82 | - _Normal2: 83 | m_Texture: {fileID: 0} 84 | m_Scale: {x: 1, y: 1} 85 | m_Offset: {x: 0, y: 0} 86 | - _Normal3: 87 | m_Texture: {fileID: 0} 88 | m_Scale: {x: 1, y: 1} 89 | m_Offset: {x: 0, y: 0} 90 | - _OcclusionMap: 91 | m_Texture: {fileID: 0} 92 | m_Scale: {x: 1, y: 1} 93 | m_Offset: {x: 0, y: 0} 94 | - _ParallaxMap: 95 | m_Texture: {fileID: 0} 96 | m_Scale: {x: 1, y: 1} 97 | m_Offset: {x: 0, y: 0} 98 | - _SpecGlossMap: 99 | m_Texture: {fileID: 0} 100 | m_Scale: {x: 1, y: 1} 101 | m_Offset: {x: 0, y: 0} 102 | - _Splat0: 103 | m_Texture: {fileID: 0} 104 | m_Scale: {x: 1, y: 1} 105 | m_Offset: {x: 0, y: 0} 106 | - _Splat1: 107 | m_Texture: {fileID: 0} 108 | m_Scale: {x: 1, y: 1} 109 | m_Offset: {x: 0, y: 0} 110 | - _Splat2: 111 | m_Texture: {fileID: 0} 112 | m_Scale: {x: 1, y: 1} 113 | m_Offset: {x: 0, y: 0} 114 | - _Splat3: 115 | m_Texture: {fileID: 0} 116 | m_Scale: {x: 1, y: 1} 117 | m_Offset: {x: 0, y: 0} 118 | - _TerrainHolesTexture: 119 | m_Texture: {fileID: 0} 120 | m_Scale: {x: 1, y: 1} 121 | m_Offset: {x: 0, y: 0} 122 | - unity_Lightmaps: 123 | m_Texture: {fileID: 0} 124 | m_Scale: {x: 1, y: 1} 125 | m_Offset: {x: 0, y: 0} 126 | - unity_LightmapsInd: 127 | m_Texture: {fileID: 0} 128 | m_Scale: {x: 1, y: 1} 129 | m_Offset: {x: 0, y: 0} 130 | - unity_ShadowMasks: 131 | m_Texture: {fileID: 0} 132 | m_Scale: {x: 1, y: 1} 133 | m_Offset: {x: 0, y: 0} 134 | m_Ints: [] 135 | m_Floats: 136 | - _AlphaClip: 0 137 | - _Blend: 0 138 | - _BumpScale: 1 139 | - _ClearCoatMask: 0 140 | - _ClearCoatSmoothness: 0 141 | - _Cull: 2 142 | - _Cutoff: 0.5 143 | - _DetailAlbedoMapScale: 1 144 | - _DetailNormalMapScale: 1 145 | - _DstBlend: 0 146 | - _EnableHeightBlend: 0 147 | - _EnableInstancedPerPixelNormal: 1 148 | - _EnvironmentReflections: 1 149 | - _GlossMapScale: 0 150 | - _Glossiness: 0 151 | - _GlossyReflections: 0 152 | - _HeightTransition: 0 153 | - _Metallic: 0 154 | - _Metallic0: 0 155 | - _Metallic1: 0 156 | - _Metallic2: 0 157 | - _Metallic3: 0 158 | - _NumLayersCount: 8 159 | - _OcclusionStrength: 1 160 | - _Parallax: 0.005 161 | - _QueueOffset: 0 162 | - _ReceiveShadows: 1 163 | - _Smoothness: 0.5 164 | - _Smoothness0: 0.5 165 | - _Smoothness1: 0.5 166 | - _Smoothness2: 0.5 167 | - _Smoothness3: 0.5 168 | - _SmoothnessTextureChannel: 0 169 | - _SpecularHighlights: 1 170 | - _SrcBlend: 1 171 | - _Surface: 0 172 | - _WorkflowMode: 1 173 | - _ZWrite: 1 174 | m_Colors: 175 | - _BaseColor: {r: 1, g: 1, b: 1, a: 1} 176 | - _Color: {r: 1, g: 1, b: 1, a: 1} 177 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 178 | - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} 179 | m_BuildTextureStacks: [] 180 | --- !u!114 &6531466961274570969 181 | MonoBehaviour: 182 | m_ObjectHideFlags: 11 183 | m_CorrespondingSourceObject: {fileID: 0} 184 | m_PrefabInstance: {fileID: 0} 185 | m_PrefabAsset: {fileID: 0} 186 | m_GameObject: {fileID: 0} 187 | m_Enabled: 1 188 | m_EditorHideFlags: 0 189 | m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} 190 | m_Name: 191 | m_EditorClassIdentifier: 192 | version: 5 193 | -------------------------------------------------------------------------------- /Runtime/Material/M_TerrainLit.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b00e7e6313a7b3e4a8972047e34afe6e 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 45e3511bd77f0fe419401373e3bb1b56 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Prefab/FeedbackCamera.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &5162534690774019376 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 5162534690774019383} 12 | - component: {fileID: 5162534690774019380} 13 | - component: {fileID: 5162534690774019379} 14 | m_Layer: 0 15 | m_Name: FeedbackCamera 16 | m_TagString: Untagged 17 | m_Icon: {fileID: 0} 18 | m_NavMeshLayer: 0 19 | m_StaticEditorFlags: 0 20 | m_IsActive: 1 21 | --- !u!4 &5162534690774019383 22 | Transform: 23 | m_ObjectHideFlags: 0 24 | m_CorrespondingSourceObject: {fileID: 0} 25 | m_PrefabInstance: {fileID: 0} 26 | m_PrefabAsset: {fileID: 0} 27 | m_GameObject: {fileID: 5162534690774019376} 28 | m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} 29 | m_LocalPosition: {x: -241.7, y: 25.02, z: -160} 30 | m_LocalScale: {x: 1, y: 1, z: 1} 31 | m_Children: [] 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | --- !u!20 &5162534690774019380 36 | Camera: 37 | m_ObjectHideFlags: 0 38 | m_CorrespondingSourceObject: {fileID: 0} 39 | m_PrefabInstance: {fileID: 0} 40 | m_PrefabAsset: {fileID: 0} 41 | m_GameObject: {fileID: 5162534690774019376} 42 | m_Enabled: 1 43 | serializedVersion: 2 44 | m_ClearFlags: 2 45 | m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0.019607844} 46 | m_projectionMatrixMode: 1 47 | m_GateFitMode: 2 48 | m_FOVAxisMode: 0 49 | m_SensorSize: {x: 36, y: 24} 50 | m_LensShift: {x: 0, y: 0} 51 | m_FocalLength: 50 52 | m_NormalizedViewPortRect: 53 | serializedVersion: 2 54 | x: 0 55 | y: 0 56 | width: 1 57 | height: 1 58 | near clip plane: 0.25 59 | far clip plane: 2048 60 | field of view: 60 61 | orthographic: 0 62 | orthographic size: 5 63 | m_Depth: -2 64 | m_CullingMask: 65 | serializedVersion: 2 66 | m_Bits: 4294967295 67 | m_RenderingPath: -1 68 | m_TargetTexture: {fileID: 0} 69 | m_TargetDisplay: 0 70 | m_TargetEye: 3 71 | m_HDR: 1 72 | m_AllowMSAA: 1 73 | m_AllowDynamicResolution: 0 74 | m_ForceIntoRT: 0 75 | m_OcclusionCulling: 1 76 | m_StereoConvergence: 10 77 | m_StereoSeparation: 0.022 78 | --- !u!114 &5162534690774019379 79 | MonoBehaviour: 80 | m_ObjectHideFlags: 0 81 | m_CorrespondingSourceObject: {fileID: 0} 82 | m_PrefabInstance: {fileID: 0} 83 | m_PrefabAsset: {fileID: 0} 84 | m_GameObject: {fileID: 5162534690774019376} 85 | m_Enabled: 1 86 | m_EditorHideFlags: 0 87 | m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} 88 | m_Name: 89 | m_EditorClassIdentifier: 90 | m_RenderShadows: 1 91 | m_RequiresDepthTextureOption: 2 92 | m_RequiresOpaqueTextureOption: 2 93 | m_CameraType: 0 94 | m_Cameras: [] 95 | m_RendererIndex: 1 96 | m_VolumeLayerMask: 97 | serializedVersion: 2 98 | m_Bits: 0 99 | m_VolumeTrigger: {fileID: 0} 100 | m_RenderPostProcessing: 0 101 | m_Antialiasing: 0 102 | m_AntialiasingQuality: 2 103 | m_StopNaN: 0 104 | m_Dithering: 0 105 | m_ClearDepth: 1 106 | m_AllowXRRendering: 1 107 | m_RequiresDepthTexture: 0 108 | m_RequiresColorTexture: 0 109 | m_Version: 2 110 | -------------------------------------------------------------------------------- /Runtime/Prefab/FeedbackCamera.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8de85f97505b35243b9b36d4fb90ad82 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Profile.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d1ff3047c7888b4cb5146a838577ec4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Profile/PipelineSettings.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d3d847e4a2e8ee641b820043902fc3b9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Profile/PipelineSettings/PlayerRenderer.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &-1637665494111836945 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 3d9afec8bd61f784aa5e6435b73a3e61, type: 3} 13 | m_Name: FeedbackRenderer 14 | m_EditorClassIdentifier: 15 | m_Active: 1 16 | layerMask: 17 | serializedVersion: 2 18 | m_Bits: 8 19 | feedbackSize: 20 | x: 1280 21 | y: 720 22 | feedbackScale: 16 23 | --- !u!114 &11400000 24 | MonoBehaviour: 25 | m_ObjectHideFlags: 0 26 | m_CorrespondingSourceObject: {fileID: 0} 27 | m_PrefabInstance: {fileID: 0} 28 | m_PrefabAsset: {fileID: 0} 29 | m_GameObject: {fileID: 0} 30 | m_Enabled: 1 31 | m_EditorHideFlags: 0 32 | m_Script: {fileID: 11500000, guid: de640fe3d0db1804a85f9fc8f5cadab6, type: 3} 33 | m_Name: PlayerRenderer 34 | m_EditorClassIdentifier: 35 | debugShaders: 36 | debugReplacementPS: {fileID: 4800000, guid: cf852408f2e174538bcd9b7fda1c5ae7, type: 3} 37 | m_RendererFeatures: 38 | - {fileID: -1637665494111836945} 39 | m_RendererFeatureMap: efa48ceae8d745e9 40 | m_UseNativeRenderPass: 0 41 | postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} 42 | xrSystemData: {fileID: 11400000, guid: 60e1133243b97e347b653163a8c01b64, type: 2} 43 | shaders: 44 | blitPS: {fileID: 4800000, guid: c17132b1f77d20942aa75f8429c0f8bc, type: 3} 45 | copyDepthPS: {fileID: 4800000, guid: d6dae50ee9e1bfa4db75f19f99355220, type: 3} 46 | screenSpaceShadowPS: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, type: 3} 47 | samplingPS: {fileID: 4800000, guid: 04c410c9937594faa893a11dceb85f7e, type: 3} 48 | stencilDeferredPS: {fileID: 4800000, guid: e9155b26e1bc55942a41e518703fe304, type: 3} 49 | fallbackErrorPS: {fileID: 4800000, guid: e6e9a19c3678ded42a3bc431ebef7dbd, type: 3} 50 | materialErrorPS: {fileID: 4800000, guid: 5fd9a8feb75a4b5894c241777f519d4e, type: 3} 51 | coreBlitPS: {fileID: 4800000, guid: 93446b5c5339d4f00b85c159e1159b7c, type: 3} 52 | coreBlitColorAndDepthPS: {fileID: 4800000, guid: d104b2fc1ca6445babb8e90b0758136b, type: 3} 53 | cameraMotionVector: {fileID: 4800000, guid: c56b7e0d4c7cb484e959caeeedae9bbf, type: 3} 54 | objectMotionVector: {fileID: 4800000, guid: 7b3ede40266cd49a395def176e1bc486, type: 3} 55 | m_AssetVersion: 1 56 | m_OpaqueLayerMask: 57 | serializedVersion: 2 58 | m_Bits: 4294967295 59 | m_TransparentLayerMask: 60 | serializedVersion: 2 61 | m_Bits: 4294967295 62 | m_DefaultStencilState: 63 | overrideStencilState: 0 64 | stencilReference: 0 65 | stencilCompareFunction: 8 66 | passOperation: 2 67 | failOperation: 0 68 | zFailOperation: 0 69 | m_ShadowTransparentReceive: 1 70 | m_RenderingMode: 0 71 | m_DepthPrimingMode: 0 72 | m_AccurateGbufferNormals: 0 73 | m_ClusteredRendering: 0 74 | m_TileSize: 32 75 | m_IntermediateTextureMode: 1 76 | -------------------------------------------------------------------------------- /Runtime/Profile/PipelineSettings/PlayerRenderer.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d906d9b24e9fa3d49939d66b21a36367 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Profile/PipelineSettings/VTPipelineAsset.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3} 13 | m_Name: VTPipelineAsset 14 | m_EditorClassIdentifier: 15 | k_AssetVersion: 11 16 | k_AssetPreviousVersion: 11 17 | m_RendererType: 1 18 | m_RendererData: {fileID: 0} 19 | m_RendererDataList: 20 | - {fileID: 11400000, guid: d906d9b24e9fa3d49939d66b21a36367, type: 2} 21 | m_DefaultRendererIndex: 0 22 | m_RequireDepthTexture: 0 23 | m_RequireOpaqueTexture: 0 24 | m_OpaqueDownsampling: 1 25 | m_SupportsTerrainHoles: 1 26 | m_SupportsHDR: 1 27 | m_HDRColorBufferPrecision: 0 28 | m_MSAA: 4 29 | m_RenderScale: 1 30 | m_UpscalingFilter: 0 31 | m_FsrOverrideSharpness: 0 32 | m_FsrSharpness: 0.92 33 | m_EnableLODCrossFade: 1 34 | m_LODCrossFadeDitheringType: 1 35 | m_MainLightRenderingMode: 1 36 | m_MainLightShadowsSupported: 1 37 | m_MainLightShadowmapResolution: 2048 38 | m_AdditionalLightsRenderingMode: 1 39 | m_AdditionalLightsPerObjectLimit: 4 40 | m_AdditionalLightShadowsSupported: 0 41 | m_AdditionalLightsShadowmapResolution: 1024 42 | m_AdditionalLightsShadowResolutionTierLow: 256 43 | m_AdditionalLightsShadowResolutionTierMedium: 512 44 | m_AdditionalLightsShadowResolutionTierHigh: 1024 45 | m_ReflectionProbeBlending: 0 46 | m_ReflectionProbeBoxProjection: 0 47 | m_ShadowDistance: 128 48 | m_ShadowCascadeCount: 4 49 | m_Cascade2Split: 0.25 50 | m_Cascade3Split: {x: 0.1, y: 0.3} 51 | m_Cascade4Split: {x: 0.078125, y: 0.203125, z: 0.453125} 52 | m_CascadeBorder: 0.2 53 | m_ShadowDepthBias: 1 54 | m_ShadowNormalBias: 1 55 | m_SoftShadowsSupported: 1 56 | m_ConservativeEnclosingSphere: 0 57 | m_NumIterationsEnclosingSphere: 64 58 | m_AdditionalLightsCookieResolution: 2048 59 | m_AdditionalLightsCookieFormat: 3 60 | m_UseSRPBatcher: 1 61 | m_SupportsDynamicBatching: 0 62 | m_MixedLightingSupported: 1 63 | m_SupportsLightCookies: 1 64 | m_SupportsLightLayers: 0 65 | m_DebugLevel: 0 66 | m_StoreActionsOptimization: 0 67 | m_EnableRenderGraph: 0 68 | m_UseAdaptivePerformance: 1 69 | m_ColorGradingMode: 1 70 | m_ColorGradingLutSize: 32 71 | m_UseFastSRGBLinearConversion: 0 72 | m_ShadowType: 1 73 | m_LocalShadowsSupported: 0 74 | m_LocalShadowsAtlasResolution: 256 75 | m_MaxPixelLights: 0 76 | m_ShadowAtlasResolution: 256 77 | m_VolumeFrameworkUpdateMode: 0 78 | m_Textures: 79 | blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} 80 | bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} 81 | m_ShaderVariantLogLevel: 0 82 | m_ShadowCascades: 2 83 | -------------------------------------------------------------------------------- /Runtime/Profile/PipelineSettings/VTPipelineAsset.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5230371a93f369e49aa3edad2bf5219d 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Profile/RuntimeVirtualTexture.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: f0ae849b22a795a4c863c571f46450d6, type: 3} 13 | m_Name: RuntimeVirtualTexture 14 | m_EditorClassIdentifier: 15 | tileNum: 16 16 | tileSize: 200 17 | tileBorder: 2 18 | pageSize: 2048 19 | compressMode: 2 20 | m_Shader: {fileID: 7200000, guid: e34776c72005e1e488fbdc217f4556c5, type: 3} 21 | -------------------------------------------------------------------------------- /Runtime/Profile/RuntimeVirtualTexture.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b8650e03683bb0844a15d265c3b49a85 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 0 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Renderer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2b6710f8e3b7344c938de592e4bbefe 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Renderer/FeedbackRenderer.cs: -------------------------------------------------------------------------------- 1 | using Unity.Jobs; 2 | using UnityEngine; 3 | using Unity.Mathematics; 4 | using Unity.Collections; 5 | using UnityEngine.Rendering; 6 | using UnityEngine.Rendering.Universal; 7 | using UnityEngine.Experimental.Rendering; 8 | 9 | namespace Landscape.RuntimeVirtualTexture 10 | { 11 | public enum EFeedbackScale 12 | { 13 | X1 = 1, 14 | X2 = 2, 15 | X4 = 4, 16 | X8 = 8, 17 | X16 = 16 18 | } 19 | 20 | internal enum EVirtualTexturePass 21 | { 22 | VirtualTexture, 23 | DrawFeedback, 24 | DrawPageTable, 25 | DrawPageColor, 26 | CompressPage, 27 | CopyPageToPhyscis 28 | } 29 | 30 | internal class FeedbackRenderPass : ScriptableRenderPass 31 | { 32 | int2 m_FeedbackSize; 33 | LayerMask m_LayerMask; 34 | ShaderTagId m_ShaderPassID; 35 | EFeedbackScale m_FeedbackScale; 36 | FilteringSettings m_FilterSetting; 37 | ProfilingSampler m_DrawFeedbackSampler; 38 | ProfilingSampler m_DrawPageTableSampler; 39 | ProfilingSampler m_DrawPageColorSampler; 40 | ProfilingSampler m_VirtualTextureSampler; 41 | RenderTexture m_FeedbackTexture; 42 | RenderTargetIdentifier m_FeedbackTextureID; 43 | FVirtualTextureFeedback m_FeedbackProcessor; 44 | 45 | public FeedbackRenderPass(in LayerMask layerMask, int2 feedbackSize, in EFeedbackScale feedbackScale) 46 | { 47 | m_LayerMask = layerMask; 48 | m_FeedbackSize = feedbackSize; 49 | m_FeedbackScale = feedbackScale; 50 | m_ShaderPassID = new ShaderTagId("VTFeedback"); 51 | m_FilterSetting = new FilteringSettings(RenderQueueRange.opaque, m_LayerMask); 52 | m_DrawFeedbackSampler = ProfilingSampler.Get(EVirtualTexturePass.DrawFeedback); 53 | m_DrawPageTableSampler = ProfilingSampler.Get(EVirtualTexturePass.DrawPageTable); 54 | m_DrawPageColorSampler = ProfilingSampler.Get(EVirtualTexturePass.DrawPageColor); 55 | m_VirtualTextureSampler = ProfilingSampler.Get(EVirtualTexturePass.VirtualTexture); 56 | m_FeedbackProcessor = new FVirtualTextureFeedback(true); 57 | } 58 | 59 | public override void OnCameraSetup(CommandBuffer cmdBuffer, ref RenderingData renderingData) 60 | { 61 | Camera camera = renderingData.cameraData.camera; 62 | int2 size = new int2(math.min(m_FeedbackSize.x, camera.pixelWidth), math.min(m_FeedbackSize.y, camera.pixelHeight)); 63 | m_FeedbackTexture = RenderTexture.GetTemporary(size.x / (int)m_FeedbackScale, size.y / (int)m_FeedbackScale, 1, GraphicsFormat.R8G8B8A8_UNorm, 1); 64 | m_FeedbackTexture.name = "FeedbackTexture"; 65 | m_FeedbackTextureID = new RenderTargetIdentifier(m_FeedbackTexture); 66 | //ConfigureTarget(m_FeedbackTextureID); 67 | //ConfigureClear(ClearFlag.All, Color.black); 68 | } 69 | 70 | public override void Execute(ScriptableRenderContext renderContext, ref RenderingData renderingData) 71 | { 72 | if (!Application.isPlaying || VirtualTextureVolume.s_VirtualTextureVolume == null) { return; } 73 | 74 | CommandBuffer cmdBuffer = CommandBufferPool.Get(); 75 | Camera camera = renderingData.cameraData.camera; 76 | 77 | using (new ProfilingScope(cmdBuffer, m_VirtualTextureSampler)) 78 | { 79 | renderContext.ExecuteCommandBuffer(cmdBuffer); 80 | cmdBuffer.Clear(); 81 | DrawVirtualTexture(renderContext, cmdBuffer, camera, ref renderingData); 82 | } 83 | 84 | renderContext.ExecuteCommandBuffer(cmdBuffer); 85 | CommandBufferPool.Release(cmdBuffer); 86 | } 87 | 88 | public override void OnCameraCleanup(CommandBuffer cmdBuffer) 89 | { 90 | RenderTexture.ReleaseTemporary(m_FeedbackTexture); 91 | } 92 | 93 | public unsafe void DrawVirtualTexture(ScriptableRenderContext renderContext, CommandBuffer cmdBuffer, Camera camera, ref RenderingData renderingData) 94 | { 95 | FPageProducer pageProducer = VirtualTextureVolume.s_VirtualTextureVolume.pageProducer; 96 | FPageRenderer pageRenderer = VirtualTextureVolume.s_VirtualTextureVolume.pageRenderer; 97 | VirtualTextureAsset virtualTexture = VirtualTextureVolume.s_VirtualTextureVolume.virtualTexture; 98 | 99 | using (new ProfilingScope(cmdBuffer, m_DrawPageTableSampler)) 100 | { 101 | if (m_FeedbackProcessor.isReady) 102 | { 103 | NativeArray decodeDatas = new NativeArray(m_FeedbackProcessor.readbackDatas.Length, Allocator.TempJob); 104 | 105 | FDecodeFeedbackJob decodeFeedbackJob; 106 | decodeFeedbackJob.pageSize = virtualTexture.pageSize; 107 | decodeFeedbackJob.decodeDatas = decodeDatas; 108 | decodeFeedbackJob.encodeDatas = m_FeedbackProcessor.readbackDatas; 109 | decodeFeedbackJob.Schedule(m_FeedbackProcessor.readbackDatas.Length, 256).Complete(); 110 | 111 | pageProducer.ProcessFeedback(ref decodeDatas, virtualTexture.NumMip, virtualTexture.tileNum, virtualTexture.pageSize, virtualTexture.lruCache, ref pageRenderer.loadRequests); 112 | decodeDatas.Dispose(); 113 | 114 | cmdBuffer.SetRenderTarget(virtualTexture.tableTextureID); 115 | pageRenderer.DrawPageTable(renderContext, cmdBuffer, pageProducer); 116 | 117 | } 118 | } 119 | 120 | using (new ProfilingScope(cmdBuffer, m_DrawFeedbackSampler)) 121 | { 122 | DrawingSettings drawSetting = new DrawingSettings(m_ShaderPassID, new SortingSettings(camera) { criteria = SortingCriteria.QuantizedFrontToBack }) 123 | { 124 | enableInstancing = true, 125 | }; 126 | cmdBuffer.SetRenderTarget(m_FeedbackTextureID); 127 | cmdBuffer.ClearRenderTarget(true, true, Color.black); 128 | // x: 页表大小(单位: 页) 129 | // y: 虚拟贴图大小(单位: 像素) 130 | // z: 最大mipmap等级 131 | // w: mipBias 132 | cmdBuffer.SetGlobalVector("_VTFeedbackParams", new Vector4(virtualTexture.pageSize, virtualTexture.pageSize * virtualTexture.tileSize * (1.0f / (float)m_FeedbackScale), virtualTexture.NumMip, 0.1f)); 133 | 134 | float cameraAspect = (float) camera.pixelRect.width / (float) camera.pixelRect.height; 135 | Matrix4x4 projectionMatrix = Matrix4x4.Perspective(90, cameraAspect, camera.nearClipPlane, camera.farClipPlane); 136 | projectionMatrix = GL.GetGPUProjectionMatrix(projectionMatrix, true); 137 | RenderingUtils.SetViewAndProjectionMatrices(cmdBuffer, camera.worldToCameraMatrix, projectionMatrix, false); 138 | renderContext.ExecuteCommandBuffer(cmdBuffer); 139 | cmdBuffer.Clear(); 140 | 141 | renderContext.DrawRenderers(renderingData.cullResults, ref drawSetting, ref m_FilterSetting); 142 | 143 | projectionMatrix = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); 144 | RenderingUtils.SetViewAndProjectionMatrices(cmdBuffer, camera.worldToCameraMatrix, projectionMatrix, false); 145 | renderContext.ExecuteCommandBuffer(cmdBuffer); 146 | cmdBuffer.Clear(); 147 | } 148 | 149 | //read-back feedback 150 | m_FeedbackProcessor.RequestReadback(cmdBuffer, m_FeedbackTexture); 151 | 152 | using (new ProfilingScope(cmdBuffer, m_DrawPageColorSampler)) 153 | { 154 | cmdBuffer.SetRenderTarget(virtualTexture.colorTextureIDs, virtualTexture.colorTextureIDs[0]); 155 | renderContext.ExecuteCommandBuffer(cmdBuffer); 156 | cmdBuffer.Clear(); 157 | 158 | FDrawPageParameter drawPageParameter = VirtualTextureVolume.s_VirtualTextureVolume.GetDrawPageParamter(); 159 | pageRenderer.DrawPageColor(renderContext, cmdBuffer, pageProducer, virtualTexture, ref virtualTexture.lruCache[0], drawPageParameter); 160 | } 161 | } 162 | } 163 | 164 | public class FeedbackRenderer : ScriptableRendererFeature 165 | { 166 | [Header("Filter")] 167 | public LayerMask layerMask; 168 | 169 | [Header("Feedback")] 170 | public int2 feedbackSize; 171 | public EFeedbackScale feedbackScale; 172 | 173 | FeedbackRenderPass m_FeedbackRenderPass; 174 | 175 | public override void Create() 176 | { 177 | m_FeedbackRenderPass = new FeedbackRenderPass(layerMask, feedbackSize, feedbackScale); 178 | m_FeedbackRenderPass.renderPassEvent = RenderPassEvent.BeforeRenderingPrePasses; 179 | } 180 | 181 | public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) 182 | { 183 | renderer.EnqueuePass(m_FeedbackRenderPass); 184 | } 185 | 186 | protected override void Dispose(bool disposing) 187 | { 188 | 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /Runtime/Renderer/FeedbackRenderer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d9afec8bd61f784aa5e6435b73a3e61 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d3a1c39dae6c2844bb82421d269a82e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Source/LruCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unity.Collections; 3 | using System.Diagnostics; 4 | using System.Collections.Generic; 5 | using System.Runtime.InteropServices; 6 | using Unity.Collections.LowLevel.Unsafe; 7 | 8 | namespace Landscape.RuntimeVirtualTexture 9 | { 10 | internal struct FNodeInfo 11 | { 12 | public int id; 13 | public int nextID; 14 | public int prevID; 15 | } 16 | 17 | #if UNITY_EDITOR 18 | internal unsafe sealed class FLruCacheDebugView 19 | { 20 | FLruCache m_Target; 21 | 22 | public FLruCacheDebugView(FLruCache target) 23 | { 24 | m_Target = target; 25 | } 26 | 27 | public int Length 28 | { 29 | get 30 | { 31 | return m_Target.length; 32 | } 33 | } 34 | 35 | public FNodeInfo HeadNode 36 | { 37 | get 38 | { 39 | return m_Target.headNodeInfo; 40 | } 41 | } 42 | 43 | public FNodeInfo TailNode 44 | { 45 | get 46 | { 47 | return m_Target.tailNodeInfo; 48 | } 49 | } 50 | 51 | public List NodeInfos 52 | { 53 | get 54 | { 55 | var result = new List(); 56 | for (int i = 0; i < m_Target.length; ++i) 57 | { 58 | result.Add(m_Target.nodeInfoList[i]); 59 | } 60 | return result; 61 | } 62 | } 63 | } 64 | 65 | [DebuggerTypeProxy(typeof(FLruCacheDebugView))] 66 | #endif 67 | internal unsafe struct FLruCache : IDisposable 68 | { 69 | internal int length; 70 | internal FNodeInfo headNodeInfo; 71 | internal FNodeInfo tailNodeInfo; 72 | [NativeDisableUnsafePtrRestriction] 73 | internal FNodeInfo* nodeInfoList; 74 | internal int First { get { return headNodeInfo.id; } } 75 | 76 | public FLruCache(in int length) 77 | { 78 | this.length = length; 79 | this.nodeInfoList = (FNodeInfo*)UnsafeUtility.Malloc(Marshal.SizeOf(typeof(FNodeInfo)) * length, 64, Allocator.Persistent); 80 | 81 | for (int i = 0; i < length; ++i) 82 | { 83 | nodeInfoList[i] = new FNodeInfo() 84 | { 85 | id = i, 86 | }; 87 | } 88 | for (int j = 0; j < length; ++j) 89 | { 90 | nodeInfoList[j].prevID = (j != 0) ? nodeInfoList[j - 1].id : 0; 91 | nodeInfoList[j].nextID = (j + 1 < length) ? nodeInfoList[j + 1].id : length - 1; 92 | } 93 | this.headNodeInfo = nodeInfoList[0]; 94 | this.tailNodeInfo = nodeInfoList[length - 1]; 95 | } 96 | 97 | public static void BuildLruCache(ref FLruCache lruCache, in int count) 98 | { 99 | lruCache.length = count; 100 | lruCache.nodeInfoList = (FNodeInfo*)UnsafeUtility.Malloc(Marshal.SizeOf(typeof(FNodeInfo)) * count, 64, Allocator.Persistent); 101 | 102 | for (int i = 0; i < count; ++i) 103 | { 104 | lruCache.nodeInfoList[i] = new FNodeInfo() 105 | { 106 | id = i, 107 | }; 108 | } 109 | for (int j = 0; j < count; ++j) 110 | { 111 | lruCache.nodeInfoList[j].prevID = (j != 0) ? lruCache.nodeInfoList[j - 1].id : 0; 112 | lruCache.nodeInfoList[j].nextID = (j + 1 < count) ? lruCache.nodeInfoList[j + 1].id : count - 1; 113 | } 114 | lruCache.headNodeInfo = lruCache.nodeInfoList[0]; 115 | lruCache.tailNodeInfo = lruCache.nodeInfoList[count - 1]; 116 | } 117 | 118 | public void Dispose() 119 | { 120 | UnsafeUtility.Free((void*)nodeInfoList, Allocator.Persistent); 121 | } 122 | 123 | public bool SetActive(in int id) 124 | { 125 | if (id < 0 || id >= length) { return false; } 126 | 127 | ref FNodeInfo nodeInfo = ref nodeInfoList[id]; 128 | if (nodeInfo.id == tailNodeInfo.id) { return true; } 129 | 130 | Remove(ref nodeInfo); 131 | AddLast(ref nodeInfo); 132 | return true; 133 | } 134 | 135 | private void AddLast(ref FNodeInfo nodeInfo) 136 | { 137 | ref FNodeInfo lastNodeInfo = ref nodeInfoList[tailNodeInfo.id]; 138 | tailNodeInfo = nodeInfo; 139 | 140 | lastNodeInfo.nextID = nodeInfo.id; 141 | nodeInfoList[lastNodeInfo.nextID] = nodeInfo; 142 | 143 | nodeInfo.prevID = lastNodeInfo.id; 144 | nodeInfoList[nodeInfo.prevID] = lastNodeInfo; 145 | } 146 | 147 | private void Remove(ref FNodeInfo nodeInfo) 148 | { 149 | if (headNodeInfo.id == nodeInfo.id) 150 | { 151 | headNodeInfo = nodeInfoList[nodeInfo.nextID]; 152 | } 153 | else 154 | { 155 | ref FNodeInfo prevNodeInfo = ref nodeInfoList[nodeInfo.prevID]; 156 | ref FNodeInfo nextNodeInfo = ref nodeInfoList[nodeInfo.nextID]; 157 | prevNodeInfo.nextID = nodeInfo.nextID; 158 | nextNodeInfo.prevID = nodeInfo.prevID; 159 | nodeInfoList[prevNodeInfo.nextID] = nextNodeInfo; 160 | nodeInfoList[nextNodeInfo.prevID] = prevNodeInfo; 161 | } 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /Runtime/Source/LruCache.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a981688ef6dfcfe44a73c5ea8cab59bc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/NativeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Unity.Jobs; 2 | using Unity.Burst; 3 | using UnityEngine; 4 | using Unity.Collections; 5 | using Unity.Mathematics; 6 | using Unity.Collections.LowLevel.Unsafe; 7 | using System.Collections.Generic; 8 | using System; 9 | 10 | namespace Landscape.RuntimeVirtualTexture 11 | { 12 | static class NativeExtensions 13 | { 14 | public static int ToInt(this Color32 color) 15 | { 16 | return (int)color.r + ((int)color.g << 8) + ((int)color.b << 16) + ((int)color.a << 24); 17 | } 18 | 19 | [BurstCompatible(GenericTypeArguments = new[] { typeof(int) })] 20 | internal struct DefaultComparer : IEqualityComparer where T : IEquatable 21 | { 22 | public bool Equals(T x, T y) => x.Equals(y); 23 | 24 | public int GetHashCode(T obj) 25 | { 26 | return obj.GetHashCode(); 27 | } 28 | } 29 | 30 | [BurstCompatible(GenericTypeArguments = new[] { typeof(int), typeof(DefaultComparer) })] 31 | public static unsafe int Unique(T* array, int size, U comp) where T : unmanaged where U : IEqualityComparer 32 | { 33 | int length = 0, current = 1; 34 | while (current < size) 35 | { 36 | if (!comp.Equals(array[current], array[length])) 37 | { 38 | length += 1; 39 | if (current != length) 40 | array[length] = array[current]; 41 | } 42 | current += 1; 43 | } 44 | return length; 45 | } 46 | 47 | public static unsafe int Unique(T* array, int size) where T : unmanaged, IEquatable 48 | { 49 | return Unique(array, size, new DefaultComparer()); 50 | } 51 | 52 | public static unsafe NativeArray Unique(NativeArray array) where T : unmanaged, IEquatable 53 | { 54 | return array.GetSubArray(0, Unique((T*)array.GetUnsafePtr(), array.Length, new DefaultComparer())); 55 | } 56 | 57 | public static int Combine(int newKey, int currentKey) 58 | { 59 | return unchecked((currentKey * (int)0xA5555529) + newKey); 60 | } 61 | } 62 | 63 | [BurstCompatible] 64 | struct ColorComparer : IComparer 65 | { 66 | public int Compare(Color32 x, Color32 y) => x.ToInt().CompareTo(y.ToInt()); 67 | } 68 | 69 | [BurstCompatible] 70 | struct ColorEqualComparer : IEqualityComparer 71 | { 72 | public bool Equals(Color32 x, Color32 y) => x.ToInt() == y.ToInt(); 73 | public int GetHashCode(Color32 obj) => obj.GetHashCode(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Runtime/Source/NativeExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df5b535f89a552b44a528a46b173733c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureAsset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Unity.Mathematics; 4 | using Unity.Collections; 5 | using UnityEngine.Rendering; 6 | using Object = UnityEngine.Object; 7 | using System.Runtime.InteropServices; 8 | using Unity.Collections.LowLevel.Unsafe; 9 | using UnityEngine.Experimental.Rendering; 10 | 11 | namespace Landscape.RuntimeVirtualTexture 12 | { 13 | public enum EBorder 14 | { 15 | X0 = 0, 16 | X1 = 1, 17 | X2 = 2, 18 | X4 = 4 19 | } 20 | 21 | public enum ECompressMode 22 | { 23 | None = 0, 24 | Bit8 = 1, 25 | Bit16 = 2 26 | } 27 | 28 | [CreateAssetMenu(menuName = "Landscape/VirtualTextureAsset")] 29 | public unsafe class VirtualTextureAsset : ScriptableObject, IDisposable 30 | { 31 | [Range(8, 32)] 32 | public int tileNum = 16; 33 | [Range(64, 512)] 34 | public int tileSize = 256; 35 | public EBorder tileBorder = EBorder.X4; 36 | [Range(128, 4096)] 37 | public int pageSize = 256; 38 | public ECompressMode compressMode = ECompressMode.Bit16; 39 | 40 | public int NumMip { get { return (int)math.log2(pageSize) + 1; } } 41 | public int TileSizePadding { get { return tileSize + (int)tileBorder * 2; } } 42 | public int QuadTileSizePadding { get { return TileSizePadding / 4; } } 43 | 44 | [HideInInspector] 45 | public ComputeShader m_Shader; 46 | 47 | internal FLruCache* lruCache; 48 | internal RenderTargetIdentifier tableTextureID; 49 | internal RenderTargetIdentifier[] colorTextureIDs; 50 | internal int TextureSize { get { return tileNum * TileSizePadding; } } 51 | 52 | private RenderTexture m_physicsTextureA; 53 | private RenderTexture m_physicsTextureB; 54 | private RenderTexture m_pageTableTexture; 55 | 56 | public void Initialize() 57 | { 58 | lruCache = (FLruCache*)UnsafeUtility.Malloc(Marshal.SizeOf(typeof(FLruCache)) * 1, 64, Allocator.Persistent); 59 | FLruCache.BuildLruCache(ref lruCache[0], tileNum * tileNum); 60 | 61 | RenderTextureFormat format = RenderTextureFormat.ARGB32; 62 | switch (compressMode) 63 | { 64 | case ECompressMode.Bit8: 65 | format = RenderTextureFormat.RGB565; 66 | break; 67 | case ECompressMode.Bit16: 68 | format = RenderTextureFormat.RGB565; 69 | break; 70 | } 71 | 72 | RenderTextureDescriptor textureDesctiptor = new RenderTextureDescriptor { width = TextureSize, height = TextureSize, volumeDepth = 1, dimension = TextureDimension.Tex2D, colorFormat = format, depthBufferBits = 0, mipCount = -1, useMipMap = false, autoGenerateMips = false, bindMS = false, msaaSamples = 1 }; 73 | 74 | //physics texture 75 | m_physicsTextureA = new RenderTexture(textureDesctiptor); 76 | m_physicsTextureA.bindTextureMS = false; 77 | m_physicsTextureA.name = "PhysicsTextureA"; 78 | m_physicsTextureA.wrapMode = TextureWrapMode.Clamp; 79 | m_physicsTextureA.filterMode = FilterMode.Trilinear; 80 | m_physicsTextureA.anisoLevel = 16; 81 | m_physicsTextureA.Create(); 82 | 83 | m_physicsTextureB = new RenderTexture(textureDesctiptor); 84 | m_physicsTextureB.bindTextureMS = false; 85 | m_physicsTextureB.name = "PhysicsTextureB"; 86 | m_physicsTextureB.wrapMode = TextureWrapMode.Clamp; 87 | m_physicsTextureB.filterMode = FilterMode.Trilinear; 88 | m_physicsTextureB.anisoLevel = 16; 89 | m_physicsTextureB.Create(); 90 | 91 | colorTextureIDs = new RenderTargetIdentifier[2]; 92 | colorTextureIDs[0] = new RenderTargetIdentifier(m_physicsTextureA); 93 | colorTextureIDs[1] = new RenderTargetIdentifier(m_physicsTextureB); 94 | 95 | m_pageTableTexture = new RenderTexture(pageSize, pageSize, 0, GraphicsFormat.R8G8B8A8_UNorm); 96 | m_pageTableTexture.bindTextureMS = false; 97 | m_pageTableTexture.name = "PageTableTexture"; 98 | m_pageTableTexture.filterMode = FilterMode.Point; 99 | m_pageTableTexture.wrapMode = TextureWrapMode.Clamp; 100 | 101 | tableTextureID = new RenderTargetIdentifier(m_pageTableTexture); 102 | 103 | // 设置Shader参数 104 | // x: padding 偏移量 105 | // y: tile 有效区域的尺寸 106 | // zw: 1/区域尺寸 107 | Shader.SetGlobalTexture("_PhyscisAlbedo", m_physicsTextureA); 108 | Shader.SetGlobalTexture("_PhyscisNormal", m_physicsTextureB); 109 | Shader.SetGlobalTexture("_PageTableTexture", m_pageTableTexture); 110 | Shader.SetGlobalVector("_VTPageParams", new Vector4(pageSize, 1 / pageSize, NumMip - 1, 0)); 111 | Shader.SetGlobalVector("_VTPageTileParams", new Vector4((float)tileBorder, (float)tileSize, TextureSize, TextureSize)); 112 | } 113 | 114 | public void Dispose() 115 | { 116 | lruCache[0].Dispose(); 117 | UnsafeUtility.Free((void*)lruCache, Allocator.Persistent); 118 | 119 | m_physicsTextureA.Release(); 120 | m_physicsTextureB.Release(); 121 | m_pageTableTexture.Release(); 122 | Object.Destroy(m_physicsTextureA); 123 | Object.Destroy(m_physicsTextureB); 124 | Object.Destroy(m_pageTableTexture); 125 | } 126 | } 127 | } -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureAsset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f0ae849b22a795a4c863c571f46450d6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_Shader: {fileID: 7200000, guid: e34776c72005e1e488fbdc217f4556c5, type: 3} 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureFeedback.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using Unity.Collections; 3 | using UnityEngine.Rendering; 4 | 5 | namespace Landscape.RuntimeVirtualTexture 6 | { 7 | internal unsafe class FVirtualTextureFeedback 8 | { 9 | internal bool isReady; 10 | internal NativeArray readbackDatas; 11 | 12 | public FVirtualTextureFeedback(in bool bReady) 13 | { 14 | isReady = bReady; 15 | } 16 | 17 | internal void RequestReadback(CommandBuffer cmdBuffer, RenderTexture feedbackTexture) 18 | { 19 | isReady = false; 20 | cmdBuffer.RequestAsyncReadback(feedbackTexture, 0, feedbackTexture.graphicsFormat, EnqueueCopy); 21 | } 22 | 23 | private void EnqueueCopy(AsyncGPUReadbackRequest request) 24 | { 25 | if (request.hasError || request.done == true) 26 | { 27 | isReady = true; 28 | readbackDatas = request.GetData(); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureFeedback.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c831d4ec0c8b28c40a65fefe6d49a7ac 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureJob.cs: -------------------------------------------------------------------------------- 1 | using Unity.Jobs; 2 | using Unity.Burst; 3 | using UnityEngine; 4 | using Unity.Collections; 5 | using Unity.Mathematics; 6 | using Unity.Collections.LowLevel.Unsafe; 7 | 8 | namespace Landscape.RuntimeVirtualTexture 9 | { 10 | [BurstCompile] 11 | internal struct FDecodeFeedbackJob : IJobParallelFor 12 | { 13 | [ReadOnly] 14 | internal int pageSize; 15 | 16 | [ReadOnly] 17 | internal NativeArray encodeDatas; 18 | 19 | [WriteOnly] 20 | internal NativeArray decodeDatas; 21 | 22 | public void Execute(int index) 23 | { 24 | Color32 x = encodeDatas[index]; 25 | float4 xRaw = new float4((float)x.r / 255.0f, (float)x.g / 255.0f, (float)x.b / 255.0f, x.a); 26 | 27 | float3 x888 = math.floor(xRaw.xyz * 255); 28 | float High = math.floor(x888.z / 16); // x888.z >> 4 29 | float Low = x888.z - High * 16; // x888.z & 15 30 | float2 x1212 = x888.xy + new float2(Low, High) * 256; 31 | x1212 = math.saturate(x1212 / 4095) * pageSize; 32 | 33 | decodeDatas[index] = new int4((int)x1212.x, (int)x1212.y, x.a, 255); 34 | } 35 | } 36 | 37 | [BurstCompile] 38 | internal unsafe struct FAnalysisFeedbackJob : IJob 39 | { 40 | internal int maxMip; 41 | 42 | internal int pageSize; 43 | 44 | internal int tileNum; 45 | 46 | internal int frameCount; 47 | 48 | [NativeDisableUnsafePtrRestriction] 49 | internal FLruCache* lruCache; 50 | 51 | [ReadOnly] 52 | internal NativeArray readbackDatas; 53 | 54 | [ReadOnly] 55 | internal NativeArray pageTables; 56 | 57 | internal NativeList loadRequests; 58 | 59 | public void Execute() 60 | { 61 | int4 prevValue = -1; 62 | 63 | for (int i = 0; i < readbackDatas.Length; ++i) 64 | { 65 | int4 readbackData = readbackDatas[i]; 66 | 67 | if (readbackData.Equals(prevValue)) //skip same page 68 | continue; 69 | 70 | prevValue = readbackData; 71 | 72 | if (readbackData.z > maxMip || readbackData.z < 0 || readbackData.x < 0 || readbackData.y < 0 || readbackData.x >= pageSize || readbackData.y >= pageSize) 73 | continue; 74 | 75 | ref FPage page = ref pageTables[readbackData.z].GetPage(readbackData.x, readbackData.y); 76 | 77 | if (page.isNull) 78 | continue; 79 | 80 | if (!page.payload.isReady && page.payload.notLoading) 81 | { 82 | page.payload.notLoading = false; 83 | loadRequests.AddNoResize(new FPageLoadInfo(readbackData.x, readbackData.y, readbackData.z)); 84 | } 85 | 86 | if (page.payload.isReady && page.payload.activeFrame != frameCount) 87 | { 88 | page.payload.activeFrame = frameCount; 89 | lruCache[0].SetActive(page.payload.pageCoord.y * tileNum + page.payload.pageCoord.x); 90 | } 91 | } 92 | } 93 | } 94 | 95 | [BurstCompile] 96 | internal struct FPageDrawInfoBuildJob : IJob 97 | { 98 | internal int pageSize; 99 | 100 | internal int frameTime; 101 | 102 | [ReadOnly] 103 | internal NativeArray pageTables; 104 | 105 | [WriteOnly] 106 | internal NativeList drawInfos; 107 | 108 | [ReadOnly] 109 | internal NativeParallelHashMap.Enumerator pageEnumerator; 110 | 111 | public void Execute() 112 | { 113 | while (pageEnumerator.MoveNext()) 114 | { 115 | var pageCoord = pageEnumerator.Current.Value; 116 | FPageTable pageTable = pageTables[pageCoord.z]; 117 | ref FPage page = ref pageTable.GetPage(pageCoord.x, pageCoord.y); 118 | if (page.payload.activeFrame != frameTime) { continue; } 119 | 120 | int2 rectXY = new int2(page.rect.xMin, page.rect.yMin); 121 | while (rectXY.x < 0) 122 | { 123 | rectXY.x += pageSize; 124 | } 125 | while (rectXY.y < 0) 126 | { 127 | rectXY.y += pageSize; 128 | } 129 | 130 | FPageDrawInfo drawInfo; 131 | drawInfo.mip = page.mipLevel; 132 | drawInfo.rect = new FRect(rectXY.x, rectXY.y, page.rect.width, page.rect.height); 133 | drawInfo.drawPos = new float2((float)page.payload.pageCoord.x / 255, (float)page.payload.pageCoord.y / 255); 134 | drawInfos.Add(drawInfo); 135 | } 136 | } 137 | } 138 | 139 | [BurstCompile] 140 | internal struct FPageDrawInfoSortJob : IJob 141 | { 142 | internal NativeList drawInfos; 143 | 144 | public void Execute() 145 | { 146 | drawInfos.Sort(); 147 | } 148 | } 149 | 150 | [BurstCompile] 151 | internal struct FPageTableInfoBuildJob : IJobParallelFor 152 | { 153 | internal int pageSize; 154 | 155 | [ReadOnly] 156 | internal NativeList drawInfos; 157 | 158 | [WriteOnly] 159 | internal NativeArray pageTableInfos; 160 | 161 | public void Execute(int i) 162 | { 163 | FPageTableInfo pageInfo; 164 | pageInfo.pageData = new float4(drawInfos[i].drawPos.x, drawInfos[i].drawPos.y, drawInfos[i].mip / 255f, 0); 165 | pageInfo.matrix_M = float4x4.TRS(new float3(drawInfos[i].rect.x / pageSize, drawInfos[i].rect.y / pageSize, 0), quaternion.identity, drawInfos[i].rect.width / pageSize); 166 | pageTableInfos[i] = pageInfo; 167 | } 168 | } 169 | 170 | [BurstCompile] 171 | internal struct FPageRequestInfoSortJob : IJob 172 | { 173 | internal NativeList loadRequests; 174 | 175 | public void Execute() 176 | { 177 | loadRequests.Sort(); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b65c2d9ca4cc61a45bdb78095fe30bd9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTexturePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unity.Mathematics; 3 | using Unity.Collections; 4 | using System.Diagnostics; 5 | using System.Collections.Generic; 6 | using System.Runtime.InteropServices; 7 | using Unity.Collections.LowLevel.Unsafe; 8 | 9 | namespace Landscape.RuntimeVirtualTexture 10 | { 11 | internal struct FPage 12 | { 13 | public bool isNull; 14 | public int mipLevel; 15 | public FRectInt rect; 16 | public FPagePayload payload; 17 | 18 | public FPage(int x, int y, int width, int height, int mipLevel, bool isNull = false) 19 | { 20 | this.rect = new FRectInt(x, y, width, height); 21 | this.isNull = isNull; 22 | this.mipLevel = mipLevel; 23 | this.payload = new FPagePayload(); 24 | this.payload.pageCoord = new int2(-1, -1); 25 | this.payload.notLoading = true; 26 | } 27 | 28 | public bool Equals(in FPage Target) 29 | { 30 | return rect.Equals(Target.rect) && payload.Equals(Target.payload) && mipLevel.Equals(Target.mipLevel) && isNull.Equals(Target.isNull); 31 | } 32 | 33 | public override bool Equals(object obj) 34 | { 35 | return Equals((FPage)obj); 36 | } 37 | 38 | public override int GetHashCode() 39 | { 40 | int hash = NativeExtensions.Combine(rect.GetHashCode(), payload.GetHashCode()); 41 | hash = NativeExtensions.Combine(hash, mipLevel.GetHashCode()); 42 | hash += (isNull ? 0 : 1); 43 | return hash; 44 | } 45 | } 46 | 47 | internal struct FPagePayload 48 | { 49 | internal int activeFrame; 50 | internal bool notLoading; 51 | internal int2 pageCoord; 52 | private static readonly int2 s_InvalidTileIndex = new int2(-1, -1); 53 | internal bool isReady { get { return (!pageCoord.Equals(s_InvalidTileIndex)); } } 54 | 55 | 56 | public void ResetTileIndex() 57 | { 58 | pageCoord = s_InvalidTileIndex; 59 | } 60 | 61 | public bool Equals(in FPagePayload target) 62 | { 63 | return isReady.Equals(target.isReady) && activeFrame.Equals(target.activeFrame) && pageCoord.Equals(target.pageCoord) && notLoading.Equals(target.notLoading); 64 | } 65 | 66 | public override bool Equals(object target) 67 | { 68 | return Equals((FPagePayload)target); 69 | } 70 | 71 | public override int GetHashCode() 72 | { 73 | int hash = NativeExtensions.Combine(pageCoord.GetHashCode(), activeFrame.GetHashCode()); 74 | hash = NativeExtensions.Combine(hash, notLoading.GetHashCode()); 75 | hash += (isReady ? 0 : 1); 76 | return hash; 77 | } 78 | } 79 | 80 | internal struct FPageLoadInfo : IComparable 81 | { 82 | internal int x; 83 | internal int y; 84 | internal int mipLevel; 85 | 86 | public FPageLoadInfo(in int x, in int y, in int mipLevel) 87 | { 88 | this.x = x; 89 | this.y = y; 90 | this.mipLevel = mipLevel; 91 | } 92 | 93 | public bool Equals(in FPageLoadInfo target) 94 | { 95 | return target.x == x && target.y == y && target.mipLevel == mipLevel; 96 | } 97 | 98 | public bool NotEquals(FPageLoadInfo target) 99 | { 100 | return target.x != x || target.y != y || target.mipLevel != mipLevel; 101 | } 102 | 103 | public override bool Equals(object target) 104 | { 105 | return Equals((FPageLoadInfo)target); 106 | } 107 | 108 | public override int GetHashCode() 109 | { 110 | return x.GetHashCode() + y.GetHashCode() + mipLevel.GetHashCode(); 111 | } 112 | 113 | public int CompareTo(FPageLoadInfo target) 114 | { 115 | return mipLevel.CompareTo(target.mipLevel); 116 | } 117 | } 118 | 119 | #if UNITY_EDITOR 120 | internal unsafe sealed class FPageTableDebugView 121 | { 122 | FPageTable m_Target; 123 | 124 | public FPageTableDebugView(FPageTable target) 125 | { 126 | m_Target = target; 127 | } 128 | 129 | public int mipLevel 130 | { 131 | get 132 | { 133 | return m_Target.mipLevel; 134 | } 135 | } 136 | 137 | public int cellSize 138 | { 139 | get 140 | { 141 | return m_Target.cellSize; 142 | } 143 | } 144 | 145 | public int cellCount 146 | { 147 | get 148 | { 149 | return m_Target.cellCount; 150 | } 151 | } 152 | 153 | public List pageBuffer 154 | { 155 | get 156 | { 157 | var result = new List(); 158 | for (int i = 0; i < m_Target.cellCount * m_Target.cellCount; ++i) 159 | { 160 | result.Add(m_Target.pageBuffer[i]); 161 | } 162 | return result; 163 | } 164 | } 165 | } 166 | 167 | [DebuggerTypeProxy(typeof(FPageTableDebugView))] 168 | #endif 169 | internal unsafe struct FPageTable : IDisposable 170 | { 171 | internal int mipLevel; 172 | internal int cellSize; 173 | internal int cellCount; 174 | [NativeDisableUnsafePtrRestriction] 175 | internal FPage* pageBuffer; 176 | 177 | public FPageTable(in int mipLevel, in int tableSize) 178 | { 179 | this.mipLevel = mipLevel; 180 | this.cellSize = (int)math.pow(2, mipLevel); 181 | this.cellCount = tableSize / cellSize; 182 | this.pageBuffer = (FPage*)UnsafeUtility.Malloc(Marshal.SizeOf(typeof(FPage)) * (cellCount * cellCount), 64, Allocator.Persistent); 183 | 184 | for (int i = 0; i < cellCount; ++i) 185 | { 186 | for (int j = 0; j < cellCount; ++j) 187 | { 188 | this.pageBuffer[i * cellCount + j] = new FPage(i * cellSize, j * cellSize, cellSize, cellSize, mipLevel); 189 | } 190 | } 191 | } 192 | 193 | public ref FPage GetPage(in int x, in int y) 194 | { 195 | int2 uv = new int2((x / cellSize) % cellCount, (y / cellSize) % cellCount); 196 | return ref pageBuffer[uv.x * cellCount + uv.y]; 197 | } 198 | 199 | public void Dispose() 200 | { 201 | UnsafeUtility.Free((void*)pageBuffer, Allocator.Persistent); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTexturePage.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a745a10ba6042b04e8ca4e0e791195d7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureProducer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unity.Jobs; 3 | using UnityEngine; 4 | using Unity.Mathematics; 5 | using Unity.Collections; 6 | 7 | namespace Landscape.RuntimeVirtualTexture 8 | { 9 | internal unsafe class FPageProducer : IDisposable 10 | { 11 | public NativeArray pageTables; 12 | public NativeParallelHashMap activePageMap; 13 | 14 | public FPageProducer(in int numTile, in int pageSize, in int maxMipLevel) 15 | { 16 | pageTables = new NativeArray(maxMipLevel, Allocator.Persistent); 17 | activePageMap = new NativeParallelHashMap(numTile * numTile, Allocator.Persistent); 18 | 19 | for (int i = 0; i < maxMipLevel; ++i) 20 | { 21 | pageTables[i] = new FPageTable(i, pageSize); 22 | } 23 | } 24 | 25 | public void ProcessFeedback(ref NativeArray readbackDatas, in int maxMip, in int tileNum, in int pageSize, FLruCache* lruCache, ref NativeList loadRequests) 26 | { 27 | FAnalysisFeedbackJob analysisFeedbackJob; 28 | analysisFeedbackJob.maxMip = maxMip - 1; 29 | analysisFeedbackJob.tileNum = tileNum; 30 | analysisFeedbackJob.pageSize = pageSize; 31 | analysisFeedbackJob.lruCache = lruCache; 32 | analysisFeedbackJob.pageTables = pageTables; 33 | analysisFeedbackJob.loadRequests = loadRequests; 34 | analysisFeedbackJob.frameCount = Time.frameCount; 35 | analysisFeedbackJob.readbackDatas = readbackDatas; 36 | analysisFeedbackJob.Run(); 37 | } 38 | 39 | public void Reset() 40 | { 41 | for (int i = 0; i < pageTables.Length; ++i) 42 | { 43 | FPageTable pageTable = pageTables[i]; 44 | 45 | for (int j = 0; j < pageTable.cellCount; ++j) 46 | { 47 | for (int k = 0; k < pageTable.cellCount; k++) 48 | { 49 | ref FPage page = ref pageTable.pageBuffer[j * pageTable.cellCount + k]; 50 | InvalidatePage(page.payload.pageCoord); 51 | } 52 | } 53 | } 54 | activePageMap.Clear(); 55 | } 56 | 57 | public void InvalidatePage(in int2 id) 58 | { 59 | if (!activePageMap.TryGetValue(id, out int3 index)) 60 | return; 61 | 62 | FPageTable pageTable = pageTables[index.z]; 63 | ref FPage page = ref pageTable.GetPage(index.x, index.y); 64 | 65 | page.payload.ResetTileIndex(); 66 | activePageMap.Remove(id); 67 | } 68 | 69 | public void Dispose() 70 | { 71 | for (int i = 0; i < pageTables.Length; ++i) 72 | { 73 | FPageTable pageTable = pageTables[i]; 74 | pageTable.Dispose(); 75 | } 76 | pageTables.Dispose(); 77 | activePageMap.Dispose(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureProducer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5d51f9b13f0bad94dae5df6414cccd67 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureRenderer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Unity.Jobs; 3 | using UnityEngine; 4 | using Unity.Mathematics; 5 | using Unity.Collections; 6 | using UnityEngine.Rendering; 7 | using Object = UnityEngine.Object; 8 | using System.Runtime.InteropServices; 9 | 10 | namespace Landscape.RuntimeVirtualTexture 11 | { 12 | internal struct FPageTableInfo 13 | { 14 | public float4 pageData; 15 | public float4x4 matrix_M; 16 | } 17 | 18 | internal struct FPageDrawInfo : IComparable 19 | { 20 | public int mip; 21 | public FRect rect; 22 | public float2 drawPos; 23 | 24 | public int CompareTo(FPageDrawInfo target) 25 | { 26 | return -(mip.CompareTo(target.mip)); 27 | } 28 | } 29 | 30 | internal struct FDrawPageParameter 31 | { 32 | public FRect volumeRect; 33 | public Terrain[] terrainList; 34 | } 35 | 36 | internal static class FPageShaderID 37 | { 38 | public static int PageTableBuffer = Shader.PropertyToID("_PageTableBuffer"); 39 | public static int SplatTileOffset = Shader.PropertyToID("_SplatTileOffset"); 40 | public static int SplatTexture = Shader.PropertyToID("_SplatTexture"); 41 | public static int SurfaceTileOffset = Shader.PropertyToID("_SurfaceTileOffset"); 42 | public static int[] AlbedoTexture = new int[4] { Shader.PropertyToID("_AlbedoTexture1"), Shader.PropertyToID("_AlbedoTexture2"), Shader.PropertyToID("_AlbedoTexture3"), Shader.PropertyToID("_AlbedoTexture4") }; 43 | public static int[] NormalTexture = new int[4] { Shader.PropertyToID("_NormalTexture1"), Shader.PropertyToID("_NormalTexture2"), Shader.PropertyToID("_NormalTexture3"), Shader.PropertyToID("_NormalTexture4") }; 44 | public static int Size = Shader.PropertyToID("_Size"); 45 | public static int SrcTexture = Shader.PropertyToID("_SrcTexture"); 46 | public static int DscTexture = Shader.PropertyToID("_DscTexture"); 47 | } 48 | 49 | internal class FPageRenderer : IDisposable 50 | { 51 | private int m_Limit; 52 | private int m_PageSize; 53 | private Mesh m_DrawPageMesh; 54 | private Mesh m_TriangleMesh; 55 | private Material m_DrawPageMaterial; 56 | private Material m_DrawColorMaterial; 57 | private ComputeBuffer m_PageTableBuffer; 58 | private MaterialPropertyBlock m_Property; 59 | private NativeList m_DrawInfos; 60 | internal NativeList loadRequests; 61 | 62 | public FPageRenderer(in int pageSize, in int limit = 16) 63 | { 64 | this.m_Limit = limit; 65 | this.m_PageSize = pageSize; 66 | this.m_Property = new MaterialPropertyBlock(); 67 | this.m_DrawInfos = new NativeList(256, Allocator.Persistent); 68 | this.loadRequests = new NativeList(4096 * 2, Allocator.Persistent); 69 | this.m_PageTableBuffer = new ComputeBuffer(pageSize, Marshal.SizeOf(typeof(FPageTableInfo))); 70 | this.m_DrawPageMesh = FVirtualTextureUtility.BuildQuadMesh(); 71 | this.m_TriangleMesh = FVirtualTextureUtility.BuildTriangleMesh(); 72 | this.m_DrawPageMaterial = new Material(Shader.Find("VirtualTexture/DrawPageTable")); 73 | this.m_DrawColorMaterial = new Material(Shader.Find("VirtualTexture/DrawPageColor")); 74 | this.m_DrawPageMaterial.enableInstancing = true; 75 | } 76 | 77 | public void DrawPageTable(ScriptableRenderContext renderContext, CommandBuffer cmdBuffer, FPageProducer pageProducer) 78 | { 79 | m_Property.Clear(); 80 | m_DrawInfos.Clear(); 81 | 82 | //Build PageDrawInfo 83 | FPageDrawInfoBuildJob pageDrawInfoBuildJob; 84 | pageDrawInfoBuildJob.pageSize = m_PageSize; 85 | pageDrawInfoBuildJob.frameTime = Time.frameCount; 86 | pageDrawInfoBuildJob.drawInfos = m_DrawInfos; 87 | pageDrawInfoBuildJob.pageTables = pageProducer.pageTables; 88 | pageDrawInfoBuildJob.pageEnumerator = pageProducer.activePageMap.GetEnumerator(); 89 | pageDrawInfoBuildJob.Run(); 90 | 91 | //Sort PageDrawInfo 92 | if (m_DrawInfos.Length == 0) { return; } 93 | FPageDrawInfoSortJob pageDrawInfoSortJob; 94 | pageDrawInfoSortJob.drawInfos = m_DrawInfos; 95 | pageDrawInfoSortJob.Run(); 96 | 97 | //Get NativeData 98 | NativeArray pageTableInfos = new NativeArray(m_DrawInfos.Length, Allocator.TempJob); 99 | 100 | //Build PageTableInfo 101 | FPageTableInfoBuildJob pageTableInfoBuildJob; 102 | pageTableInfoBuildJob.pageSize = m_PageSize; 103 | pageTableInfoBuildJob.drawInfos = m_DrawInfos; 104 | pageTableInfoBuildJob.pageTableInfos = pageTableInfos; 105 | pageTableInfoBuildJob.Run(m_DrawInfos.Length); 106 | 107 | //Draw PageTable 108 | m_Property.Clear(); 109 | m_Property.SetBuffer(FPageShaderID.PageTableBuffer, m_PageTableBuffer); 110 | m_PageTableBuffer.SetData(pageTableInfos, 0, 0, pageTableInfos.Length); 111 | cmdBuffer.DrawMeshInstancedProcedural(m_DrawPageMesh, 0, m_DrawPageMaterial, 1, pageTableInfos.Length, m_Property); 112 | 113 | //Release NativeData 114 | pageTableInfos.Dispose(); 115 | } 116 | 117 | public void DrawPageColor(ScriptableRenderContext renderContext, CommandBuffer cmdBuffer, FPageProducer pageProducer, VirtualTextureAsset virtualTexture, ref FLruCache lruCache, in FDrawPageParameter drawPageParameter) 118 | { 119 | if (loadRequests.Length <= 0) { return; } 120 | FPageRequestInfoSortJob pageRequestInfoSortJob; 121 | pageRequestInfoSortJob.loadRequests = loadRequests; 122 | pageRequestInfoSortJob.Run(); 123 | 124 | int count = m_Limit; 125 | while (count > 0 && loadRequests.Length > 0) 126 | { 127 | count--; 128 | FPageLoadInfo loadRequest = loadRequests[loadRequests.Length - 1]; 129 | loadRequests.RemoveAt(loadRequests.Length - 1); 130 | 131 | int3 pageUV = new int3(loadRequest.x, loadRequest.y, loadRequest.mipLevel); 132 | FPageTable pageTable = pageProducer.pageTables[pageUV.z]; 133 | ref FPage page = ref pageTable.GetPage(pageUV.x, pageUV.y); 134 | 135 | if (page.isNull == true) { continue; } 136 | page.payload.notLoading = true; 137 | 138 | int2 pageCoord = new int2(lruCache.First % virtualTexture.tileNum, lruCache.First / virtualTexture.tileNum); 139 | if (lruCache.SetActive(pageCoord.y * virtualTexture.tileNum + pageCoord.x)) 140 | { 141 | pageProducer.InvalidatePage(pageCoord); 142 | 143 | FRectInt pageRect = new FRectInt(pageCoord.x * virtualTexture.TileSizePadding, pageCoord.y * virtualTexture.TileSizePadding, virtualTexture.TileSizePadding, virtualTexture.TileSizePadding); 144 | RenderPage(cmdBuffer, virtualTexture, pageRect, loadRequest, drawPageParameter); 145 | } 146 | 147 | page.payload.pageCoord = pageCoord; 148 | pageProducer.activePageMap.Add(pageCoord, pageUV); 149 | } 150 | } 151 | 152 | private void RenderPage(CommandBuffer cmdBuffer, VirtualTextureAsset virtualTexture, in FRectInt pageRect, in FPageLoadInfo loadRequest, in FDrawPageParameter drawPageParameter) 153 | { 154 | int x = loadRequest.x; 155 | int y = loadRequest.y; 156 | int perSize = (int)Mathf.Pow(2, loadRequest.mipLevel); 157 | x = x - x % perSize; 158 | y = y - y % perSize; 159 | 160 | var padding = (int)virtualTexture.tileBorder * perSize * (drawPageParameter.volumeRect.width / virtualTexture.pageSize) / virtualTexture.tileSize; 161 | var volumeRect = new Rect(drawPageParameter.volumeRect.xMin + (float)x / virtualTexture.pageSize * drawPageParameter.volumeRect.width - padding, drawPageParameter.volumeRect.yMin + (float)y / virtualTexture.pageSize * drawPageParameter.volumeRect.height - padding, drawPageParameter.volumeRect.width / virtualTexture.pageSize * perSize + 2f * padding, drawPageParameter.volumeRect.width / virtualTexture.pageSize * perSize + 2f * padding); 162 | 163 | foreach (var terrain in drawPageParameter.terrainList) 164 | { 165 | var terrainRect = Rect.zero; 166 | terrainRect.xMin = terrain.transform.position.x; 167 | terrainRect.yMin = terrain.transform.position.z; 168 | terrainRect.width = terrain.terrainData.size.x; 169 | terrainRect.height = terrain.terrainData.size.z; 170 | 171 | if (!volumeRect.Overlaps(terrainRect)) { continue; } 172 | 173 | var maxRect = volumeRect; 174 | maxRect.xMin = Mathf.Max(volumeRect.xMin, terrainRect.xMin); 175 | maxRect.yMin = Mathf.Max(volumeRect.yMin, terrainRect.yMin); 176 | maxRect.xMax = Mathf.Min(volumeRect.xMax, terrainRect.xMax); 177 | maxRect.yMax = Mathf.Min(volumeRect.yMax, terrainRect.yMax); 178 | 179 | var scaleFactor = pageRect.width / volumeRect.width; 180 | FRect offsetRect = new FRect(pageRect.x + (maxRect.xMin - volumeRect.xMin) * scaleFactor, pageRect.y + (maxRect.yMin - volumeRect.yMin) * scaleFactor, maxRect.width * scaleFactor, maxRect.height * scaleFactor); 181 | float l = offsetRect.x * 2.0f / virtualTexture.TextureSize - 1; 182 | float r = (offsetRect.x + offsetRect.width) * 2.0f / virtualTexture.TextureSize - 1; 183 | float b = offsetRect.y * 2.0f / virtualTexture.TextureSize - 1; 184 | float t = (offsetRect.y + offsetRect.height) * 2.0f / virtualTexture.TextureSize - 1; 185 | Matrix4x4 Matrix_MVP = new Matrix4x4(); 186 | Matrix_MVP.m00 = r - l; 187 | Matrix_MVP.m03 = l; 188 | Matrix_MVP.m11 = t - b; 189 | Matrix_MVP.m13 = b; 190 | Matrix_MVP.m23 = -1; 191 | Matrix_MVP.m33 = 1; 192 | 193 | float4 scaleOffset = new float4(maxRect.width / terrainRect.width, maxRect.height / terrainRect.height, (maxRect.xMin - terrainRect.xMin) / terrainRect.width, (maxRect.yMin - terrainRect.yMin) / terrainRect.height); 194 | m_Property.Clear(); 195 | m_Property.SetVector(FPageShaderID.SplatTileOffset, scaleOffset); 196 | m_Property.SetMatrix(Shader.PropertyToID("_Matrix_MVP"), GL.GetGPUProjectionMatrix(Matrix_MVP, true)); 197 | 198 | int layerIndex = 0; 199 | var terrainLayers = terrain.terrainData.terrainLayers; 200 | 201 | for (int i = 0; i < terrain.terrainData.alphamapTextureCount; ++i) 202 | { 203 | m_Property.SetTexture(FPageShaderID.SplatTexture, terrain.terrainData.GetAlphamapTexture(i)); 204 | 205 | int index = 1; 206 | for (; layerIndex < terrain.terrainData.alphamapLayers && index <= 4; ++layerIndex) 207 | { 208 | var terrainLayer = terrainLayers[layerIndex]; 209 | float2 tileScale = new float2(terrain.terrainData.size.x / terrainLayer.tileSize.x, terrain.terrainData.size.z / terrainLayer.tileSize.y); 210 | float4 tileOffset = new float4(tileScale.x * scaleOffset.x, tileScale.y * scaleOffset.y, scaleOffset.z * tileScale.x, scaleOffset.w * tileScale.y); 211 | m_Property.SetVector(FPageShaderID.SurfaceTileOffset, tileOffset); 212 | m_Property.SetTexture(FPageShaderID.AlbedoTexture[index - 1], terrainLayer.diffuseTexture); 213 | m_Property.SetTexture(FPageShaderID.NormalTexture[index - 1], terrainLayer.normalMapTexture); 214 | ++index; 215 | } 216 | 217 | cmdBuffer.DrawMesh(m_DrawPageMesh, Matrix4x4.identity, m_DrawColorMaterial, 0, layerIndex <= 4 ? 0 : 1, m_Property); 218 | } 219 | } 220 | } 221 | 222 | public void Dispose() 223 | { 224 | m_DrawInfos.Dispose(); 225 | loadRequests.Dispose(); 226 | m_PageTableBuffer.Dispose(); 227 | Object.DestroyImmediate(m_DrawPageMesh); 228 | Object.DestroyImmediate(m_TriangleMesh); 229 | Object.DestroyImmediate(m_DrawPageMaterial); 230 | Object.DestroyImmediate(m_DrawColorMaterial); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureRenderer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 13095ccdf527ada4f96b0597d4c606c6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine; 3 | using Unity.Collections; 4 | using Unity.Mathematics; 5 | using System.Globalization; 6 | using System.Collections.Generic; 7 | 8 | namespace Landscape.RuntimeVirtualTexture 9 | { 10 | public struct FRect : IEquatable, IFormattable 11 | { 12 | private float m_XMin; 13 | private float m_YMin; 14 | private float m_Width; 15 | private float m_Height; 16 | 17 | public FRect(float x, float y, float width, float height) 18 | { 19 | this.m_XMin = x; 20 | this.m_YMin = y; 21 | this.m_Width = width; 22 | this.m_Height = height; 23 | } 24 | 25 | public FRect(float2 position, float2 size) 26 | { 27 | this.m_XMin = position.x; 28 | this.m_YMin = position.y; 29 | this.m_Width = size.x; 30 | this.m_Height = size.y; 31 | } 32 | 33 | public FRect(FRect source) 34 | { 35 | this.m_XMin = source.m_XMin; 36 | this.m_YMin = source.m_YMin; 37 | this.m_Width = source.m_Width; 38 | this.m_Height = source.m_Height; 39 | } 40 | 41 | public static FRect zero => new FRect(0.0f, 0.0f, 0.0f, 0.0f); 42 | public static FRect MinMaxRect(float xmin, float ymin, float xmax, float ymax) => new FRect(xmin, ymin, xmax - xmin, ymax - ymin); 43 | 44 | public void Set(float x, float y, float width, float height) 45 | { 46 | this.m_XMin = x; 47 | this.m_YMin = y; 48 | this.m_Width = width; 49 | this.m_Height = height; 50 | } 51 | 52 | public float x 53 | { 54 | get => this.m_XMin; 55 | set => this.m_XMin = value; 56 | } 57 | 58 | public float y 59 | { 60 | get => this.m_YMin; 61 | set => this.m_YMin = value; 62 | } 63 | 64 | public float2 position 65 | { 66 | get => new float2(this.m_XMin, this.m_YMin); 67 | set 68 | { 69 | this.m_XMin = value.x; 70 | this.m_YMin = value.y; 71 | } 72 | } 73 | 74 | public float2 center 75 | { 76 | get => new float2(this.x + this.m_Width / 2f, this.y + this.m_Height / 2f); 77 | set 78 | { 79 | this.m_XMin = value.x - this.m_Width / 2f; 80 | this.m_YMin = value.y - this.m_Height / 2f; 81 | } 82 | } 83 | 84 | public float2 min 85 | { 86 | get => new float2(this.xMin, this.yMin); 87 | set 88 | { 89 | this.xMin = value.x; 90 | this.yMin = value.y; 91 | } 92 | } 93 | 94 | public float2 max 95 | { 96 | get => new float2(this.xMax, this.yMax); 97 | set 98 | { 99 | this.xMax = value.x; 100 | this.yMax = value.y; 101 | } 102 | } 103 | 104 | public float width 105 | { 106 | get => this.m_Width; 107 | set => this.m_Width = value; 108 | } 109 | 110 | public float height 111 | { 112 | get => this.m_Height; 113 | set => this.m_Height = value; 114 | } 115 | 116 | public float2 size 117 | { 118 | get => new float2(this.m_Width, this.m_Height); 119 | set 120 | { 121 | this.m_Width = value.x; 122 | this.m_Height = value.y; 123 | } 124 | } 125 | 126 | public float xMin 127 | { 128 | get => this.m_XMin; 129 | set 130 | { 131 | float xMax = this.xMax; 132 | this.m_XMin = value; 133 | this.m_Width = xMax - this.m_XMin; 134 | } 135 | } 136 | 137 | public float yMin 138 | { 139 | get => this.m_YMin; 140 | set 141 | { 142 | float yMax = this.yMax; 143 | this.m_YMin = value; 144 | this.m_Height = yMax - this.m_YMin; 145 | } 146 | } 147 | 148 | public float xMax 149 | { 150 | get => this.m_Width + this.m_XMin; 151 | set => this.m_Width = value - this.m_XMin; 152 | } 153 | public float yMax 154 | { 155 | get => this.m_Height + this.m_YMin; 156 | set => this.m_Height = value - this.m_YMin; 157 | } 158 | 159 | public bool Contains(float2 point) => (double)point.x >= (double)this.xMin && (double)point.x < (double)this.xMax && (double)point.y >= (double)this.yMin && (double)point.y < (double)this.yMax; 160 | 161 | public bool Contains(float3 point) => (double)point.x >= (double)this.xMin && (double)point.x < (double)this.xMax && (double)point.y >= (double)this.yMin && (double)point.y < (double)this.yMax; 162 | 163 | public bool Contains(float3 point, bool allowInverse) => !allowInverse ? this.Contains(point) : ((double)this.width < 0.0 && (double)point.x <= (double)this.xMin && (double)point.x > (double)this.xMax || (double)this.width >= 0.0 && (double)point.x >= (double)this.xMin && (double)point.x < (double)this.xMax) & ((double)this.height < 0.0 && (double)point.y <= (double)this.yMin && (double)point.y > (double)this.yMax || (double)this.height >= 0.0 && (double)point.y >= (double)this.yMin && (double)point.y < (double)this.yMax); 164 | 165 | private static FRect OrderMinMax(FRect rect) 166 | { 167 | if ((double)rect.xMin > (double)rect.xMax) 168 | { 169 | float xMin = rect.xMin; 170 | rect.xMin = rect.xMax; 171 | rect.xMax = xMin; 172 | } 173 | if ((double)rect.yMin > (double)rect.yMax) 174 | { 175 | float yMin = rect.yMin; 176 | rect.yMin = rect.yMax; 177 | rect.yMax = yMin; 178 | } 179 | return rect; 180 | } 181 | 182 | public bool Overlaps(FRect other) => (double)other.xMax > (double)this.xMin && (double)other.xMin < (double)this.xMax && (double)other.yMax > (double)this.yMin && (double)other.yMin < (double)this.yMax; 183 | 184 | public bool Overlaps(FRect other, bool allowInverse) 185 | { 186 | FRect rect = this; 187 | if (allowInverse) 188 | { 189 | rect = FRect.OrderMinMax(rect); 190 | other = FRect.OrderMinMax(other); 191 | } 192 | return rect.Overlaps(other); 193 | } 194 | 195 | public static float2 NormalizedToPoint(FRect rectangle, float2 normalizedRectCoordinates) 196 | { 197 | return new float2(math.lerp(rectangle.x, rectangle.xMax, normalizedRectCoordinates.x), math.lerp(rectangle.y, rectangle.yMax, normalizedRectCoordinates.y)); 198 | } 199 | 200 | public static float2 PointToNormalized(FRect rectangle, float2 point) => new float2(Mathf.InverseLerp(rectangle.x, rectangle.xMax, point.x), Mathf.InverseLerp(rectangle.y, rectangle.yMax, point.y)); 201 | 202 | public static bool operator !=(FRect lhs, FRect rhs) => !(lhs == rhs); 203 | 204 | public static bool operator ==(FRect lhs, FRect rhs) => (double)lhs.x == (double)rhs.x && (double)lhs.y == (double)rhs.y && (double)lhs.width == (double)rhs.width && (double)lhs.height == (double)rhs.height; 205 | 206 | public override int GetHashCode() 207 | { 208 | float num1 = this.x; 209 | int hashCode = num1.GetHashCode(); 210 | num1 = this.width; 211 | int num2 = num1.GetHashCode() << 2; 212 | int num3 = hashCode ^ num2; 213 | num1 = this.y; 214 | int num4 = num1.GetHashCode() >> 2; 215 | int num5 = num3 ^ num4; 216 | num1 = this.height; 217 | int num6 = num1.GetHashCode() >> 1; 218 | return num5 ^ num6; 219 | } 220 | 221 | public override bool Equals(object other) => other is FRect other1 && this.Equals(other1); 222 | 223 | public bool Equals(FRect other) 224 | { 225 | int num1; 226 | if (this.x.Equals(other.x)) 227 | { 228 | float num2 = this.y; 229 | if (num2.Equals(other.y)) 230 | { 231 | num2 = this.width; 232 | if (num2.Equals(other.width)) 233 | { 234 | num2 = this.height; 235 | num1 = num2.Equals(other.height) ? 1 : 0; 236 | goto label_5; 237 | } 238 | } 239 | } 240 | num1 = 0; 241 | 242 | label_5: 243 | return num1 != 0; 244 | } 245 | 246 | public override string ToString() => this.ToString((string)null, (IFormatProvider)CultureInfo.InvariantCulture.NumberFormat); 247 | 248 | public string ToString(string format) => this.ToString(format, (IFormatProvider)CultureInfo.InvariantCulture.NumberFormat); 249 | 250 | public string ToString(string format, IFormatProvider formatProvider) 251 | { 252 | if (string.IsNullOrEmpty(format)) 253 | format = "F2"; 254 | object[] objArray = new object[4]; 255 | float num = this.x; 256 | objArray[0] = (object)num.ToString(format, formatProvider); 257 | num = this.y; 258 | objArray[1] = (object)num.ToString(format, formatProvider); 259 | num = this.width; 260 | objArray[2] = (object)num.ToString(format, formatProvider); 261 | num = this.height; 262 | objArray[3] = (object)num.ToString(format, formatProvider); 263 | return string.Format("(x:{0}, y:{1}, width:{2}, height:{3})", objArray); 264 | } 265 | } 266 | 267 | public struct FRectInt : IEquatable, IFormattable 268 | { 269 | private int m_XMin; 270 | private int m_YMin; 271 | private int m_Width; 272 | private int m_Height; 273 | 274 | public int x 275 | { 276 | get => this.m_XMin; 277 | set => this.m_XMin = value; 278 | } 279 | 280 | public int y 281 | { 282 | get => this.m_YMin; 283 | set => this.m_YMin = value; 284 | } 285 | 286 | public float2 center => new float2((float)this.x + (float)this.m_Width / 2f, (float)this.y + (float)this.m_Height / 2f); 287 | 288 | public int2 min 289 | { 290 | get => new int2(this.xMin, this.yMin); 291 | set 292 | { 293 | this.xMin = value.x; 294 | this.yMin = value.y; 295 | } 296 | } 297 | 298 | public int2 max 299 | { 300 | get => new int2(this.xMax, this.yMax); 301 | set 302 | { 303 | this.xMax = value.x; 304 | this.yMax = value.y; 305 | } 306 | } 307 | 308 | public int width 309 | { 310 | get => this.m_Width; 311 | set => this.m_Width = value; 312 | } 313 | 314 | public int height 315 | { 316 | get => this.m_Height; 317 | set => this.m_Height = value; 318 | } 319 | 320 | public int xMin 321 | { 322 | get => math.min(this.m_XMin, this.m_XMin + this.m_Width); 323 | set 324 | { 325 | int xMax = this.xMax; 326 | this.m_XMin = value; 327 | this.m_Width = xMax - this.m_XMin; 328 | } 329 | } 330 | 331 | public int yMin 332 | { 333 | get => math.min(this.m_YMin, this.m_YMin + this.m_Height); 334 | set 335 | { 336 | int yMax = this.yMax; 337 | this.m_YMin = value; 338 | this.m_Height = yMax - this.m_YMin; 339 | } 340 | } 341 | 342 | public int xMax 343 | { 344 | get => math.max(this.m_XMin, this.m_XMin + this.m_Width); 345 | set => this.m_Width = value - this.m_XMin; 346 | } 347 | 348 | public int yMax 349 | { 350 | get => math.max(this.m_YMin, this.m_YMin + this.m_Height); 351 | set => this.m_Height = value - this.m_YMin; 352 | } 353 | 354 | public int2 position 355 | { 356 | get => new int2(this.m_XMin, this.m_YMin); 357 | set 358 | { 359 | this.m_XMin = value.x; 360 | this.m_YMin = value.y; 361 | } 362 | } 363 | 364 | public int2 size 365 | { 366 | get => new int2(this.m_Width, this.m_Height); 367 | set 368 | { 369 | this.m_Width = value.x; 370 | this.m_Height = value.y; 371 | } 372 | } 373 | 374 | public void SetMinMax(int2 minPosition, int2 maxPosition) 375 | { 376 | this.min = minPosition; 377 | this.max = maxPosition; 378 | } 379 | 380 | public FRectInt(int xMin, int yMin, int width, int height) 381 | { 382 | this.m_XMin = xMin; 383 | this.m_YMin = yMin; 384 | this.m_Width = width; 385 | this.m_Height = height; 386 | } 387 | 388 | public FRectInt(int2 position, int2 size) 389 | { 390 | this.m_XMin = position.x; 391 | this.m_YMin = position.y; 392 | this.m_Width = size.x; 393 | this.m_Height = size.y; 394 | } 395 | 396 | public void ClampToBounds(FRectInt bounds) 397 | { 398 | this.position = new int2(Math.Max(Math.Min(bounds.xMax, this.position.x), bounds.xMin), Math.Max(Math.Min(bounds.yMax, this.position.y), bounds.yMin)); 399 | this.size = new int2(Math.Min(bounds.xMax - this.position.x, this.size.x), Math.Min(bounds.yMax - this.position.y, this.size.y)); 400 | } 401 | 402 | public bool Contains(int2 position) => position.x >= this.xMin && position.y >= this.yMin && position.x < this.xMax && position.y < this.yMax; 403 | 404 | public bool Overlaps(FRectInt other) => other.xMin < this.xMax && other.xMax > this.xMin && other.yMin < this.yMax && other.yMax > this.yMin; 405 | 406 | public override string ToString() => this.ToString((string)null, (IFormatProvider)CultureInfo.InvariantCulture.NumberFormat); 407 | 408 | public string ToString(string format) => this.ToString(format, (IFormatProvider)CultureInfo.InvariantCulture.NumberFormat); 409 | 410 | public string ToString(string format, IFormatProvider formatProvider) => string.Format("(x:{0}, y:{1}, width:{2}, height:{3})", (object)this.x.ToString(format, formatProvider), (object)this.y.ToString(format, formatProvider), (object)this.width.ToString(format, formatProvider), (object)this.height.ToString(format, formatProvider)); 411 | 412 | public bool Equals(FRectInt other) => this.m_XMin == other.m_XMin && this.m_YMin == other.m_YMin && this.m_Width == other.m_Width && this.m_Height == other.m_Height; 413 | } 414 | 415 | internal static class FVirtualTextureUtility 416 | { 417 | public static Mesh BuildQuadMesh() 418 | { 419 | List VertexArray = new List(); 420 | List IndexArray = new List(); 421 | List UB0Array = new List(); 422 | 423 | VertexArray.Add(new Vector3(0, 1, 0.1f)); 424 | VertexArray.Add(new Vector3(0, 0, 0.1f)); 425 | VertexArray.Add(new Vector3(1, 0, 0.1f)); 426 | VertexArray.Add(new Vector3(1, 1, 0.1f)); 427 | 428 | UB0Array.Add(new Vector2(0, 1)); 429 | UB0Array.Add(new Vector2(0, 0)); 430 | UB0Array.Add(new Vector2(1, 0)); 431 | UB0Array.Add(new Vector2(1, 1)); 432 | 433 | IndexArray.Add(0); 434 | IndexArray.Add(1); 435 | IndexArray.Add(2); 436 | IndexArray.Add(2); 437 | IndexArray.Add(3); 438 | IndexArray.Add(0); 439 | 440 | Mesh mesh = new Mesh(); 441 | mesh.SetVertices(VertexArray); 442 | mesh.SetUVs(0, UB0Array); 443 | mesh.SetTriangles(IndexArray, 0); 444 | return mesh; 445 | } 446 | 447 | public static Mesh BuildTriangleMesh() 448 | { 449 | Mesh mesh = new Mesh { name = "FullScreen Mesh" }; 450 | 451 | mesh.vertices = new Vector3[] 452 | { 453 | new Vector3(-1f, -1f, 0f), 454 | new Vector3(-1f, 3f, 0f), 455 | new Vector3( 3f, -1f, 0f) 456 | }; 457 | 458 | mesh.SetIndices(new int[] { 0, 1, 2 }, MeshTopology.Triangles, 0, false); 459 | mesh.UploadMeshData(false); 460 | return mesh; 461 | } 462 | } 463 | } 464 | -------------------------------------------------------------------------------- /Runtime/Source/VirtualTextureUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cc930d03480b1f14995d7c290b3b2bc7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Shaders.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c2242a8f8dd2e548ae540b10680e974 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/Common.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c63038e491ea194ebe43d9dc2d318c3 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/Common/StochasticSampling.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef StochasticSampling 2 | #define StochasticSampling 3 | 4 | #ifdef UNITY_COLORSPACE_GAMMA 5 | #define stochastic_ColorSpaceLuminance half4(0.22, 0.707, 0.071, 0.0) // Legacy: alpha is set to 0.0 to specify gamma mode 6 | #else 7 | #define stochastic_ColorSpaceLuminance half4(0.0396819152, 0.458021790, 0.00609653955, 1.0) // Legacy: alpha is set to 1.0 to specify linear mode 8 | #endif 9 | 10 | inline half StochasticLuminance(half3 rgb) 11 | { 12 | return dot(rgb, stochastic_ColorSpaceLuminance.rgb); 13 | } 14 | 15 | 16 | // Compute local triangle barycentric coordinates and vertex IDs 17 | void StochasticTriangleGrid(float2 uv, 18 | out float w1, out float w2, out float w3, 19 | out int2 vertex1, out int2 vertex2, out int2 vertex3, float scale) 20 | { 21 | // Scaling of the input 22 | uv *= 3.464 * scale; // 2 * sqrt(3) 23 | 24 | // Skew input space into simplex triangle grid 25 | const float2x2 gridToSkewedGrid = float2x2(1.0, 0.0, -0.57735027, 1.15470054); 26 | float2 skewedCoord = mul(gridToSkewedGrid, uv); 27 | 28 | // Compute local triangle vertex IDs and local barycentric coordinates 29 | int2 baseId = int2(floor(skewedCoord)); 30 | float3 temp = float3(frac(skewedCoord), 0); 31 | temp.z = 1.0 - temp.x - temp.y; 32 | if (temp.z > 0.0) 33 | { 34 | w1 = temp.z; 35 | w2 = temp.y; 36 | w3 = temp.x; 37 | vertex1 = baseId; 38 | vertex2 = baseId + int2(0, 1); 39 | vertex3 = baseId + int2(1, 0); 40 | } 41 | else 42 | { 43 | w1 = -temp.z; 44 | w2 = 1.0 - temp.y; 45 | w3 = 1.0 - temp.x; 46 | vertex1 = baseId + int2(1, 1); 47 | vertex2 = baseId + int2(1, 0); 48 | vertex3 = baseId + int2(0, 1); 49 | } 50 | } 51 | 52 | float2 StochasticSimpleHash2(float2 p) 53 | { 54 | return frac(sin(mul(float2x2(127.1, 311.7, 269.5, 183.3), p)) * 43758.5453); 55 | } 56 | 57 | 58 | half3 StochasticBaryWeightBlend(half3 iWeights, half tex0, half tex1, half tex2, half contrast) 59 | { 60 | // compute weight with height map 61 | const half epsilon = 1.0f / 1024.0f; 62 | half3 weights = half3(iWeights.x * (tex0 + epsilon), 63 | iWeights.y * (tex1 + epsilon), 64 | iWeights.z * (tex2 + epsilon)); 65 | 66 | // Contrast weights 67 | half maxWeight = max(weights.x, max(weights.y, weights.z)); 68 | half transition = contrast * maxWeight; 69 | half threshold = maxWeight - transition; 70 | half scale = 1.0f / transition; 71 | weights = saturate((weights - threshold) * scale); 72 | // Normalize weights. 73 | half weightScale = 1.0f / (weights.x + weights.y + weights.z); 74 | weights *= weightScale; 75 | return weights; 76 | } 77 | 78 | void StochasticPrepareStochasticUVs(float2 uv, out float2 uv1, out float2 uv2, out float2 uv3, out half3 weights, float scale) 79 | { 80 | // Get triangle info 81 | float w1, w2, w3; 82 | int2 vertex1, vertex2, vertex3; 83 | StochasticTriangleGrid(uv, w1, w2, w3, vertex1, vertex2, vertex3, scale); 84 | 85 | // Assign random offset to each triangle vertex 86 | uv1 = uv; 87 | uv2 = uv; 88 | uv3 = uv; 89 | 90 | uv1.xy += StochasticSimpleHash2(vertex1); 91 | uv2.xy += StochasticSimpleHash2(vertex2); 92 | uv3.xy += StochasticSimpleHash2(vertex3); 93 | weights = half3(w1, w2, w3); 94 | } 95 | 96 | half4 StochasticSample2DWeightsR(Texture2D Tex, SamplerState TexSampler, float2 uv, out half3 cw, out float2 uv1, out float2 uv2, out float2 uv3, out float2 dx, out float2 dy, float scale, float contrast) 97 | { 98 | half3 w; 99 | StochasticPrepareStochasticUVs(uv, uv1, uv2, uv3, w, scale); 100 | 101 | dx = ddx(uv); 102 | dy = ddy(uv); 103 | 104 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 105 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 106 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 107 | 108 | 109 | cw.xyz = StochasticBaryWeightBlend(w, G1.r, G2.r, G3.r, contrast); 110 | 111 | 112 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 113 | 114 | } 115 | 116 | half4 StochasticSample2DWeightsG(Texture2D Tex, SamplerState TexSampler, float2 uv, out half3 cw, out float2 uv1, out float2 uv2, out float2 uv3, out float2 dx, out float2 dy, float scale, float contrast) 117 | { 118 | half3 w; 119 | StochasticPrepareStochasticUVs(uv, uv1, uv2, uv3, w, scale); 120 | 121 | dx = ddx(uv); 122 | dy = ddy(uv); 123 | 124 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 125 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 126 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 127 | 128 | 129 | cw.xyz = StochasticBaryWeightBlend(w, G1.g, G2.g, G3.g, contrast); 130 | 131 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 132 | 133 | } 134 | 135 | half4 StochasticSample2DWeightsB(Texture2D Tex, SamplerState TexSampler, float2 uv, out half3 cw, out float2 uv1, out float2 uv2, out float2 uv3, out float2 dx, out float2 dy, float scale, float contrast) 136 | { 137 | half3 w; 138 | StochasticPrepareStochasticUVs(uv, uv1, uv2, uv3, w, scale); 139 | 140 | dx = ddx(uv); 141 | dy = ddy(uv); 142 | 143 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 144 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 145 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 146 | 147 | cw.xyz = StochasticBaryWeightBlend(w, G1.b, G2.b, G3.b, contrast); 148 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 149 | } 150 | 151 | half4 StochasticSample2DWeightsA(Texture2D Tex, SamplerState TexSampler, float2 uv, out half3 cw, out float2 uv1, out float2 uv2, out float2 uv3, out float2 dx, out float2 dy, float scale, float contrast) 152 | { 153 | half3 w; 154 | StochasticPrepareStochasticUVs(uv, uv1, uv2, uv3, w, scale); 155 | 156 | dx = ddx(uv); 157 | dy = ddy(uv); 158 | 159 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 160 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 161 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 162 | 163 | cw.xyz = StochasticBaryWeightBlend(w, G1.a, G2.a, G3.a, contrast); 164 | 165 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 166 | } 167 | 168 | half4 StochasticSample2DWeightsLum(Texture2D Tex, SamplerState TexSampler, float2 uv, out half3 cw, out float2 uv1, out float2 uv2, out float2 uv3, out float2 dx, out float2 dy, float scale, float contrast) 169 | { 170 | half3 w; 171 | StochasticPrepareStochasticUVs(uv, uv1, uv2, uv3, w, scale); 172 | 173 | dx = ddx(uv); 174 | dy = ddy(uv); 175 | 176 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 177 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 178 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 179 | 180 | cw.xyz = StochasticBaryWeightBlend(w, StochasticLuminance(G1.rgb), StochasticLuminance(G2.rgb), StochasticLuminance(G3.rgb), contrast); 181 | 182 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 183 | } 184 | 185 | half4 StochasticSample2D(Texture2D Tex, SamplerState TexSampler, half3 cw, float2 uv1, float2 uv2, float2 uv3, float2 dx, float2 dy) 186 | { 187 | float4 G1 = Tex.SampleGrad(TexSampler, uv1, dx, dy); 188 | float4 G2 = Tex.SampleGrad(TexSampler, uv2, dx, dy); 189 | float4 G3 = Tex.SampleGrad(TexSampler, uv3, dx, dy); 190 | return G1 * cw.x + G2 * cw.y + G3 * cw.z; 191 | } 192 | 193 | float2 hash2D2D (float2 s) 194 | { 195 | return frac(sin(fmod(float2(dot(s, float2(127.1,311.7)), dot(s, float2(269.5,183.3))), 3.14159))*43758.5453); 196 | } 197 | 198 | float4 StochasticSample2D(Texture2D Tex, SamplerState TexSampler, float2 UV) 199 | { 200 | //triangle vertices and blend weights 201 | //BW_vx[0...2].xyz = triangle verts 202 | //BW_vx[3].xy = blend weights (z is unused) 203 | float4x3 BW_vx; 204 | 205 | //uv transformed into triangular grid space with UV scaled by approximation of 2*sqrt(3) 206 | float2 skewUV = mul(float2x2 (1.0 , 0.0 , -0.57735027 , 1.15470054), UV * 3.464); 207 | 208 | //vertex IDs and barycentric coords 209 | float2 vxID = float2 (floor(skewUV)); 210 | float3 barry = float3 (frac(skewUV), 0); 211 | barry.z = 1.0-barry.x-barry.y; 212 | 213 | BW_vx = ((barry.z>0) ? 214 | float4x3(float3(vxID, 0), float3(vxID + float2(0, 1), 0), float3(vxID + float2(1, 0), 0), barry.zyx) : 215 | float4x3(float3(vxID + float2 (1, 1), 0), float3(vxID + float2 (1, 0), 0), float3(vxID + float2 (0, 1), 0), float3(-barry.z, 1.0-barry.y, 1.0-barry.x))); 216 | 217 | //calculate derivatives to avoid triangular grid artifacts 218 | float2 dx = ddx(UV); 219 | float2 dy = ddy(UV); 220 | 221 | //blend samples with calculated weights 222 | return mul(Tex.Sample(TexSampler, UV + hash2D2D(BW_vx[0].xy) + dx + dy), BW_vx[3].x) + 223 | mul(Tex.Sample(TexSampler, UV + hash2D2D(BW_vx[1].xy) + dx + dy), BW_vx[3].y) + 224 | mul(Tex.Sample(TexSampler, UV + hash2D2D(BW_vx[2].xy) + dx + dy), BW_vx[3].z); 225 | } 226 | 227 | #endif 228 | 229 | 230 | 231 | -------------------------------------------------------------------------------- /Shaders/Common/StochasticSampling.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f8570e6b6d19a1646a2a8278f975d14c 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Compress.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86083cbddf30d6a40a074abb639747bb 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/Compress/BCCompress.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef _BC3Compress_ 2 | #define _BC3Compress_ 3 | 4 | half LinearToSrgbBranchingChannel(half lin) 5 | { 6 | if (lin < 0.00313067) 7 | return lin * 12.92; 8 | return pow(lin, (1.0 / 2.4)) * 1.055 - 0.055; 9 | } 10 | half3 LinearToSrgbBranching(half3 lin) 11 | { 12 | return half3( 13 | LinearToSrgbBranchingChannel(lin.r), 14 | LinearToSrgbBranchingChannel(lin.g), 15 | LinearToSrgbBranchingChannel(lin.b)); 16 | } 17 | 18 | half3 LinearToSrgb(half3 lin) 19 | { 20 | // Branching is faster than branchless on AMD on PC. 21 | return LinearToSrgbBranching(lin); 22 | } 23 | 24 | // Simple convert float3 color to 565 uint using 'round' arithmetic 25 | uint Float3ToUint565(in float3 Color) 26 | { 27 | float3 Scale = float3(31.f, 63.f, 31.f); 28 | float3 ColorScaled = round(saturate(Color) * Scale); 29 | uint ColorPacked = ((uint) ColorScaled.r << 11) | ((uint) ColorScaled.g << 5) | (uint) ColorScaled.b; 30 | 31 | return ColorPacked; 32 | } 33 | 34 | // Convert float3 color to 565 uint using 'ceil' arithmetic 35 | // Color parameter is inout and is modified to match the converted value 36 | uint Float3ToUint565_Ceil(inout float3 Color) 37 | { 38 | float3 Scale = float3(31.f, 63.f, 31.f); 39 | float3 ColorScaled = ceil(saturate(Color) * Scale); 40 | uint ColorPacked = ((uint) ColorScaled.r << 11) | ((uint) ColorScaled.g << 5) | (uint) ColorScaled.b; 41 | Color = ColorScaled / Scale; 42 | 43 | return ColorPacked; 44 | } 45 | 46 | // Convert float3 color to 565 uint using 'floor' arithmetic 47 | // Color parameter is inout and is modified to match the converted value 48 | uint Float3ToUint565_Floor(inout float3 Color) 49 | { 50 | float3 Scale = float3(31.f, 63.f, 31.f); 51 | float3 ColorScaled = floor(saturate(Color) * Scale); 52 | uint ColorPacked = ((uint) ColorScaled.r << 11) | ((uint) ColorScaled.g << 5) | (uint) ColorScaled.b; 53 | Color = ColorScaled / Scale; 54 | 55 | return ColorPacked; 56 | } 57 | 58 | // Get min and max values in a single channel block 59 | void GetMinMax(in float Block[16], out float OutMin, out float OutMax) 60 | { 61 | OutMin = Block[0]; 62 | OutMax = Block[0]; 63 | 64 | for (int i = 1; i < 16; ++i) 65 | { 66 | OutMin = min(OutMin, Block[i]); 67 | OutMax = max(OutMax, Block[i]); 68 | } 69 | } 70 | 71 | // Get min and max values in two single channel blocks 72 | void GetMinMax(in float Block0[16], in float Block1[16], out float OutMin0, out float OutMax0, out float OutMin1, out float OutMax1) 73 | { 74 | OutMin0 = Block0[0]; 75 | OutMax0 = Block0[0]; 76 | OutMin1 = Block1[0]; 77 | OutMax1 = Block1[0]; 78 | 79 | for (int i = 1; i < 16; ++i) 80 | { 81 | OutMin0 = min(OutMin0, Block0[i]); 82 | OutMax0 = max(OutMax0, Block0[i]); 83 | OutMin1 = min(OutMin1, Block1[i]); 84 | OutMax1 = max(OutMax1, Block1[i]); 85 | } 86 | } 87 | 88 | // Get min and max values in a single three channel block 89 | void GetMinMax(in float3 Block[16], out float3 OutMin, out float3 OutMax) 90 | { 91 | OutMin = Block[0]; 92 | OutMax = Block[0]; 93 | 94 | for (int i = 1; i < 16; ++i) 95 | { 96 | OutMin = min(OutMin, Block[i]); 97 | OutMax = max(OutMax, Block[i]); 98 | } 99 | } 100 | 101 | // Calculate the final packed indices for a color block 102 | uint GetPackedColorBlockIndices(in float3 Block[16], in float3 MinColor, in float3 MaxColor) 103 | { 104 | uint PackedIndices = 0; 105 | 106 | // Project onto max->min color vector and segment into range [0,3] 107 | float3 Range = MinColor - MaxColor; 108 | float Scale = 3.f / dot(Range, Range); 109 | float3 ScaledRange = Range * Scale; 110 | float Bias = (dot(MaxColor, MaxColor) - dot(MaxColor, MinColor)) * Scale; 111 | 112 | for (int i = 15; i >= 0; --i) 113 | { 114 | // Compute the distance index for this element 115 | uint Index = round(dot(Block[i], ScaledRange) + Bias); 116 | // Convert distance index into the BC index 117 | Index += (Index > 0) - (3 * (Index == 3)); 118 | // OR into the final PackedIndices 119 | PackedIndices = (PackedIndices << 2) | Index; 120 | } 121 | 122 | return PackedIndices; 123 | } 124 | 125 | // Calculate the final packed indices for an alpha block 126 | // The results are in their final location of the uint2 indices and will need ORing with the min and max alpha 127 | uint2 GetPackedAlphaBlockIndices(in float Block[16], in float MinAlpha, in float MaxAlpha) 128 | { 129 | uint2 PackedIndices = 0; 130 | 131 | // Segment alpha max->min into range [0,7] 132 | float Range = MinAlpha - MaxAlpha; 133 | float Scale = 7.f / Range; 134 | float Bias = -Scale * MaxAlpha; 135 | 136 | uint i = 0; 137 | // The first 5 elements of the block will go into the top 16 bits of the x component 138 | for (i = 0; i < 5; ++i) 139 | { 140 | // Compute the distance index for this element 141 | uint Index = round(Block[i] * Scale + Bias); 142 | // Convert distance index into the BC index 143 | Index += (Index > 0) - (7 * (Index == 7)); 144 | // OR into the final PackedIndices 145 | PackedIndices.x |= (Index << (i * 3 + 16)); 146 | } 147 | 148 | // The 6th element is split across the x and y components 149 | { 150 | i = 5; 151 | uint Index = round(Block[i] * Scale + Bias); 152 | Index += (Index > 0) - (7 * (Index == 7)); 153 | PackedIndices.x |= (Index << 31); 154 | PackedIndices.y |= (Index >> 1); 155 | } 156 | 157 | // The rest of the elements fill the y component 158 | for (i = 6; i < 16; ++i) 159 | { 160 | uint Index = round(Block[i] * Scale + Bias); 161 | Index += (Index > 0) - (7 * (Index == 7 ? 1 : 0)); 162 | PackedIndices.y |= (Index << (i * 3 - 16)); 163 | } 164 | 165 | return PackedIndices; 166 | } 167 | 168 | // Compress a BC1 block 169 | uint2 CompressBC1Block(in float3 Block[16]) 170 | { 171 | float3 MinColor, MaxColor; 172 | GetMinMax(Block, MinColor, MaxColor); 173 | 174 | uint MinColor565 = Float3ToUint565_Floor(MinColor); 175 | uint MaxColor565 = Float3ToUint565_Ceil(MaxColor); 176 | 177 | uint Indices = 0; 178 | if (MinColor565 < MaxColor565) 179 | { 180 | Indices = GetPackedColorBlockIndices(Block, MinColor, MaxColor); 181 | } 182 | 183 | return uint2((MinColor565 << 16) | MaxColor565, Indices); 184 | } 185 | 186 | // Compress a BC1 block that will be sampled as sRGB 187 | // We expect linear colors as input and convert internally 188 | uint2 CompressBC1Block_SRGB(in float3 Block[16]) 189 | { 190 | #if (FEATURE_LEVEL == FEATURE_LEVEL_ES3_1) 191 | // mobile uses linear color for RVT 192 | return CompressBC1Block(Block); 193 | #endif 194 | 195 | float3 MinColor, MaxColor; 196 | GetMinMax(Block, MinColor, MaxColor); 197 | 198 | uint MinColor565 = Float3ToUint565(LinearToSrgb(MinColor)); 199 | uint MaxColor565 = Float3ToUint565(LinearToSrgb(MaxColor)); 200 | 201 | uint Indices = 0; 202 | if (MinColor565 < MaxColor565) 203 | { 204 | Indices = GetPackedColorBlockIndices(Block, MinColor, MaxColor); 205 | } 206 | 207 | return uint2((MinColor565 << 16) | MaxColor565, Indices); 208 | } 209 | 210 | // Compress a BC3 block 211 | uint4 CompressBC3Block(in float3 BlockRGB[16], in float BlockA[16]) 212 | { 213 | float3 MinColor, MaxColor; 214 | GetMinMax(BlockRGB, MinColor, MaxColor); 215 | 216 | uint MinColor565 = Float3ToUint565_Floor(MinColor); 217 | uint MaxColor565 = Float3ToUint565_Ceil(MaxColor); 218 | 219 | float MinAlpha, MaxAlpha; 220 | GetMinMax(BlockA, MinAlpha, MaxAlpha); 221 | 222 | uint MinAlphaUint = (uint) round(MinAlpha * 255.f); 223 | uint MaxAlphaUint = (uint) round(MaxAlpha * 255.f); 224 | 225 | uint ColorIndices = 0; 226 | if (MinColor565 < MaxColor565) 227 | { 228 | ColorIndices = GetPackedColorBlockIndices(BlockRGB, MinColor, MaxColor); 229 | } 230 | 231 | uint2 AlphaIndices = 0; 232 | if (MinAlphaUint < MaxAlphaUint) 233 | { 234 | AlphaIndices = GetPackedAlphaBlockIndices(BlockA, MinAlpha, MaxAlpha); 235 | } 236 | 237 | return uint4((MinAlphaUint << 8) | MaxAlphaUint | AlphaIndices.x, AlphaIndices.y, (MinColor565 << 16) | MaxColor565, ColorIndices); 238 | } 239 | 240 | // Compress a BC3 block that will be sampled as sRGB 241 | // We expect linear colors as input and convert internally 242 | uint4 CompressBC3Block_SRGB(in float3 BlockRGB[16], in float BlockA[16]) 243 | { 244 | #if (FEATURE_LEVEL == FEATURE_LEVEL_ES3_1) 245 | // mobile uses linear color for RVT 246 | return CompressBC3Block(BlockRGB, BlockA); 247 | #endif 248 | 249 | float3 MinColor, MaxColor; 250 | GetMinMax(BlockRGB, MinColor, MaxColor); 251 | 252 | uint MinColor565 = Float3ToUint565(LinearToSrgb(MinColor)); 253 | uint MaxColor565 = Float3ToUint565(LinearToSrgb(MaxColor)); 254 | 255 | float MinAlpha, MaxAlpha; 256 | GetMinMax(BlockA, MinAlpha, MaxAlpha); 257 | 258 | uint MinAlphaUint = (uint) round(MinAlpha * 255.f); 259 | uint MaxAlphaUint = (uint) round(MaxAlpha * 255.f); 260 | 261 | uint ColorIndices = 0; 262 | if (MinColor565 < MaxColor565) 263 | { 264 | ColorIndices = GetPackedColorBlockIndices(BlockRGB, MinColor, MaxColor); 265 | } 266 | 267 | uint2 AlphaIndices = 0; 268 | if (MinAlphaUint < MaxAlphaUint) 269 | { 270 | AlphaIndices = GetPackedAlphaBlockIndices(BlockA, MinAlpha, MaxAlpha); 271 | } 272 | 273 | return uint4((MinAlphaUint << 8) | MaxAlphaUint | AlphaIndices.x, AlphaIndices.y, (MinColor565 << 16) | MaxColor565, ColorIndices); 274 | } 275 | 276 | // Compress a BC4 block 277 | uint2 CompressBC4Block(in float Block[16]) 278 | { 279 | float MinAlpha, MaxAlpha; 280 | GetMinMax(Block, MinAlpha, MaxAlpha); 281 | 282 | uint MinAlphaUint = (uint) round(MinAlpha * 255.f); 283 | uint MaxAlphaUint = (uint) round(MaxAlpha * 255.f); 284 | 285 | uint2 Indices = 0; 286 | if (MinAlphaUint < MaxAlphaUint) 287 | { 288 | Indices = GetPackedAlphaBlockIndices(Block, MinAlpha, MaxAlpha); 289 | } 290 | 291 | return uint2((MinAlphaUint << 8) | MaxAlphaUint | Indices.x, Indices.y); 292 | } 293 | 294 | // Compress a BC5 block 295 | uint4 CompressBC5Block(in float BlockU[16], in float BlockV[16]) 296 | { 297 | float MinU, MaxU, MinV, MaxV; 298 | GetMinMax(BlockU, BlockV, MinU, MaxU, MinV, MaxV); 299 | 300 | uint MinUUint = (uint) round(MinU * 255.f); 301 | uint MaxUUint = (uint) round(MaxU * 255.f); 302 | uint MinVUint = (uint) round(MinV * 255.f); 303 | uint MaxVUint = (uint) round(MaxV * 255.f); 304 | 305 | uint2 IndicesU = 0; 306 | if (MinUUint < MaxUUint) 307 | { 308 | IndicesU = GetPackedAlphaBlockIndices(BlockU, MinU, MaxU); 309 | } 310 | 311 | uint2 IndicesV = 0; 312 | if (MinVUint < MaxVUint) 313 | { 314 | IndicesV = GetPackedAlphaBlockIndices(BlockV, MinV, MaxV); 315 | } 316 | 317 | return uint4((MinUUint << 8) | MaxUUint | IndicesU.x, IndicesU.y, (MinVUint << 8) | MaxVUint | IndicesV.x, IndicesV.y); 318 | } 319 | 320 | // Convert RGB linear color to YCoCG 321 | float3 RGB2YCoCg(float3 RGB) 322 | { 323 | float Y = (RGB.r + 2.f * RGB.g + RGB.b) * 0.25f; 324 | float Co = ((2.f * RGB.r - 2.f * RGB.b) * 0.25f + 128.f / 255.f); 325 | float Cg = ((-RGB.r + 2.f * RGB.g - RGB.b) * 0.25f + 128.f / 255.f); 326 | return float3(Y, Co, Cg); 327 | } 328 | 329 | // Get a single scale factor to use for a YCoCg color block 330 | // This increases precision at the expense of potential blending artifacts across blocks 331 | float2 GetYCoCgScale(float2 MinCoCg, float2 MaxCoCg) 332 | { 333 | MinCoCg = abs(MinCoCg - 128.f / 255.f); 334 | MaxCoCg = abs(MaxCoCg - 128.f / 255.f); 335 | 336 | float MaxComponent = max(max(MinCoCg.x, MinCoCg.y), max(MaxCoCg.x, MaxCoCg.y)); 337 | 338 | return (MaxComponent < 32.f / 255.f) ? float2(4.f, 0.25f) : (MaxComponent < 64.f / 255.f) ? float2(2.f, 0.5f) : float2(1.f, 1.f); 339 | } 340 | 341 | void ApplyYCoCgScale(inout float2 MinCoCg, inout float2 MaxCoCg, float Scale) 342 | { 343 | MinCoCg = (MinCoCg - 128.f / 255.f) * Scale + 128.f / 255.f; 344 | MaxCoCg = (MaxCoCg - 128.f / 255.f) * Scale + 128.f / 255.f; 345 | } 346 | 347 | // Inset the CoCg bounding end points 348 | void InsetCoCgEndPoints(inout float2 MinCoCg, inout float2 MaxCoGg) 349 | { 350 | float2 Inset = (MaxCoGg - MinCoCg - (8.f / 255.f)) / 16.f; 351 | MinCoCg = saturate(MinCoCg + Inset); 352 | MaxCoGg = saturate(MaxCoGg - Inset); 353 | } 354 | 355 | // Inset the luminance end points 356 | void InsetLumaEndPoints(inout float MinY, inout float MaxY) 357 | { 358 | float Inset = (MaxY - MinY - (16.f / 255.f)) / 32.f; 359 | MinY = saturate(MinY + Inset); 360 | MaxY = saturate(MaxY - Inset); 361 | } 362 | 363 | // Select the 2 min/max end points from the CoCg bounding rectangle based on the block contents 364 | void AdjustMinMaxDiagonalYCoCg(const float3 Block[16], inout float2 MinCoCg, inout float2 MaxCoGg) 365 | { 366 | float2 MidCoCg = (MaxCoGg + MinCoCg) * 0.5; 367 | 368 | float Sum = 0.f; 369 | for (int i = 0; i < 16; i++) 370 | { 371 | float2 Diff = Block[i].yz - MidCoCg; 372 | Sum += Diff.x * Diff.y; 373 | } 374 | if (Sum < 0.f) 375 | { 376 | float Temp = MaxCoGg.y; 377 | MaxCoGg.y = MinCoCg.y; 378 | MinCoCg.y = Temp; 379 | } 380 | } 381 | 382 | uint CoCgToUint565(inout float2 CoCg) 383 | { 384 | float2 Scale = float2(31.f, 63.f); 385 | float2 ColorScaled = round(saturate(CoCg) * Scale); 386 | uint ColorPacked = ((uint) ColorScaled.r << 11) | ((uint) ColorScaled.g << 5); 387 | CoCg = ColorScaled / Scale; 388 | 389 | return ColorPacked; 390 | } 391 | 392 | // Calculate the final packed indices for the CoCg part of a color block 393 | uint GetPackedCoCgBlockIndices(in float3 Block[16], in float2 MinCoCg, in float2 MaxCoCg) 394 | { 395 | uint PackedIndices = 0; 396 | 397 | // Project onto max->min color vector and segment into range [0,3] 398 | float2 Range = MinCoCg - MaxCoCg; 399 | float Scale = 3.f / dot(Range, Range); 400 | float2 ScaledRange = Range * Scale; 401 | float Bias = (dot(MaxCoCg, MaxCoCg) - dot(MaxCoCg, MinCoCg)) * Scale; 402 | 403 | for (int i = 15; i >= 0; --i) 404 | { 405 | // Compute the distance index for this element 406 | uint Index = round(dot(Block[i].yz, ScaledRange) + Bias); 407 | // Convert distance index into the BC index 408 | Index += (Index > 0) - (3 * (Index == 3)); 409 | // OR into the final PackedIndices 410 | PackedIndices = (PackedIndices << 2) | Index; 411 | } 412 | 413 | return PackedIndices; 414 | } 415 | 416 | // Calculate the final packed indices for the Luma part of a color block 417 | uint2 GetPackedLumaBlockIndices(in float3 Block[16], in float MinAlpha, in float MaxAlpha) 418 | { 419 | uint2 PackedIndices = 0; 420 | 421 | // Segment alpha max->min into range [0,7] 422 | float Range = MinAlpha - MaxAlpha; 423 | float Scale = 7.f / Range; 424 | float Bias = -Scale * MaxAlpha; 425 | 426 | uint i = 0; 427 | // The first 5 elements of the block will go into the top 16 bits of the x component 428 | for (i = 0; i < 5; ++i) 429 | { 430 | // Compute the distance index for this element 431 | uint Index = round(Block[i].x * Scale + Bias); 432 | // Convert distance index into the BC index 433 | Index += (Index > 0) - (7 * (Index == 7)); 434 | // OR into the final PackedIndices 435 | PackedIndices.x |= (Index << (i * 3 + 16)); 436 | } 437 | 438 | // The 6th element is split across the x and y components 439 | { 440 | i = 5; 441 | uint Index = round(Block[i].x * Scale + Bias); 442 | Index += (Index > 0) - (7 * (Index == 7)); 443 | PackedIndices.x |= (Index << 31); 444 | PackedIndices.y |= (Index >> 1); 445 | } 446 | 447 | // The rest of the elements fill the y component 448 | for (i = 6; i < 16; ++i) 449 | { 450 | uint Index = round(Block[i].x * Scale + Bias); 451 | Index += (Index > 0) - (7 * (Index == 7 ? 1 : 0)); 452 | PackedIndices.y |= (Index << (i * 3 - 16)); 453 | } 454 | 455 | return PackedIndices; 456 | } 457 | 458 | // Convert a linear RGB block to YCoCg and compress a BC3 block 459 | uint4 CompressBC3BlockYCoCg(in float3 Block[16]) 460 | { 461 | for (int i = 0; i < 16; ++i) 462 | { 463 | Block[i] = RGB2YCoCg(Block[i]); 464 | } 465 | 466 | float3 MinColor, MaxColor; 467 | GetMinMax(Block, MinColor, MaxColor); 468 | 469 | AdjustMinMaxDiagonalYCoCg(Block, MinColor.yz, MaxColor.yz); 470 | 471 | float2 Scale = GetYCoCgScale(MinColor.yz, MaxColor.yz); 472 | 473 | ApplyYCoCgScale(MinColor.yz, MaxColor.yz, Scale.x); 474 | 475 | InsetCoCgEndPoints(MinColor.yz, MaxColor.yz); 476 | 477 | uint MinColor565 = CoCgToUint565(MinColor.yz) | ((uint) Scale.x - 1); 478 | uint MaxColor565 = CoCgToUint565(MaxColor.yz) | ((uint) Scale.x - 1); 479 | 480 | ApplyYCoCgScale(MinColor.yz, MaxColor.yz, Scale.y); 481 | 482 | uint CoCgIndices = GetPackedCoCgBlockIndices(Block, MinColor.yz, MaxColor.yz); 483 | 484 | InsetLumaEndPoints(MinColor.x, MaxColor.x); 485 | 486 | uint MinLumaUint = round(MinColor.x * 255.f); 487 | uint MaxLumaUint = round(MaxColor.x * 255.f); 488 | 489 | uint2 Indices = GetPackedLumaBlockIndices(Block, MinColor.x, MaxColor.x); 490 | 491 | return uint4((MinLumaUint << 8) | MaxLumaUint | Indices.x, Indices.y, (MinColor565 << 16) | MaxColor565, CoCgIndices); 492 | } 493 | 494 | #endif 495 | -------------------------------------------------------------------------------- /Shaders/Compress/BCCompress.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cc1c0bcb6edf1c646bb37cbb103d55da 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | preprocessorOverride: 0 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Shaders/Compress/ComputeCompress.compute: -------------------------------------------------------------------------------- 1 | #include "BCCompress.hlsl" 2 | #include "ETCCompress.hlsl" 3 | 4 | //#pragma enable_d3d11_debug_symbols 5 | #pragma multi_compile _COMPRESS_BC3 _COMPRESS_ETC2 6 | 7 | uint _Size; 8 | Texture2D _SrcTexture; SamplerState sampler_SrcTexture; 9 | RWTexture2D _DscTexture; 10 | 11 | void ReadBlockRGB(Texture2D SourceTexture, SamplerState TextureSampler, float2 UV, float2 TexelUVSize, out float3 Block[16]) 12 | { 13 | { 14 | float4 Red = SourceTexture.GatherRed(TextureSampler, UV); 15 | float4 Green = SourceTexture.GatherGreen(TextureSampler, UV); 16 | float4 Blue = SourceTexture.GatherBlue(TextureSampler, UV); 17 | Block[0] = float3(Red.a, Green.a, Blue.a); 18 | Block[1] = float3(Red.b, Green.b, Blue.b); 19 | Block[4] = float3(Red.r, Green.r, Blue.r); 20 | Block[5] = float3(Red.g, Green.g, Blue.g); 21 | /*Block[0] = float3(Red[3], Green[3], Blue[3]); 22 | Block[1] = float3(Red[2], Green[2], Blue[2]); 23 | Block[4] = float3(Red[0], Green[0], Blue[0]); 24 | Block[5] = float3(Red[1], Green[1], Blue[1]);*/ 25 | } 26 | { 27 | float2 UVOffset = UV + float2(2.f * TexelUVSize.x, 0); 28 | float4 Red = SourceTexture.GatherRed(TextureSampler, UVOffset); 29 | float4 Green = SourceTexture.GatherGreen(TextureSampler, UVOffset); 30 | float4 Blue = SourceTexture.GatherBlue(TextureSampler, UVOffset); 31 | Block[2] = float3(Red.a, Green.a, Blue.a); 32 | Block[3] = float3(Red.b, Green.b, Blue.b); 33 | Block[6] = float3(Red.r, Green.r, Blue.r); 34 | Block[7] = float3(Red.g, Green.g, Blue.g); 35 | /*Block[2] = float3(Red[3], Green[3], Blue[3]); 36 | Block[3] = float3(Red[2], Green[2], Blue[2]); 37 | Block[6] = float3(Red[0], Green[0], Blue[0]); 38 | Block[7] = float3(Red[1], Green[1], Blue[1]);*/ 39 | } 40 | { 41 | float2 UVOffset = UV + float2(0, 2.f * TexelUVSize.y); 42 | float4 Red = SourceTexture.GatherRed(TextureSampler, UVOffset); 43 | float4 Green = SourceTexture.GatherGreen(TextureSampler, UVOffset); 44 | float4 Blue = SourceTexture.GatherBlue(TextureSampler, UVOffset); 45 | Block[8] = float3(Red.a, Green.a, Blue.a); 46 | Block[9] = float3(Red.b, Green.b, Blue.b); 47 | Block[12] = float3(Red.r, Green.r, Blue.r); 48 | Block[13] = float3(Red.g, Green.g, Blue.g); 49 | /*Block[8] = float3(Red[3], Green[3], Blue[3]); 50 | Block[9] = float3(Red[2], Green[2], Blue[2]); 51 | Block[12] = float3(Red[0], Green[0], Blue[0]); 52 | Block[13] = float3(Red[1], Green[1], Blue[1]);*/ 53 | } 54 | { 55 | float2 UVOffset = UV + 2.f * TexelUVSize; 56 | float4 Red = SourceTexture.GatherRed(TextureSampler, UVOffset); 57 | float4 Green = SourceTexture.GatherGreen(TextureSampler, UVOffset); 58 | float4 Blue = SourceTexture.GatherBlue(TextureSampler, UVOffset); 59 | Block[10] = float3(Red.a, Green.a, Blue.a); 60 | Block[11] = float3(Red.b, Green.b, Blue.b); 61 | Block[14] = float3(Red.r, Green.r, Blue.r); 62 | Block[15] = float3(Red.g, Green.g, Blue.g); 63 | /*Block[10] = float3(Red[3], Green[3], Blue[3]); 64 | Block[11] = float3(Red[2], Green[2], Blue[2]); 65 | Block[14] = float3(Red[0], Green[0], Blue[0]); 66 | Block[15] = float3(Red[1], Green[1], Blue[1]);*/ 67 | } 68 | } 69 | 70 | #pragma kernel Compress 71 | [numthreads(8, 8, 1)] 72 | void Compress(uint3 ThreadId : SV_DispatchThreadID) 73 | { 74 | uint2 SamplePos = ThreadId.xy * 4; 75 | if (any(SamplePos >= _Size.xx)) { return; } 76 | 77 | float2 TexelUVSize = 1.0f / _Size; 78 | float2 SampleUV = (float2(SamplePos) + 0.5f) * TexelUVSize; 79 | 80 | float BlockA[16]; 81 | float3 BlockRGB[16]; 82 | ReadBlockRGB(_SrcTexture, sampler_SrcTexture, SampleUV, TexelUVSize, BlockRGB); 83 | 84 | for (int i = 0; i < 16; ++i) 85 | { 86 | BlockA[i] = 1; 87 | } 88 | 89 | #ifdef _COMPRESS_BC3 90 | _DscTexture[ThreadId.xy] = CompressBC3Block_SRGB(BlockRGB, BlockA); 91 | #else 92 | _DscTexture[ThreadId.xy] = CompressBlock_ETC2_RGBA(BlockRGB, BlockA); 93 | #endif 94 | } 95 | 96 | 97 | /*Texture2D _SrcAlbedo; SamplerState sampler_SrcAlbedo; 98 | Texture2D _SrcNormal; SamplerState sampler_SrcNormal; 99 | RWTexture2D _DscAlbedo, _DscNormal; 100 | 101 | #pragma kernel CompressPacked 102 | [numthreads(8, 8, 1)] 103 | void CompressPacked(uint3 ThreadId : SV_DispatchThreadID) 104 | { 105 | uint2 SamplePos = ThreadId.xy * 4; 106 | if (any(SamplePos >= _Size.xx)) { return; } 107 | 108 | float2 TexelUVSize = 1.0f / _Size; 109 | float2 SampleUV = (float2(SamplePos) + 0.5f) * TexelUVSize; 110 | 111 | float AlbedoBlockA[16]; 112 | float3 AlbedoBlockRGB[16]; 113 | ReadBlockRGB(_SrcAlbedo, sampler_SrcAlbedo, SampleUV, TexelUVSize, AlbedoBlockRGB); 114 | 115 | float NormalBlockA[16]; 116 | float3 NormalBlockRGB[16]; 117 | ReadBlockRGB(_SrcNormal, sampler_SrcNormal, SampleUV, TexelUVSize, NormalBlockRGB); 118 | 119 | for (int i = 0; i < 16; ++i) 120 | { 121 | AlbedoBlockA[i] = 1; 122 | NormalBlockA[i] = 1; 123 | } 124 | 125 | #ifdef _COMPRESS_BC3 126 | _DscAlbedo[ThreadId.xy] = CompressBC3Block_SRGB(AlbedoBlockRGB, AlbedoBlockA); 127 | _DscNormal[ThreadId.xy] = CompressBC3Block_SRGB(NormalBlockRGB, NormalBlockA); 128 | #else 129 | _DscAlbedo[ThreadId.xy] = CompressBlock_ETC2_RGBA(AlbedoBlockRGB, AlbedoBlockA); 130 | _DscNormal[ThreadId.xy] = CompressBlock_ETC2_RGBA(NormalBlockRGB, NormalBlockA); 131 | #endif 132 | }*/ -------------------------------------------------------------------------------- /Shaders/Compress/ComputeCompress.compute.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e34776c72005e1e488fbdc217f4556c5 3 | ComputeShaderImporter: 4 | externalObjects: {} 5 | currentAPIMask: 2097156 6 | preprocessorOverride: 0 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Compress/ETCCompress.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef _ETCCompress_ 2 | #define _ETCCompress_ 3 | 4 | #define BLOCK_MODE_INDIVIDUAL 0 5 | #define BLOCK_MODE_DIFFERENTIAL 1 6 | #define NUM_RGB_TABLES 8 7 | #define NUM_ALPHA_TABLES 16 8 | 9 | float4 alpha_distance_tables[16] = 10 | { 11 | float4(2, 5, 8, 14), 12 | float4(2, 6, 9, 12), 13 | float4(1, 4, 7, 12), 14 | float4(1, 3, 5, 12), 15 | float4(2, 5, 7, 11), 16 | float4(2, 6, 8, 10), 17 | float4(3, 6, 7, 10), 18 | float4(2, 4, 7, 10), 19 | float4(1, 5, 7, 9), 20 | float4(1, 4, 7, 9), 21 | float4(1, 3, 7, 9), 22 | float4(1, 4, 6, 9), 23 | float4(2, 3, 6, 9), 24 | float4(0, 1, 2, 9), 25 | float4(3, 5, 7, 8), 26 | float4(2, 4, 6, 8) 27 | }; 28 | 29 | float4 rgb_distance_tables[8] = 30 | { 31 | float4(-8, -2, 2, 8), 32 | float4(-17, -5, 5, 17), 33 | float4(-29, -9, 9, 29), 34 | float4(-42, -13, 13, 42), 35 | float4(-60, -18, 18, 60), 36 | float4(-80, -24, 24, 80), 37 | float4(-106, -33, 33, 106), 38 | float4(-183, -47, 47, 183) 39 | }; 40 | 41 | void SelectAlphaMod(in float SourceAlpha, in float EncodedAlpha, int IndexInTable, inout int SelectedIndex, inout float MinDif) 42 | { 43 | float Dif = abs(EncodedAlpha - SourceAlpha); 44 | if (Dif < MinDif) 45 | { 46 | MinDif = Dif; 47 | SelectedIndex = IndexInTable; 48 | } 49 | } 50 | 51 | 52 | int3 FloatColorToUint555(in float3 FloatColor) 53 | { 54 | float3 Scale = float3(31.f, 31.f, 31.f); 55 | float3 ColorScaled = round(saturate(FloatColor) * Scale); 56 | return int3((int) ColorScaled.r, (int) ColorScaled.g, (int) ColorScaled.b); 57 | } 58 | 59 | float3 ExpandColor444(in int3 Color444) 60 | { 61 | int3 Color888 = (Color444 << 4) + Color444; 62 | return Color888 / 255.f; 63 | } 64 | 65 | float3 ExpandColor555(in int3 Color555) 66 | { 67 | int3 Color888 = (Color555 << 3) + (Color555 >> 2); 68 | return Color888 / 255.f; 69 | } 70 | 71 | uint SwapEndian32(in uint x) 72 | { 73 | return 74 | ((x & 0x0000ff) << 24) | 75 | ((x & 0x00ff00) << 8) | 76 | ((x & 0xff0000) >> 8) | 77 | (x >> 24); 78 | } 79 | 80 | float Luminance(float3 LinearColor) 81 | { 82 | return dot(LinearColor, float3(0.3, 0.59, 0.11)); 83 | } 84 | 85 | float max3(float a, float b, float c) 86 | { 87 | return max(a, max(b, c)); 88 | } 89 | 90 | float min3(float a, float b, float c) 91 | { 92 | return min(a, min(b, c)); 93 | } 94 | 95 | uint SelectRGBTableIndex(float LuminanceR) 96 | { 97 | uint Out = 7; 98 | float Range = (LuminanceR + LuminanceR * 0.1) * 255.0; 99 | 100 | if (Range < 8.0) 101 | { 102 | Out = 0; 103 | } else if (Range < 17.0) { 104 | Out = 1; 105 | } else if (Range < 29.0) { 106 | Out = 2; 107 | } else if (Range < 42.0) { 108 | Out = 3; 109 | } else if (Range < 60.0) { 110 | Out = 4; 111 | } else if (Range < 80.0) { 112 | Out = 5; 113 | } else if (Range < 106.0) { 114 | Out = 6; 115 | } 116 | return Out; 117 | } 118 | 119 | 120 | void FindPixelWeights(in float3 Block[16], in float3 BaseColor, in uint TableIdx, in int StartX, in int EndX, in int StartY, in int EndY, out uint SubBlockWeights) 121 | { 122 | //int PIXEL_INDEX_ENCODE_TABLE[4] = { 3, 2, 0, 1 }; 123 | SubBlockWeights = 0; 124 | 125 | float TableRangeMax = rgb_distance_tables[TableIdx].w / 255.f; 126 | float BaseLum = Luminance(BaseColor); 127 | 128 | for (int Y = StartY; Y < EndY; ++Y) 129 | { 130 | for (int X = StartX; X < EndX; ++X) 131 | { 132 | float3 OrigColor = Block[4 * Y + X]; 133 | float Diff = Luminance(OrigColor) - BaseLum; 134 | int EncIndex = 0; 135 | if (Diff < 0.f) 136 | { 137 | EncIndex = (-Diff * 1.58) > TableRangeMax ? 3 : 2; 138 | } 139 | else 140 | { 141 | EncIndex = (Diff * 1.58) > TableRangeMax ? 1 : 0; 142 | } 143 | //int EncIndex = PIXEL_INDEX_ENCODE_TABLE[SelectedIndex]; 144 | int IndexInBlock = X * 4 + Y; 145 | SubBlockWeights |= ((EncIndex & 1) << IndexInBlock) | ((EncIndex >> 1) << (16 + IndexInBlock)); 146 | } 147 | } 148 | } 149 | 150 | uint2 CompressBlock_ETC2_RGB(in float3 Block[16]) 151 | { 152 | // Always use side-by-side mode (flip bit set to 0). 153 | uint FlipBit = 0; 154 | 155 | float3 BaseColor1_Float = (Block[0] + Block[1] + Block[4] + Block[5] + Block[8] + Block[9] + Block[12] + Block[13]) * 0.125; 156 | float3 BaseColor2_Float = (Block[2] + Block[3] + Block[6] + Block[7] + Block[10] + Block[11] + Block[14] + Block[15]) * 0.125; 157 | 158 | int3 BaseColor1 = FloatColorToUint555(BaseColor1_Float); 159 | int3 BaseColor2 = FloatColorToUint555(BaseColor2_Float); 160 | int3 Diff = BaseColor2 - BaseColor1; 161 | 162 | uint ColorBits; 163 | float3 BaseColor1_Quant, BaseColor2_Quant; 164 | 165 | uint BlockMode; 166 | int3 MinDiff = { -4, -4, -4 }, MaxDiff = { 3, 3, 3 }; 167 | if (all(Diff >= MinDiff) && all(Diff <= MaxDiff)) 168 | { 169 | // We can use differential mode. 170 | BlockMode = BLOCK_MODE_DIFFERENTIAL; 171 | ColorBits = ((Diff.b & 7) << 16) | (BaseColor1.b << 19) | ((Diff.g & 7) << 8) | (BaseColor1.g << 11) | (Diff.r & 7) | (BaseColor1.r << 3); 172 | BaseColor1_Quant = ExpandColor555(BaseColor1); 173 | BaseColor2_Quant = ExpandColor555(BaseColor2); 174 | } 175 | else 176 | { 177 | // We must use the lower precision individual mode. 178 | BlockMode = BLOCK_MODE_INDIVIDUAL; 179 | BaseColor1 >>= 1; 180 | BaseColor2 >>= 1; 181 | ColorBits = (BaseColor1.b << 20) | (BaseColor2.b << 16) | (BaseColor1.g << 12) | (BaseColor2.g << 8) | (BaseColor1.r << 4) | BaseColor2.r; 182 | BaseColor1_Quant = ExpandColor444(BaseColor1); 183 | BaseColor2_Quant = ExpandColor444(BaseColor2); 184 | } 185 | 186 | float l00 = Luminance(Block[0]); 187 | float l08 = Luminance(Block[8]); 188 | float l13 = Luminance(Block[13]); 189 | float LuminanceR1 = (max3(l00, l08, l13) - min3(l00, l08, l13)) * 0.5; 190 | uint SubBlock1TableIdx = SelectRGBTableIndex(LuminanceR1); 191 | uint SubBlock1Weights = 0; 192 | FindPixelWeights(Block, BaseColor1_Quant, SubBlock1TableIdx, 0, 2, 0, 4, SubBlock1Weights); 193 | 194 | float l02 = Luminance(Block[2]); 195 | float l10 = Luminance(Block[10]); 196 | float l15 = Luminance(Block[15]); 197 | float LuminanceR2 = (max3(l02, l10, l15) - min3(l02, l10, l15)) * 0.5; 198 | uint SubBlock2TableIdx = SelectRGBTableIndex(LuminanceR2); 199 | uint SubBlock2Weights = 0; 200 | FindPixelWeights(Block, BaseColor2_Quant, SubBlock2TableIdx, 2, 4, 0, 4, SubBlock2Weights); 201 | 202 | // Both these values need to be big-endian. We can build ModeBits directly in big-endian layout, but for IndexBits 203 | // it's too hard, so we'll just swap here. 204 | uint ModeBits = (SubBlock1TableIdx << 29) | (SubBlock2TableIdx << 26) | (BlockMode << 25) | (FlipBit << 24) | ColorBits; 205 | uint IndexBits = SwapEndian32(SubBlock1Weights | SubBlock2Weights); 206 | 207 | return uint2(ModeBits, IndexBits); 208 | } 209 | 210 | uint2 CompressBlock_ETC2_Alpha(in float BlockA[16]) 211 | { 212 | float MinAlpha = 1.f; 213 | float MaxAlpha = 0.f; 214 | for (int k = 0; k < 16; ++k) 215 | { 216 | float A = BlockA[k]; 217 | MinAlpha = min(A, MinAlpha); 218 | MaxAlpha = max(A, MaxAlpha); 219 | } 220 | 221 | float AlphaRange = MaxAlpha - MinAlpha; 222 | const float MidRange = 20.f; // an average range in ALPHA_DISTANCE_TABLES 223 | float Multiplier = clamp(round(255.f * AlphaRange / MidRange), 1.f, 15.f); 224 | 225 | int TableIdx = 0; 226 | float4 TableValueNeg = float4(0, 0, 0, 0); 227 | float4 TableValuePos = float4(0, 0, 0, 0); 228 | 229 | // iterating through all tables to find a best fit is quite slow 230 | // instead guess the best table based on alpha range 231 | for (int i = 0; i < NUM_ALPHA_TABLES; ++i) 232 | { 233 | TableIdx = NUM_ALPHA_TABLES - 1 - i; 234 | TableValuePos = alpha_distance_tables[TableIdx]; 235 | 236 | float TableRange = ((TableValuePos.w * 2 + 1) / 255.f) * Multiplier; 237 | float Dif = TableRange - AlphaRange; 238 | if (Dif >= 0.f) 239 | { 240 | break; 241 | } 242 | } 243 | TableValueNeg = -(TableValuePos + float4(1, 1, 1, 1)); 244 | 245 | // make sure an exact value of MinAlpha can always be decoded from a BaseValue 246 | float BaseValue = MinAlpha - TableValueNeg.w; 247 | 248 | TableValueNeg = saturate(TableValueNeg + BaseValue.xxxx); 249 | TableValuePos = saturate(TableValuePos + BaseValue.xxxx); 250 | uint2 BlockWeights = 0; 251 | 252 | for (int PixelIndex = 0; PixelIndex < 16; ++PixelIndex) 253 | { 254 | float Alpha = BlockA[PixelIndex]; 255 | int SelectedIndex = 0; 256 | float MinDif = 100000.f; 257 | 258 | if ((Alpha - TableValuePos.x) < 0.f) 259 | { 260 | SelectAlphaMod(Alpha, TableValueNeg.x, 0, SelectedIndex, MinDif); 261 | SelectAlphaMod(Alpha, TableValueNeg.y, 1, SelectedIndex, MinDif); 262 | SelectAlphaMod(Alpha, TableValueNeg.z, 2, SelectedIndex, MinDif); 263 | SelectAlphaMod(Alpha, TableValueNeg.w, 3, SelectedIndex, MinDif); 264 | } 265 | else 266 | { 267 | SelectAlphaMod(Alpha, TableValuePos.x, 4, SelectedIndex, MinDif); 268 | SelectAlphaMod(Alpha, TableValuePos.y, 5, SelectedIndex, MinDif); 269 | SelectAlphaMod(Alpha, TableValuePos.z, 6, SelectedIndex, MinDif); 270 | SelectAlphaMod(Alpha, TableValuePos.w, 7, SelectedIndex, MinDif); 271 | } 272 | 273 | // ETC uses column-major indexing for the pixels in a block... 274 | int TransposedIndex = (PixelIndex >> 2) | ((PixelIndex & 3) << 2); 275 | int StartBit = (15 - TransposedIndex) * 3; 276 | BlockWeights.x |= (StartBit < 32) ? SelectedIndex << StartBit : 0; 277 | int ShiftRight = (StartBit == 30) ? 2 : 0; 278 | int ShiftLeft = (StartBit >= 32) ? StartBit - 32 : 0; 279 | BlockWeights.y |= (StartBit >= 30) ? (SelectedIndex >> ShiftRight) << ShiftLeft : 0; 280 | } 281 | 282 | int MultiplierInt = round(Multiplier); 283 | int BaseValueInt = round(BaseValue * 255.f); 284 | 285 | uint2 AlphaBits; 286 | AlphaBits.x = SwapEndian32(BlockWeights.y | (TableIdx << 16) | (MultiplierInt << 20) | (BaseValueInt << 24)); 287 | AlphaBits.y = SwapEndian32(BlockWeights.x); 288 | 289 | return AlphaBits; 290 | } 291 | 292 | uint4 CompressBlock_ETC2_RGBA(in float3 BlockRGB[16], in float BlockA[16]) 293 | { 294 | uint2 CompressedRGB = CompressBlock_ETC2_RGB(BlockRGB); 295 | uint2 CompressedAlpha = CompressBlock_ETC2_Alpha(BlockA); 296 | return uint4(CompressedAlpha, CompressedRGB); 297 | } 298 | 299 | #endif 300 | -------------------------------------------------------------------------------- /Shaders/Compress/ETCCompress.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 68e635d140bcf0046aa34c61e663db2b 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | preprocessorOverride: 0 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Shaders/DummyVirtualTextureShaderLibrary.cs: -------------------------------------------------------------------------------- 1 | // This file is only to force Unity to load the ShaderLibrary's hlsl files in visual studio project via asmdef file, so they can be browse. 2 | class DummyVirtualTextureShaderLibrary 3 | { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /Shaders/DummyVirtualTextureShaderLibrary.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d1ee1287fe978bd4c898da921761de89 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Shaders/Infinity.Rendering.VirtualTexture.Shader.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Infinity.Rendering.VirtualTexture.Shader", 3 | "rootNamespace": "", 4 | "references": [ 5 | "GUID:46a67ded66a63de48b9329c593fc08de", 6 | "GUID:c5fe2eb9d5ef64b4f892cb2e1428b4cc" 7 | ], 8 | "includePlatforms": [], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": true, 11 | "overrideReferences": false, 12 | "precompiledReferences": [], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /Shaders/Infinity.Rendering.VirtualTexture.Shader.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd482b936f0513b419aff029d5af0cb3 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Shaders/PageTable.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 37c6076ea94188445930dcb784757e41 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/PageTable/DrawPageColor.shader: -------------------------------------------------------------------------------- 1 | Shader "VirtualTexture/DrawPageColor" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | _Diffuse1("Diffuse1", 2D) = "white" {} 7 | _Diffuse2("Diffuse2", 2D) = "white" {} 8 | _Diffuse3("Diffuse3", 2D) = "white" {} 9 | _Diffuse4("Diffuse4", 2D) = "white" {} 10 | 11 | _Normal1("Normal1", 2D) = "white" {} 12 | _Normal2("Normal2", 2D) = "white" {} 13 | _Normal3("Normal3", 2D) = "white" {} 14 | _Normal4("Normal4", 2D) = "white" {} 15 | _Blend("Blend", 2D) = "white" {} 16 | _TileOffset1("TileOffset1",Vector) = (1,1,0,0) 17 | _TileOffset2("TileOffset2",Vector) = (1,1,0,0) 18 | _TileOffset3("TileOffset3",Vector) = (1,1,0,0) 19 | _TileOffset4("TileOffset4",Vector) = (1,1,0,0) 20 | _BlendTile("Blend Tile",Vector) = (0,0,100,100) 21 | } 22 | 23 | SubShader 24 | { 25 | Cull Off ZWrite Off ZTest Always 26 | 27 | Pass 28 | { 29 | HLSLPROGRAM 30 | #pragma target 4.5 31 | 32 | #pragma vertex vert 33 | #pragma fragment frag 34 | //#pragma enable_d3d11_debug_symbols 35 | 36 | #include "DrwaPageCommon.hlsl" 37 | ENDHLSL 38 | } 39 | 40 | Pass 41 | { 42 | Blend One One 43 | HLSLPROGRAM 44 | #pragma target 4.5 45 | 46 | #pragma vertex vert 47 | #pragma fragment frag 48 | #define TERRAIN_SPLAT_ADDPASS 49 | //#pragma enable_d3d11_debug_symbols 50 | 51 | #include "DrwaPageCommon.hlsl" 52 | ENDHLSL 53 | } 54 | 55 | /*Pass 56 | { 57 | HLSLPROGRAM 58 | #pragma target 4.5 59 | 60 | #pragma vertex vertTriangle 61 | #pragma fragment frag 62 | //#pragma enable_d3d11_debug_symbols 63 | 64 | #include "DrwaPageCommon.hlsl" 65 | ENDHLSL 66 | } 67 | 68 | Pass 69 | { 70 | Blend One One 71 | HLSLPROGRAM 72 | #pragma target 4.5 73 | 74 | #pragma vertex vertTriangle 75 | #pragma fragment frag 76 | #define TERRAIN_SPLAT_ADDPASS 77 | //#pragma enable_d3d11_debug_symbols 78 | 79 | #include "DrwaPageCommon.hlsl" 80 | ENDHLSL 81 | }*/ 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Shaders/PageTable/DrawPageColor.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 451669337d3073941bfd7910ae77fe65 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/PageTable/DrawPageTable.shader: -------------------------------------------------------------------------------- 1 | Shader "VirtualTexture/DrawPageTable" 2 | { 3 | SubShader 4 | { 5 | Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline"} 6 | 7 | Cull Front 8 | ZTest Always 9 | 10 | Pass 11 | { 12 | Tags { "LightMode" = "Default" } 13 | 14 | HLSLPROGRAM 15 | #pragma vertex vert 16 | #pragma fragment frag 17 | #pragma multi_compile_instancing 18 | //#pragma enable_d3d11_debug_symbols 19 | 20 | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 21 | 22 | struct Attributes 23 | { 24 | float4 positionOS : POSITION; 25 | float2 uv : TEXCOORD0; 26 | 27 | UNITY_VERTEX_INPUT_INSTANCE_ID 28 | }; 29 | 30 | struct Varyings 31 | { 32 | float4 color : TEXCOORD0; 33 | float4 positionHCS : SV_POSITION; 34 | }; 35 | 36 | float4 _tempInfo; 37 | UNITY_INSTANCING_BUFFER_START(InstanceProp) 38 | UNITY_DEFINE_INSTANCED_PROP(float4, _PageInfo) 39 | UNITY_DEFINE_INSTANCED_PROP(float4x4, _Matrix_MVP) 40 | UNITY_INSTANCING_BUFFER_END(InstanceProp) 41 | 42 | Varyings vert(Attributes IN) 43 | { 44 | Varyings OUT; 45 | UNITY_SETUP_INSTANCE_ID(IN); 46 | float4x4 mat = UNITY_MATRIX_M; 47 | 48 | mat = UNITY_ACCESS_INSTANCED_PROP(InstanceProp, _Matrix_MVP); 49 | float2 pos = saturate(mul(mat, IN.positionOS).xy); 50 | pos.y = 1 - pos.y; 51 | 52 | OUT.positionHCS = float4(2.0 * pos - 1,0.5,1); 53 | OUT.color = UNITY_ACCESS_INSTANCED_PROP(InstanceProp, _PageInfo); 54 | return OUT; 55 | } 56 | 57 | float4 frag(Varyings IN) : SV_Target 58 | { 59 | return IN.color; 60 | } 61 | ENDHLSL 62 | } 63 | 64 | Pass 65 | { 66 | Tags { "LightMode" = "Custom" } 67 | 68 | HLSLPROGRAM 69 | #pragma vertex vert 70 | #pragma fragment frag 71 | //#pragma enable_d3d11_debug_symbols 72 | 73 | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 74 | 75 | struct Attributes 76 | { 77 | uint InstanceId : SV_InstanceID; 78 | float2 texCoord0 : TEXCOORD0; 79 | float4 vertexOS : POSITION; 80 | }; 81 | 82 | struct Varyings 83 | { 84 | float4 texCoord0 : TEXCOORD0; 85 | float4 vertexCS : SV_POSITION; 86 | }; 87 | 88 | struct FPageTableInfo 89 | { 90 | float4 pageData; 91 | float4x4 matrix_M; 92 | }; 93 | 94 | StructuredBuffer _PageTableBuffer; 95 | 96 | Varyings vert(Attributes input) 97 | { 98 | Varyings output; 99 | FPageTableInfo PageTableInfo = _PageTableBuffer[input.InstanceId]; 100 | 101 | float2 pos = saturate(mul(PageTableInfo.matrix_M, input.vertexOS).xy); 102 | pos.y = 1 - pos.y; 103 | 104 | output.texCoord0 = PageTableInfo.pageData; 105 | output.vertexCS = float4(pos * 2 - 1, 0.5, 1); 106 | return output; 107 | } 108 | 109 | float4 frag(Varyings input) : SV_Target 110 | { 111 | return input.texCoord0; 112 | } 113 | ENDHLSL 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Shaders/PageTable/DrawPageTable.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e9b94491ae45d7c45af4ea434d0002a5 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/PageTable/DrwaPageCommon.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef PageCommon 2 | #define PageCommon 3 | 4 | #include "../Common/StochasticSampling.hlsl" 5 | #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl" 6 | #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl" 7 | 8 | float4 _SplatTileOffset; 9 | float4 _SurfaceTileOffset; 10 | float4x4 _Matrix_MVP; 11 | 12 | TEXTURE2D(_SplatTexture); 13 | TEXTURE2D(_AlbedoTexture1); 14 | TEXTURE2D(_AlbedoTexture2); 15 | TEXTURE2D(_AlbedoTexture3); 16 | TEXTURE2D(_AlbedoTexture4); 17 | TEXTURE2D(_NormalTexture1); 18 | TEXTURE2D(_NormalTexture2); 19 | TEXTURE2D(_NormalTexture3); 20 | TEXTURE2D(_NormalTexture4); 21 | 22 | SAMPLER(sampler_SplatTexture); 23 | SAMPLER(Global_trilinear_repeat_sampler); 24 | 25 | struct Attributes 26 | { 27 | float2 uv0 : TEXCOORD0; 28 | float4 vertexOS : POSITION; 29 | }; 30 | 31 | struct Varyings 32 | { 33 | float2 uv0 : TEXCOORD0; 34 | float4 vertexCS : SV_POSITION; 35 | }; 36 | 37 | Varyings vert(Attributes input) 38 | { 39 | Varyings output; 40 | output.uv0 = input.uv0; 41 | output.vertexCS = mul(_Matrix_MVP, input.vertexOS); 42 | return output; 43 | } 44 | 45 | Varyings vertTriangle(Attributes input) 46 | { 47 | Varyings output; 48 | output.vertexCS = float4(input.vertexOS.x, -input.vertexOS.y, 0, 1); 49 | output.uv0 = (input.vertexOS.xy + 1) * 0.5; 50 | return output; 51 | } 52 | 53 | void frag(Varyings input, out float4 ColorBuffer : SV_Target0, out float4 NormalBuffer : SV_Target1) 54 | { 55 | float4 splatMap = saturate(_SplatTexture.Sample(sampler_SplatTexture, input.uv0 * _SplatTileOffset.xy + _SplatTileOffset.zw)); 56 | 57 | #ifdef TERRAIN_SPLAT_ADDPASS 58 | clip(splatMap.x + splatMap.y + splatMap.z + splatMap.w <= 0.005h ? -1.0h : 1.0h); 59 | #endif 60 | 61 | float2 transUv = input.uv0 * _SurfaceTileOffset.xy + _SurfaceTileOffset.zw; 62 | 63 | /*float4 Diffuse1 = _AlbedoTexture1.Sample(Global_trilinear_repeat_sampler, transUv); 64 | float3 Normal1 = UnpackNormalScale(_NormalTexture1.Sample(Global_trilinear_repeat_sampler, transUv), 1); 65 | 66 | float4 Diffuse2 = _AlbedoTexture2.Sample(Global_trilinear_repeat_sampler, transUv); 67 | float3 Normal2 = UnpackNormalScale(_NormalTexture2.Sample(Global_trilinear_repeat_sampler, transUv), 1); 68 | 69 | float4 Diffuse3 = _AlbedoTexture3.Sample(Global_trilinear_repeat_sampler, transUv); 70 | float3 Normal3 = UnpackNormalScale(_NormalTexture3.Sample(Global_trilinear_repeat_sampler, transUv), 1); 71 | 72 | float4 Diffuse4 = _AlbedoTexture4.Sample(Global_trilinear_repeat_sampler, transUv); 73 | float3 Normal4 = UnpackNormalScale(_NormalTexture4.Sample(Global_trilinear_repeat_sampler, transUv), 1);*/ 74 | 75 | float3 cw5 = 0; 76 | float2 uv15 = 0; 77 | float2 uv25 = 0; 78 | float2 uv35 = 0; 79 | float2 dx5 = 0; 80 | float2 dy5 = 0; 81 | 82 | float3 cw8 = 0; 83 | float2 uv18 = 0; 84 | float2 uv28 = 0; 85 | float2 uv38 = 0; 86 | float2 dx8 = 0; 87 | float2 dy8 = 0; 88 | 89 | float StochasticScale = 0.5; 90 | 91 | float4 Diffuse1 = StochasticSample2DWeightsR(_AlbedoTexture1, Global_trilinear_repeat_sampler, transUv, cw5, uv15, uv25, uv35, dx5, dy5, StochasticScale, 0.15); 92 | float4 Normal1 = StochasticSample2DWeightsLum(_NormalTexture1, Global_trilinear_repeat_sampler, transUv, cw8, uv18, uv28, uv38, dx8, dy8, StochasticScale, 0.15); 93 | Normal1.xyz = UnpackNormalScale(Normal1, 1); 94 | 95 | float4 Diffuse2 = StochasticSample2DWeightsR(_AlbedoTexture2, Global_trilinear_repeat_sampler, transUv, cw5, uv15, uv25, uv35, dx5, dy5, StochasticScale, 0.15); 96 | float4 Normal2 = StochasticSample2DWeightsLum(_NormalTexture2, Global_trilinear_repeat_sampler, transUv, cw8, uv18, uv28, uv38, dx8, dy8, StochasticScale, 0.15); 97 | Normal2.xyz = UnpackNormalScale(Normal2, 1); 98 | 99 | float4 Diffuse3 = StochasticSample2DWeightsR(_AlbedoTexture3, Global_trilinear_repeat_sampler, transUv, cw5, uv15, uv25, uv35, dx5, dy5, StochasticScale, 0.15); 100 | float4 Normal3 = StochasticSample2DWeightsLum(_NormalTexture3, Global_trilinear_repeat_sampler, transUv, cw8, uv18, uv28, uv38, dx8, dy8, StochasticScale, 0.15); 101 | Normal3.xyz = UnpackNormalScale(Normal3, 1); 102 | 103 | float4 Diffuse4 = StochasticSample2DWeightsR(_AlbedoTexture4, Global_trilinear_repeat_sampler, transUv, cw5, uv15, uv25, uv35, dx5, dy5, StochasticScale, 0.15); 104 | float4 Normal4 = StochasticSample2DWeightsLum(_NormalTexture4, Global_trilinear_repeat_sampler, transUv, cw8, uv18, uv28, uv38, dx8, dy8, StochasticScale, 0.15); 105 | Normal4.xyz = UnpackNormalScale(Normal4, 1); 106 | 107 | /*float4 Diffuse1 = StochasticSample2D(_AlbedoTexture1, Global_trilinear_repeat_sampler, transUv); 108 | float4 Normal1 = StochasticSample2D(_NormalTexture1, Global_trilinear_repeat_sampler, transUv); 109 | 110 | float4 Diffuse2 = StochasticSample2D(_AlbedoTexture2, Global_trilinear_repeat_sampler, transUv); 111 | float4 Normal2 = StochasticSample2D(_NormalTexture2, Global_trilinear_repeat_sampler, transUv); 112 | 113 | float4 Diffuse3 = StochasticSample2D(_AlbedoTexture3, Global_trilinear_repeat_sampler, transUv); 114 | float4 Normal3 = StochasticSample2D(_NormalTexture3, Global_trilinear_repeat_sampler, transUv); 115 | 116 | float4 Diffuse4 = StochasticSample2D(_AlbedoTexture4, Global_trilinear_repeat_sampler, transUv); 117 | float4 Normal4 = StochasticSample2D(_NormalTexture4, Global_trilinear_repeat_sampler, transUv);*/ 118 | 119 | ColorBuffer = 0; 120 | ColorBuffer += splatMap.r * Diffuse1; 121 | ColorBuffer += splatMap.g * Diffuse2; 122 | ColorBuffer += splatMap.b * Diffuse3; 123 | ColorBuffer += splatMap.a * Diffuse4; 124 | 125 | NormalBuffer = 0; 126 | NormalBuffer.rgb += splatMap.r * Normal1; 127 | NormalBuffer.rgb += splatMap.g * Normal2; 128 | NormalBuffer.rgb += splatMap.b * Normal3; 129 | NormalBuffer.rgb += splatMap.a * Normal4; 130 | NormalBuffer = normalize(NormalBuffer); 131 | } 132 | 133 | #endif -------------------------------------------------------------------------------- /Shaders/PageTable/DrwaPageCommon.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f940db68a5ccca469840bc45cd135ca 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Terrain.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 466e942c101ddac45984e00369b8a1d6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Shaders/Terrain/FeedbackCommon.hlsl: -------------------------------------------------------------------------------- 1 | #ifndef VIRTUAL_TEXTURE_FEEDBACK_INCLUDED 2 | #define VIRTUAL_TEXTURE_FEEDBACK_INCLUDED 3 | 4 | //#include "VirtualTextureCommon.hlsl" 5 | #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 6 | 7 | #define UNITY_INSTANCING_ENABLED 8 | 9 | UNITY_INSTANCING_BUFFER_START(Terrain) 10 | UNITY_DEFINE_INSTANCED_PROP(float4, _TerrainPatchInstanceData) // float4(xBase, yBase, skipScale, ~) 11 | UNITY_INSTANCING_BUFFER_END(Terrain) 12 | 13 | #ifdef UNITY_INSTANCING_ENABLED 14 | float4 _TerrainHeightmapScale; // float4(hmScale.x, hmScale.y / (float)(kMaxHeight), hmScale.z, 0) 15 | float4 _TerrainHeightmapRecipSize; // float4(1.0f/width, 1.0f/height, 1.0f/(width-1), 1.0f/(height-1)) 16 | TEXTURE2D(_TerrainHeightmapTexture); 17 | SAMPLER(sampler_TerrainNormalmapTexture); 18 | #endif 19 | 20 | struct Attributes 21 | { 22 | float4 vertexOS : POSITION; 23 | float2 texcoord0 : TEXCOORD0; 24 | UNITY_VERTEX_INPUT_INSTANCE_ID 25 | }; 26 | 27 | struct Varyings 28 | { 29 | float4 vertexCS : SV_POSITION; 30 | float2 texcoord0 : TEXCOORD0; 31 | float2 texcoord1 : TEXCOORD1; 32 | }; 33 | 34 | int _VTMipCount; 35 | 36 | float4 _VTVolumeRect; 37 | 38 | // xy: page count 39 | // z: max mipmap level 40 | float4 _VTPageParams; 41 | 42 | // x: page size 43 | // y: vertual texture size 44 | // z: max mipmap level 45 | // w: mipmap level bias 46 | float4 _VTFeedbackParams; 47 | 48 | // x: padding size 49 | // y: center size 50 | // zw: 1 / tile count 51 | float4 _VTPageTileParams; 52 | 53 | #ifdef _ALPHATEST_ON 54 | TEXTURE2D(_TerrainHolesTexture); 55 | SAMPLER(sampler_TerrainHolesTexture); 56 | 57 | void ClipHoles(float2 uv) 58 | { 59 | float hole = SAMPLE_TEXTURE2D(_TerrainHolesTexture, sampler_TerrainHolesTexture, uv).r; 60 | clip(hole == 0.0f ? -1 : 1); 61 | } 62 | #endif 63 | 64 | Varyings FeedbackVert(Attributes input) 65 | { 66 | Varyings output; 67 | UNITY_SETUP_INSTANCE_ID(input); 68 | 69 | #if defined(UNITY_INSTANCING_ENABLED) 70 | float2 patchVertex = input.vertexOS.xy; 71 | float4 instanceData = UNITY_ACCESS_INSTANCED_PROP(Terrain, _TerrainPatchInstanceData); 72 | 73 | float2 sampleCoords = (patchVertex.xy + instanceData.xy) * instanceData.z; // (xy + float2(xBase,yBase)) * skipScale 74 | float height = UnpackHeightmap(_TerrainHeightmapTexture.Load(int3(sampleCoords, 0))); 75 | 76 | input.vertexOS.xz = sampleCoords * _TerrainHeightmapScale.xz; 77 | input.vertexOS.y = height * _TerrainHeightmapScale.y; 78 | 79 | input.texcoord0 = sampleCoords * _TerrainHeightmapRecipSize.zw; 80 | #endif 81 | 82 | VertexPositionInputs Attributes = GetVertexPositionInputs(input.vertexOS.xyz); 83 | output.vertexCS = Attributes.positionCS; 84 | float2 vertexWS = Attributes.positionWS.xz; 85 | //output.texcoord0 = (vertexWS + 256) * rcp(256); 86 | //output.texcoord0 = (vertexWS + 512) * rcp(1024); 87 | output.texcoord1 = sampleCoords * _TerrainHeightmapRecipSize.xy; 88 | output.texcoord0 = (vertexWS - _VTVolumeRect.xy) * rcp(_VTVolumeRect.zw); 89 | return output; 90 | } 91 | 92 | float ComputeMip(float2 UV) 93 | { 94 | float2 DX = ddx(UV); 95 | float2 DY = ddy(UV); 96 | float MaxSqr = max(dot(DX, DX), dot(DY, DY)); 97 | float MipLevel = 0.5 * log2(MaxSqr); 98 | return max(0, MipLevel); 99 | } 100 | 101 | float BoxMask(float2 A, float2 B, float2 Size) 102 | { 103 | return 1 - saturate(ceil(length(max(0, abs(A - B) - (Size * 0.5))))); 104 | } 105 | 106 | float3 Pack1212To888(float2 x) 107 | { 108 | // Pack 12:12 to 8:8:8 109 | #if 0 110 | uint2 x1212 = (uint2)(x * 4095); 111 | uint2 High = x1212 >> 8; 112 | uint2 Low = x1212 & 255; 113 | uint3 x888 = uint3( Low, High.x | (High.y << 4) ); 114 | return x888 / 255.0; 115 | #else 116 | float2 x1212 = floor( x * 4095 ); 117 | float2 High = floor( x1212 / 256 ); // x1212 >> 8 118 | float2 Low = x1212 - High * 256; // x1212 & 255 119 | float3 x888 = float3( Low, High.x + High.y * 16 ); 120 | return saturate( x888 / 255 ); 121 | #endif 122 | } 123 | 124 | float4 FeedbackFrag(Varyings input) : SV_Target 125 | { 126 | #ifdef _ALPHATEST_ON 127 | ClipHoles(input.texcoord1); 128 | #endif 129 | 130 | float mipLevel = clamp(ComputeMip(input.texcoord0 * _VTFeedbackParams.y) + _VTFeedbackParams.w * 0.5 - 0.25, 0, _VTMipCount); 131 | //float2 pageUV = floor(input.texcoord0 * _VTFeedbackParams.x) / 256; 132 | float2 pageUV = ceil(input.texcoord0 * _VTFeedbackParams.x) / _VTFeedbackParams.x; 133 | 134 | //return float4(pageUV, floor(mipLevel) / 255, 1); 135 | return float4(Pack1212To888(pageUV), floor(mipLevel) / 255); 136 | } 137 | 138 | #endif -------------------------------------------------------------------------------- /Shaders/Terrain/FeedbackCommon.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e23959ce0d963cd40b9d00f8ea0f8c6a 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLit.shader: -------------------------------------------------------------------------------- 1 | Shader "Landscape/TerrainLit" 2 | { 3 | Properties 4 | { 5 | [HideInInspector] [ToggleUI] _EnableHeightBlend("EnableHeightBlend", Float) = 0.0 6 | _HeightTransition("Height Transition", Range(0, 1.0)) = 0.0 7 | // Layer count is passed down to guide height-blend enable/disable, due 8 | // to the fact that heigh-based blend will be broken with multipass. 9 | [HideInInspector] [PerRendererData] _NumLayersCount ("Total Layer Count", Float) = 1.0 10 | 11 | // set by terrain engine 12 | [HideInInspector] _Control("Control (RGBA)", 2D) = "red" {} 13 | [HideInInspector] _Splat3("Layer 3 (A)", 2D) = "grey" {} 14 | [HideInInspector] _Splat2("Layer 2 (B)", 2D) = "grey" {} 15 | [HideInInspector] _Splat1("Layer 1 (G)", 2D) = "grey" {} 16 | [HideInInspector] _Splat0("Layer 0 (R)", 2D) = "grey" {} 17 | [HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {} 18 | [HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {} 19 | [HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {} 20 | [HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {} 21 | [HideInInspector] _Mask3("Mask 3 (A)", 2D) = "grey" {} 22 | [HideInInspector] _Mask2("Mask 2 (B)", 2D) = "grey" {} 23 | [HideInInspector] _Mask1("Mask 1 (G)", 2D) = "grey" {} 24 | [HideInInspector] _Mask0("Mask 0 (R)", 2D) = "grey" {} 25 | [HideInInspector][Gamma] _Metallic0("Metallic 0", Range(0.0, 1.0)) = 0.0 26 | [HideInInspector][Gamma] _Metallic1("Metallic 1", Range(0.0, 1.0)) = 0.0 27 | [HideInInspector][Gamma] _Metallic2("Metallic 2", Range(0.0, 1.0)) = 0.0 28 | [HideInInspector][Gamma] _Metallic3("Metallic 3", Range(0.0, 1.0)) = 0.0 29 | [HideInInspector] _Smoothness0("Smoothness 0", Range(0.0, 1.0)) = 0.5 30 | [HideInInspector] _Smoothness1("Smoothness 1", Range(0.0, 1.0)) = 0.5 31 | [HideInInspector] _Smoothness2("Smoothness 2", Range(0.0, 1.0)) = 0.5 32 | [HideInInspector] _Smoothness3("Smoothness 3", Range(0.0, 1.0)) = 0.5 33 | 34 | // used in fallback on old cards & base map 35 | [HideInInspector] _MainTex("BaseMap (RGB)", 2D) = "grey" {} 36 | [HideInInspector] _BaseColor("Main Color", Color) = (1,1,1,1) 37 | 38 | [HideInInspector] _TerrainHolesTexture("Holes Map (RGB)", 2D) = "white" {} 39 | 40 | [ToggleUI] _EnableInstancedPerPixelNormal("Enable Instanced per-pixel normal", Float) = 1.0 41 | } 42 | 43 | HLSLINCLUDE 44 | 45 | #pragma multi_compile_fragment __ _ALPHATEST_ON 46 | 47 | ENDHLSL 48 | 49 | SubShader 50 | { 51 | Tags { "Queue" = "Geometry-100" "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" "IgnoreProjector" = "False" "TerrainCompatible" = "True"} 52 | 53 | Pass 54 | { 55 | Name "ForwardLit" 56 | Tags { "LightMode" = "UniversalForward" } 57 | HLSLPROGRAM 58 | #pragma target 3.0 59 | 60 | #pragma vertex SplatmapVert 61 | #pragma fragment SplatmapFragment 62 | 63 | #define _METALLICSPECGLOSSMAP 1 64 | #define _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 1 65 | 66 | // ------------------------------------- 67 | // Universal Pipeline keywords 68 | #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN 69 | //#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS 70 | //#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS 71 | #pragma multi_compile_fragment _ _SHADOWS_SOFT 72 | //#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING 73 | //#pragma multi_compile _ SHADOWS_SHADOWMASK 74 | //#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION 75 | 76 | // ------------------------------------- 77 | // Unity defined keywords 78 | //#pragma multi_compile _ DIRLIGHTMAP_COMBINED 79 | //#pragma multi_compile _ LIGHTMAP_ON 80 | //#pragma multi_compile_fog 81 | #pragma multi_compile_instancing 82 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 83 | 84 | #pragma shader_feature_local_fragment _TERRAIN_BLEND_HEIGHT 85 | #pragma shader_feature_local _NORMALMAP 86 | #pragma shader_feature_local_fragment _MASKMAP 87 | // Sample normal in pixel shader when doing instancing 88 | #pragma shader_feature_local _TERRAIN_INSTANCED_PERPIXEL_NORMAL 89 | 90 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 91 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 92 | ENDHLSL 93 | } 94 | 95 | Pass 96 | { 97 | Name "ShadowCaster" 98 | Tags{"LightMode" = "ShadowCaster"} 99 | 100 | ZWrite On 101 | ColorMask 0 102 | 103 | HLSLPROGRAM 104 | #pragma target 2.0 105 | 106 | #pragma vertex ShadowPassVertex 107 | #pragma fragment ShadowPassFragment 108 | 109 | #pragma multi_compile_instancing 110 | #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW 111 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 112 | 113 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 114 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 115 | ENDHLSL 116 | } 117 | 118 | Pass 119 | { 120 | Name "DepthOnly" 121 | Tags{"LightMode" = "DepthOnly"} 122 | 123 | ZWrite On 124 | ColorMask 0 125 | 126 | HLSLPROGRAM 127 | #pragma target 2.0 128 | 129 | #pragma vertex DepthOnlyVertex 130 | #pragma fragment DepthOnlyFragment 131 | 132 | #pragma multi_compile_instancing 133 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 134 | 135 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 136 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 137 | ENDHLSL 138 | } 139 | 140 | Pass 141 | { 142 | Name "SceneSelectionPass" 143 | Tags { "LightMode" = "SceneSelectionPass" } 144 | 145 | HLSLPROGRAM 146 | #pragma target 2.0 147 | 148 | #pragma vertex DepthOnlyVertex 149 | #pragma fragment DepthOnlyFragment 150 | 151 | #pragma multi_compile_instancing 152 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 153 | 154 | #define SCENESELECTIONPASS 155 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 156 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 157 | ENDHLSL 158 | } 159 | 160 | //UsePass "Hidden/Nature/Terrain/Utilities/PICKING" 161 | } 162 | Dependency "AddPassShader" = "Landscape/TerrainLit_Add" 163 | //Dependency "BaseMapShader" = "Hidden/Universal Render Pipeline/Terrain/Lit (Base Pass)" 164 | //Dependency "BaseMapGenShader" = "Hidden/Universal Render Pipeline/Terrain/Lit (Basemap Gen)" 165 | 166 | CustomEditor "UnityEditor.Rendering.Universal.TerrainLitShaderGUI" 167 | 168 | //Fallback "Hidden/Universal Render Pipeline/FallbackError" 169 | } 170 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLit.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a5c8edbfb27e9bf4cb5010201278f04f 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | preprocessorOverride: 0 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLitAdd.shader: -------------------------------------------------------------------------------- 1 | Shader "Landscape/TerrainLit_Add" 2 | { 3 | Properties 4 | { 5 | // Layer count is passed down to guide height-blend enable/disable, due 6 | // to the fact that heigh-based blend will be broken with multipass. 7 | [HideInInspector] [PerRendererData] _NumLayersCount ("Total Layer Count", Float) = 1.0 8 | 9 | // set by terrain engine 10 | [HideInInspector] _Control("Control (RGBA)", 2D) = "red" {} 11 | [HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {} 12 | [HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {} 13 | [HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {} 14 | [HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {} 15 | [HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {} 16 | [HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {} 17 | [HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {} 18 | [HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {} 19 | [HideInInspector][Gamma] _Metallic0("Metallic 0", Range(0.0, 1.0)) = 0.0 20 | [HideInInspector][Gamma] _Metallic1("Metallic 1", Range(0.0, 1.0)) = 0.0 21 | [HideInInspector][Gamma] _Metallic2("Metallic 2", Range(0.0, 1.0)) = 0.0 22 | [HideInInspector][Gamma] _Metallic3("Metallic 3", Range(0.0, 1.0)) = 0.0 23 | [HideInInspector] _Mask3("Mask 3 (A)", 2D) = "grey" {} 24 | [HideInInspector] _Mask2("Mask 2 (B)", 2D) = "grey" {} 25 | [HideInInspector] _Mask1("Mask 1 (G)", 2D) = "grey" {} 26 | [HideInInspector] _Mask0("Mask 0 (R)", 2D) = "grey" {} 27 | [HideInInspector] _Smoothness0("Smoothness 0", Range(0.0, 1.0)) = 1.0 28 | [HideInInspector] _Smoothness1("Smoothness 1", Range(0.0, 1.0)) = 1.0 29 | [HideInInspector] _Smoothness2("Smoothness 2", Range(0.0, 1.0)) = 1.0 30 | [HideInInspector] _Smoothness3("Smoothness 3", Range(0.0, 1.0)) = 1.0 31 | 32 | // used in fallback on old cards & base map 33 | [HideInInspector] _BaseMap("BaseMap (RGB)", 2D) = "white" {} 34 | [HideInInspector] _BaseColor("Main Color", Color) = (1,1,1,1) 35 | 36 | [HideInInspector] _TerrainHolesTexture("Holes Map (RGB)", 2D) = "white" {} 37 | } 38 | 39 | HLSLINCLUDE 40 | 41 | #pragma multi_compile_fragment __ _ALPHATEST_ON 42 | 43 | ENDHLSL 44 | 45 | SubShader 46 | { 47 | Tags { "Queue" = "Geometry-99" "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" "IgnoreProjector" = "True"} 48 | 49 | Pass 50 | { 51 | Name "TerrainAddLit" 52 | Tags { "LightMode" = "UniversalForward" } 53 | Blend One One 54 | HLSLPROGRAM 55 | #pragma target 3.0 56 | 57 | #pragma vertex SplatmapVert 58 | #pragma fragment SplatmapFragment 59 | 60 | // ------------------------------------- 61 | // Universal Pipeline keywords 62 | #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN 63 | //#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS 64 | //#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS 65 | #pragma multi_compile_fragment _ _SHADOWS_SOFT 66 | //#pragma multi_compile _ LIGHTMAP_SHADOW_MIXING 67 | //#pragma multi_compile _ SHADOWS_SHADOWMASK 68 | //#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION 69 | 70 | // ------------------------------------- 71 | // Unity defined keywords 72 | //#pragma multi_compile _ DIRLIGHTMAP_COMBINED 73 | //#pragma multi_compile _ LIGHTMAP_ON 74 | //#pragma multi_compile_fog 75 | #pragma multi_compile_instancing 76 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 77 | 78 | #pragma shader_feature_local_fragment _TERRAIN_BLEND_HEIGHT 79 | #pragma shader_feature_local _NORMALMAP 80 | #pragma shader_feature_local_fragment _MASKMAP 81 | // Sample normal in pixel shader when doing instancing 82 | #pragma shader_feature_local _TERRAIN_INSTANCED_PERPIXEL_NORMAL 83 | #define TERRAIN_SPLAT_ADDPASS 84 | 85 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 86 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 87 | ENDHLSL 88 | } 89 | } 90 | Fallback "Hidden/Universal Render Pipeline/FallbackError" 91 | } 92 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLitAdd.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0cb8ab4c8d30a149a7b68f0546a1829 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | preprocessorOverride: 0 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLitInclude.hlsl.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e745c0098dd27664b8cac177ce0cc471 3 | timeCreated: 1488965025 4 | licenseType: Pro 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLit_VT.shader: -------------------------------------------------------------------------------- 1 | Shader "Landscape/TerrainLit_VT" 2 | { 3 | Properties 4 | { 5 | [HideInInspector] [ToggleUI] _EnableHeightBlend("EnableHeightBlend", Float) = 0.0 6 | _HeightTransition("Height Transition", Range(0, 1.0)) = 0.0 7 | // Layer count is passed down to guide height-blend enable/disable, due 8 | // to the fact that heigh-based blend will be broken with multipass. 9 | [HideInInspector] [PerRendererData] _NumLayersCount ("Total Layer Count", Float) = 1.0 10 | 11 | // set by terrain engine 12 | [HideInInspector] _Control("Control (RGBA)", 2D) = "red" {} 13 | [HideInInspector] _Splat3("Layer 3 (A)", 2D) = "grey" {} 14 | [HideInInspector] _Splat2("Layer 2 (B)", 2D) = "grey" {} 15 | [HideInInspector] _Splat1("Layer 1 (G)", 2D) = "grey" {} 16 | [HideInInspector] _Splat0("Layer 0 (R)", 2D) = "grey" {} 17 | [HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {} 18 | [HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {} 19 | [HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {} 20 | [HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {} 21 | [HideInInspector] _Mask3("Mask 3 (A)", 2D) = "grey" {} 22 | [HideInInspector] _Mask2("Mask 2 (B)", 2D) = "grey" {} 23 | [HideInInspector] _Mask1("Mask 1 (G)", 2D) = "grey" {} 24 | [HideInInspector] _Mask0("Mask 0 (R)", 2D) = "grey" {} 25 | [HideInInspector][Gamma] _Metallic0("Metallic 0", Range(0.0, 1.0)) = 0.0 26 | [HideInInspector][Gamma] _Metallic1("Metallic 1", Range(0.0, 1.0)) = 0.0 27 | [HideInInspector][Gamma] _Metallic2("Metallic 2", Range(0.0, 1.0)) = 0.0 28 | [HideInInspector][Gamma] _Metallic3("Metallic 3", Range(0.0, 1.0)) = 0.0 29 | [HideInInspector] _Smoothness0("Smoothness 0", Range(0.0, 1.0)) = 0.5 30 | [HideInInspector] _Smoothness1("Smoothness 1", Range(0.0, 1.0)) = 0.5 31 | [HideInInspector] _Smoothness2("Smoothness 2", Range(0.0, 1.0)) = 0.5 32 | [HideInInspector] _Smoothness3("Smoothness 3", Range(0.0, 1.0)) = 0.5 33 | 34 | // used in fallback on old cards & base map 35 | [HideInInspector] _MainTex("BaseMap (RGB)", 2D) = "grey" {} 36 | [HideInInspector] _BaseColor("Main Color", Color) = (1,1,1,1) 37 | 38 | [HideInInspector] _TerrainHolesTexture("Holes Map (RGB)", 2D) = "white" {} 39 | 40 | [ToggleUI] _EnableInstancedPerPixelNormal("Enable Instanced per-pixel normal", Float) = 1.0 41 | } 42 | 43 | HLSLINCLUDE 44 | #pragma multi_compile __ _ALPHATEST_ON 45 | ENDHLSL 46 | 47 | SubShader 48 | { 49 | Tags { "Queue" = "Geometry-100" "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "False" "TerrainCompatible" = "True"} 50 | 51 | Pass 52 | { 53 | Tags { "LightMode" = "VTFeedback" } 54 | 55 | HLSLPROGRAM 56 | #pragma target 3.0 57 | #pragma multi_compile_instancing 58 | #pragma enable_d3d11_debug_symbols 59 | #pragma shader_feature_local _TERRAIN_INSTANCED_PERPIXEL_NORMAL 60 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 61 | 62 | #include "FeedbackCommon.hlsl" 63 | #pragma vertex FeedbackVert 64 | #pragma fragment FeedbackFrag 65 | ENDHLSL 66 | } 67 | 68 | Pass 69 | { 70 | Name "ForwardLit" 71 | Tags { "LightMode" = "UniversalForward" } 72 | 73 | HLSLPROGRAM 74 | #pragma target 3.0 75 | 76 | #pragma vertex SplatmapVert 77 | #pragma fragment SplatmapFragment 78 | 79 | #define _METALLICSPECGLOSSMAP 1 80 | #define _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 1 81 | #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _SHADOWS_SOFT 82 | 83 | #pragma multi_compile_instancing 84 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 85 | 86 | #define _NORMALMAP 87 | #pragma shader_feature_local _MASKMAP 88 | #pragma shader_feature_local _TERRAIN_INSTANCED_PERPIXEL_NORMAL 89 | 90 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 91 | #include "TerrainLitInclude.hlsl" 92 | ENDHLSL 93 | } 94 | 95 | Pass 96 | { 97 | Name "ShadowCaster" 98 | Tags{"LightMode" = "ShadowCaster"} 99 | 100 | ZWrite On 101 | 102 | HLSLPROGRAM 103 | #pragma target 3.0 104 | //#pragma prefer_hlslcc gles 105 | //#pragma exclude_renderers d3d11_9x 106 | 107 | #pragma vertex ShadowPassVertex 108 | #pragma fragment ShadowPassFragment 109 | 110 | #pragma multi_compile_instancing 111 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 112 | 113 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 114 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 115 | ENDHLSL 116 | } 117 | 118 | Pass 119 | { 120 | Name "DepthOnly" 121 | Tags{"LightMode" = "DepthOnly"} 122 | 123 | ZWrite On 124 | ColorMask 0 125 | 126 | HLSLPROGRAM 127 | #pragma target 3.0 128 | //#pragma prefer_hlslcc gles 129 | //#pragma exclude_renderers d3d11_9x 130 | 131 | #pragma vertex DepthOnlyVertex 132 | #pragma fragment DepthOnlyFragment 133 | 134 | #pragma multi_compile_instancing 135 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 136 | 137 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 138 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 139 | ENDHLSL 140 | } 141 | 142 | Pass 143 | { 144 | Name "SceneSelectionPass" 145 | Tags { "LightMode" = "SceneSelectionPass" } 146 | 147 | HLSLPROGRAM 148 | #pragma target 2.0 149 | //#pragma prefer_hlslcc gles 150 | //#pragma exclude_renderers d3d11_9x 151 | 152 | #pragma vertex DepthOnlyVertex 153 | #pragma fragment DepthOnlyFragment 154 | 155 | #pragma multi_compile_instancing 156 | #pragma instancing_options assumeuniformscaling nomatrices nolightprobe nolightmap 157 | 158 | #define SCENESELECTIONPASS 159 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitInput.hlsl" 160 | #include "Packages/com.unity.render-pipelines.universal/Shaders/Terrain/TerrainLitPasses.hlsl" 161 | ENDHLSL 162 | } 163 | 164 | //UsePass "Hidden/Nature/Terrain/Utilities/PICKING" 165 | } 166 | 167 | CustomEditor "UnityEditor.Rendering.Universal.TerrainLitShaderGUI" 168 | 169 | //Fallback "Hidden/Universal Render Pipeline/FallbackError" 170 | } 171 | -------------------------------------------------------------------------------- /Shaders/Terrain/TerrainLit_VT.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 04691e96727abdd4ebed0762df75cc74 3 | ShaderImporter: 4 | externalObjects: {} 5 | defaultTextures: [] 6 | nonModifiableTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.infinity.virtual-texture", 3 | "description": "Runtime VirtualTexture for UnityTerrain in Universal Render Pipeline(URP).", 4 | "version": "1.0.0", 5 | "unity": "2021.1", 6 | "unityRelease": "0a8", 7 | "displayName": "Infinity Texture", 8 | "dependencies": { 9 | "com.unity.burst": "1.6.5", 10 | "com.unity.mathematics": "1.2.6" 11 | }, 12 | "type": "library" 13 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3015cad1d53523b46aa2222c6f5936a0 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------