├── Editor
├── MobileNeRFScene.cs
├── MobileNeRFImporter.cs
├── Doji.MobileNeRF.asmdef.meta
├── Mlp.cs.meta
├── ShaderTemplate.cs.meta
├── MobileNeRFImporter.cs.meta
├── MobileNeRFScene.cs.meta
├── ObjImportProcessor.cs.meta
├── PNGImportProcessor.cs.meta
├── WebRequestAsyncUtility.cs.meta
├── Doji.MobileNeRF.asmdef
├── Mlp.cs
├── PNGImportProcessor.cs
├── ObjImportProcessor.cs
├── ShaderTemplate.cs
└── WebRequestAsyncUtility.cs
├── CHANGELOG.md.meta
├── LICENSE.txt.meta
├── readme.md.meta
├── package.json.meta
├── Editor.meta
├── Third Party Notices.txt.meta
├── package.json
├── CHANGELOG.md
├── Third Party Notices.txt
├── LICENSE.txt
├── .gitignore
└── readme.md
/Editor/MobileNeRFScene.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julienkay/MobileNeRF-Unity-Viewer/HEAD/Editor/MobileNeRFScene.cs
--------------------------------------------------------------------------------
/Editor/MobileNeRFImporter.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/julienkay/MobileNeRF-Unity-Viewer/HEAD/Editor/MobileNeRFImporter.cs
--------------------------------------------------------------------------------
/CHANGELOG.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a1cc125fe711e9e46850930d4711b9b2
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/LICENSE.txt.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cc0c970179e4cd6438b134f015e67f3f
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/readme.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8c704b83110fb5349aed26629a4d15d7
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/package.json.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19b9c07104ad4374196c8eb43a1317c1
3 | PackageManifestImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1c7358ccaf80ed04482be4e74ea60702
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Third Party Notices.txt.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 93c13af626350cf4792e0477a1d7c9df
3 | TextScriptImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor/Doji.MobileNeRF.asmdef.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 648fc805c72ae7c49bf0e39c0e9f8195
3 | AssemblyDefinitionImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/Editor/Mlp.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4cbeaa8c68a3b834f88cabe1efecd6c3
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/ShaderTemplate.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1dc0edd415f24e747abc0bdc1c5a45a2
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/MobileNeRFImporter.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b10acd302c8803d48babe8c612d26f80
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/MobileNeRFScene.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a0d80641e9f59c94491d5bf137c38e5a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/ObjImportProcessor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4129a0e7f3ee6484b8e9d548046015ae
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/PNGImportProcessor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d5e5cd8c1458ed44aba0c9348b36861
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Editor/WebRequestAsyncUtility.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b257fece027b7a94a87a6ec25e32a6d6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "com.doji.mobilenerf",
3 | "version": "1.1.0",
4 | "displayName": "MobileNeRF",
5 | "description": "An unofficial Unity port of the MobileNeRF viewer.",
6 | "dependencies":
7 | {
8 | "com.unity.nuget.newtonsoft-json": "3.0.2"
9 | },
10 | "author":
11 | {
12 | "name": "Doji Technologies",
13 | "email": "support@doji-tech.com",
14 | "url": "https://www.doji-tech.com/"
15 | }
16 | }
--------------------------------------------------------------------------------
/Editor/Doji.MobileNeRF.asmdef:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Doji.MobileNeRF",
3 | "rootNamespace": "",
4 | "references": [],
5 | "includePlatforms": [
6 | "Editor"
7 | ],
8 | "excludePlatforms": [],
9 | "allowUnsafeCode": false,
10 | "overrideReferences": false,
11 | "precompiledReferences": [],
12 | "autoReferenced": true,
13 | "defineConstraints": [],
14 | "versionDefines": [],
15 | "noEngineReferences": false
16 | }
--------------------------------------------------------------------------------
/Editor/Mlp.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | public partial class Mlp {
4 | [JsonProperty("0_weights")]
5 | public double[][] _0Weights;
6 |
7 | [JsonProperty("1_weights")]
8 | public double[][] _1Weights;
9 |
10 | [JsonProperty("2_weights")]
11 | public double[][] _2Weights;
12 |
13 | [JsonProperty("0_bias")]
14 | public double[] _0Bias;
15 |
16 | [JsonProperty("1_bias")]
17 | public double[] _1Bias;
18 |
19 | [JsonProperty("2_bias")]
20 | public double[] _2Bias;
21 |
22 | [JsonProperty("obj_num")]
23 | public int ObjNum;
24 | }
--------------------------------------------------------------------------------
/Editor/PNGImportProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.Text.RegularExpressions;
2 | using UnityEditor;
3 | using UnityEngine;
4 |
5 | ///
6 | /// Configures MobileNeRF feature textures to have the correct import settings.
7 | ///
8 | public class PNGImportProcessor : AssetPostprocessor {
9 |
10 | private void OnPreprocessTexture() {
11 | Regex featureTexturePattern = new Regex(@"shape[0-9].pngfeat[0-9]\.png");
12 | if (featureTexturePattern.IsMatch(assetPath)) {
13 | TextureImporter textureImporter = assetImporter as TextureImporter;
14 | textureImporter.maxTextureSize = 4096;
15 | textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
16 | textureImporter.sRGBTexture = false;
17 | textureImporter.filterMode = FilterMode.Point;
18 | textureImporter.mipmapEnabled = false;
19 | textureImporter.alphaIsTransparency = false;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 | ## [1.1.0] - 2023-05-28
9 |
10 | ### Changed
11 |
12 | - Optimized network evaluation shader code (thanks to [@mrxz](https://github.com/mrxz))
13 |
14 | ## [1.0.1] - 2023-04-07
15 |
16 | ### Changed
17 |
18 | - Remove Unity version restriction from package
19 |
20 | ## [1.0.0] - 2023-04-07
21 |
22 | ### Added
23 |
24 | - Add support for 'Linear' color space
25 |
26 | ### Changed
27 |
28 | - Convert to package format
29 |
30 | ## [x.x.x] - 2022-09-01
31 |
32 | ### Added
33 |
34 | - Add support for importing your own trained datasets
35 |
36 | ## [x.x.x] - 2022-08-24
37 |
38 | ### Added
39 |
40 | - Add support for Single Pass Instanced rendering
41 |
42 | ## [x.x.x] - 2022-08-23
43 |
44 | ### Added
45 |
46 | - Add support for shadows
47 |
48 | ## [x.x.x] - 2022-08-07
49 | Initial Release
--------------------------------------------------------------------------------
/Editor/ObjImportProcessor.cs:
--------------------------------------------------------------------------------
1 | using System.Text.RegularExpressions;
2 | using UnityEditor;
3 |
4 | ///
5 | /// Custom import settings for MobileNeRF OBJs.
6 | ///
7 | public class ObjImportProcessor : AssetPostprocessor {
8 | private void OnPreprocessModel() {
9 | Regex objPattern = new Regex(@"shape.*\.obj");
10 |
11 | if (objPattern.IsMatch(assetPath)) {
12 | ModelImporter modelImporter = assetImporter as ModelImporter;
13 | // MobileNeRFs don't use normals, so we disable trying to read them when importing .obj files
14 | // This is not strictly necessary, but prevents the warnings showing in the console.
15 | modelImporter.importTangents = ModelImporterTangents.None;
16 | modelImporter.importNormals = ModelImporterNormals.None;
17 |
18 | // one material per shape (each has individual feature textures)
19 | modelImporter.materialLocation = ModelImporterMaterialLocation.External;
20 | modelImporter.materialName = ModelImporterMaterialName.BasedOnModelNameAndMaterialName;
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/Third Party Notices.txt:
--------------------------------------------------------------------------------
1 | This project uses third-party libraries or other resources that may
2 | be distributed under licenses different than the project itself.
3 |
4 | In the event that we accidentally failed to list a required notice,
5 | please bring it to our attention.
6 |
7 | The attached notices are provided for information only.
8 |
9 | MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures
10 | ---------------------------------------------------------------------------------------------------------------------
11 |
12 | Licensed under the Apache License, Version 2.0 (the "License");
13 | you may not use this file except in compliance with the License.
14 | You may obtain a copy of the License at
15 |
16 | http://www.apache.org/licenses/LICENSE-2.0
17 |
18 | Unless required by applicable law or agreed to in writing, software
19 | distributed under the License is distributed on an "AS IS" BASIS,
20 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 | See the License for the specific language governing permissions and
22 | limitations under the License.
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Julien Kipp
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Uu]ser[Ss]ettings/
12 |
13 | # MemoryCaptures can get excessive in size.
14 | # They also could contain extremely sensitive data
15 | /[Mm]emoryCaptures/
16 |
17 | # Asset meta data should only be ignored when the corresponding asset is also ignored
18 | !/[Aa]ssets/**/*.meta
19 |
20 | # Uncomment this line if you wish to ignore the asset store tools plugin
21 | # /[Aa]ssets/AssetStoreTools*
22 |
23 | # Autogenerated Jetbrains Rider plugin
24 | /[Aa]ssets/Plugins/Editor/JetBrains*
25 |
26 | # Visual Studio cache directory
27 | .vs/
28 |
29 | # Gradle cache directory
30 | .gradle/
31 |
32 | # Autogenerated VS/MD/Consulo solution and project files
33 | ExportedObj/
34 | .consulo/
35 | *.csproj
36 | *.unityproj
37 | *.sln
38 | *.suo
39 | *.tmp
40 | *.user
41 | *.userprefs
42 | *.pidb
43 | *.booproj
44 | *.svd
45 | *.pdb
46 | *.mdb
47 | *.opendb
48 | *.VC.db
49 | *.editorconfig
50 | *.vsconfig
51 |
52 | # Unity3D generated meta files
53 | *.pidb.meta
54 | *.pdb.meta
55 | *.mdb.meta
56 |
57 | # Unity3D generated file on crash reports
58 | sysinfo.txt
59 |
60 | # Builds
61 | *.apk
62 | *.aab
63 | *.unitypackage
64 |
65 | # Crashlytics generated file
66 | crashlytics-build.properties
67 |
68 | # Packed Addressables
69 | /[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
70 |
71 | # Temporary auto-generated Android Assets
72 | /[Aa]ssets/[Ss]treamingAssets/aa.meta
73 | /[Aa]ssets/[Ss]treamingAssets/aa/*
74 |
75 |
76 | ----------------------------------------------------
77 |
78 |
79 | # ============ #
80 | # OS generated #
81 | # ============ #
82 | .DS_Store
83 | .DS_Store?
84 | ._*
85 | .Spotlight-V100
86 | .Trashes
87 | ehthumbs.db
88 | Thumbs.db
89 |
90 |
91 | # ====== #
92 | # custom #
93 | # ====== #
94 | /[Aa]ssets/[Mm]obileNeRF Data/
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # MobileNeRF Unity Viewer
2 |
3 | 
4 |
5 | This repository contains the source code for a Unity port of the web viewer from the paper [MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures](https://mobile-nerf.github.io/)[^1]
6 |
7 | *Please note, that this is an unofficial port. I am not affiliated with the original authors or their institution.*
8 |
9 | ## Usage
10 |
11 | ### Installation
12 |
13 | Go to the [releases section](https://github.com/julienkay/MobileNeRF-Unity-Viewer/releases/latest), download the Unity Package, and import it into any Unity project. This is a 'Hybrid Package' that will install into your project as a local package.
14 |
15 | ##### Alternatives
16 |
17 |
18 | UPM Package via OpenUPM
19 |
20 | In `Edit -> Project Settings -> Package Manager`, add a new scoped registry:
21 |
22 | Name: Doji
23 | URL: https://package.openupm.com
24 | Scope(s): com.doji
25 |
26 | In the Package Manager install 'com.doji.mobilenerf either by name or via `Package Manager -> My Registries`
27 |
28 |
29 |
30 | UPM Package via Git URL
31 |
32 | In `Package Manager -> Add package from git URL...` paste `https://github.com/julienkay/MobileNeRF-Unity-Viewer.git` [as described here](https://docs.unity3d.com/Manual/upm-ui-giturl)
33 |
34 |
35 | ### Importing sample scenes
36 |
37 | After succesful installation, you can use the menu `MobileNeRF -> Asset Downloads` to download any of the sample scenes available.
38 | In each scene folder there will be a convenient prefab, that you can then drag into the scene and you're good to go.
39 |
40 | ### Updating
41 |
42 | Since the initial release a small number of features have been added to the automatic shader generation code.
43 | That means, that if you have already downloaded some scenes before, you'll have to regenerate the source files by going to `MobileNeRF -> Asset Downloads` again.
44 | (This will not actually redownload Assets unless necessary, so this shouldn't take too long)
45 |
46 | ### Importing self-trained scenes
47 |
48 | If you have successfully trained your own MobileNeRF scenes using the [official code release](https://github.com/google-research/jax3d/tree/main/jax3d/projects/mobilenerf) and want to render them in Unity, you can use the menu *MobileNeRF -> Import from disk*.
49 | This lets you choose a folder that should contain all the output files of your training process.
50 |
51 | More specifically, the following assets are required:
52 | - multiple shapes as OBJ files with naming convention: shapeX.obj
53 | - multiple PNG files with naming convention: shapeX.pngfeatZ.png (where Z goes from 0 to 1, so 2 .pngs per shape)
54 | - The weights of the MLP in a file called mlp.json
55 |
56 | ## Details
57 |
58 | The project was created with Unity 2021.3 LTS using the Built-in Render Pipeline.
59 |
60 | The biggest deviation from the official viewer is, that this project doesn't use Deferred Rendering, but uses Forward Rendering instead.
61 | This has certain implications on performance.
62 | While the MobileNeRF representation itself greatly reduces the cost to render NeRFs, it still requires evaluating a small, view-dependent MLP (Multi Layer Perceptron) per fragment. Whenever the bottleneck is in the fragment shader, Deferred Rendering has obvious advantages, as each pixel only needs to run a single fragment shader.
63 |
64 | Forward Rendering however gives us MSAA, which is important for VR use cases. Additionally, in VR the image has to be rendered twice, once for each eye, with a fairly large resolution. The larger the G-buffer, the smaller the benefit of Deferred Rendering. Still, MobileNeRFs mesh representations have a fairly large poly count which works against us using Forward Rendering here.
65 |
66 | Some things to possibly look into:
67 | * Forward Rendering, but do a Depth Prepass to reduce overdraw (might require URP, see [here](https://forum.unity.com/threads/need-clarification-on-urps-use-of-the-depth-prepass.1004577/) and [here](https://gist.github.com/aras-p/5e3aa6f81c543ca74e3ae296c72ffcaf))
68 | * Implement Deferred Rendering and compare performance in various scenarios
69 |
70 | ## Known Issues
71 |
72 | - Does not work well with MSAA. For now, I recommend turning MSAA off in `Project Settings -> Quality -> Anti Aliasing`
73 |
74 | ## References
75 |
76 | Thanks to
77 |
78 | - [@mrxz](https://github.com/mrxz) for providing some major performance optimizations as part of his [WebXR port](https://github.com/mrxz/mobilenerf-viewer-webxr)
79 |
80 | Other projects exploring NeRFs and related techniques in Unity:
81 | - [SNeRG (Sparse Neural Radiance Grids)](https://github.com/julienkay/SNeRG-Unity-Viewer)
82 | - [MERF (Memory Efficient Radiance Fields)](https://github.com/julienkay/MERF-Unity-Viewer)
83 |
84 | [^1]: [Zhiqin Chen and Thomas Funkhouser and Peter Hedman and Andrea Tagliasacchi. MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Rendering on Mobile Architectures. arXiv preprint arXiv:2208.00277, 2022](https://mobile-nerf.github.io/)
85 |
--------------------------------------------------------------------------------
/Editor/ShaderTemplate.cs:
--------------------------------------------------------------------------------
1 | public static class ViewDependenceNetworkShader {
2 | public const string Template = @"Shader ""MobileNeRF/ViewDependenceNetworkShader/OBJECT_NAME"" {
3 | Properties {
4 | tDiffuse0x (""Diffuse Texture 0"", 2D) = ""white"" {}
5 | tDiffuse1x (""Diffuse Texture 1"", 2D) = ""white"" {}
6 | }
7 |
8 | CGINCLUDE
9 | #include ""UnityCG.cginc""
10 |
11 | struct appdata {
12 | float4 vertex : POSITION;
13 | float2 uv : TEXCOORD0;
14 | UNITY_VERTEX_INPUT_INSTANCE_ID
15 | };
16 |
17 | struct v2f {
18 | float2 uv : TEXCOORD0;
19 | float4 vertex : SV_POSITION;
20 | float3 rayDirection : TEXCOORD1;
21 | UNITY_VERTEX_OUTPUT_STEREO
22 | };
23 |
24 | v2f vert(appdata v) {
25 | v2f o;
26 |
27 | UNITY_SETUP_INSTANCE_ID(v);
28 | UNITY_INITIALIZE_OUTPUT(v2f, o);
29 | UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
30 |
31 | o.vertex = UnityObjectToClipPos(v.vertex);
32 | o.uv = v.uv;
33 | o.rayDirection = -WorldSpaceViewDir(v.vertex);
34 | AXIS_SWIZZLE
35 |
36 | return o;
37 | }
38 |
39 | sampler2D tDiffuse0x;
40 | sampler2D tDiffuse1x;
41 |
42 | half3 evaluateNetwork(fixed4 f0, fixed4 f1, fixed4 viewdir) {
43 | float4x4 intermediate_one = { BIAS_LIST_ZERO };
44 | intermediate_one += f0.r * float4x4(__W0_0__)
45 | + f0.g * float4x4(__W0_1__)
46 | + f0.b * float4x4(__W0_2__)
47 | + f0.a * float4x4(__W0_3__)
48 | + f1.r * float4x4(__W0_4__)
49 | + f1.g * float4x4(__W0_5__)
50 | + f1.b * float4x4(__W0_6__)
51 | + f1.a * float4x4(__W0_7__)
52 | + viewdir.r * float4x4(__W0_8__)
53 | + viewdir.g * float4x4(__W0_9__)
54 | + viewdir.b * float4x4(__W0_10__);
55 | intermediate_one[0] = max(intermediate_one[0], 0.0);
56 | intermediate_one[1] = max(intermediate_one[1], 0.0);
57 | intermediate_one[2] = max(intermediate_one[2], 0.0);
58 | intermediate_one[3] = max(intermediate_one[3], 0.0);
59 | float4x4 intermediate_two = float4x4(
60 | BIAS_LIST_ONE
61 | );
62 | intermediate_two += intermediate_one[0][0] * float4x4(__W1_0__)
63 | + intermediate_one[0][1] * float4x4(__W1_1__)
64 | + intermediate_one[0][2] * float4x4(__W1_2__)
65 | + intermediate_one[0][3] * float4x4(__W1_3__)
66 | + intermediate_one[1][0] * float4x4(__W1_4__)
67 | + intermediate_one[1][1] * float4x4(__W1_5__)
68 | + intermediate_one[1][2] * float4x4(__W1_6__)
69 | + intermediate_one[1][3] * float4x4(__W1_7__)
70 | + intermediate_one[2][0] * float4x4(__W1_8__)
71 | + intermediate_one[2][1] * float4x4(__W1_9__)
72 | + intermediate_one[2][2] * float4x4(__W1_10__)
73 | + intermediate_one[2][3] * float4x4(__W1_11__)
74 | + intermediate_one[3][0] * float4x4(__W1_12__)
75 | + intermediate_one[3][1] * float4x4(__W1_13__)
76 | + intermediate_one[3][2] * float4x4(__W1_14__)
77 | + intermediate_one[3][3] * float4x4(__W1_15__);
78 | intermediate_two[0] = max(intermediate_two[0], 0.0);
79 | intermediate_two[1] = max(intermediate_two[1], 0.0);
80 | intermediate_two[2] = max(intermediate_two[2], 0.0);
81 | intermediate_two[3] = max(intermediate_two[3], 0.0);
82 | float3 result = float3(
83 | BIAS_LIST_TWO
84 | );
85 | result += intermediate_two[0][0] * float3(__W2_0__)
86 | + intermediate_two[0][1] * float3(__W2_1__)
87 | + intermediate_two[0][2] * float3(__W2_2__)
88 | + intermediate_two[0][3] * float3(__W2_3__)
89 | + intermediate_two[1][0] * float3(__W2_4__)
90 | + intermediate_two[1][1] * float3(__W2_5__)
91 | + intermediate_two[1][2] * float3(__W2_6__)
92 | + intermediate_two[1][3] * float3(__W2_7__)
93 | + intermediate_two[2][0] * float3(__W2_8__)
94 | + intermediate_two[2][1] * float3(__W2_9__)
95 | + intermediate_two[2][2] * float3(__W2_10__)
96 | + intermediate_two[2][3] * float3(__W2_11__)
97 | + intermediate_two[3][0] * float3(__W2_12__)
98 | + intermediate_two[3][1] * float3(__W2_13__)
99 | + intermediate_two[3][2] * float3(__W2_14__)
100 | + intermediate_two[3][3] * float3(__W2_15__);
101 | result = 1.0 / (1.0 + exp(-result));
102 | return result*viewdir.a+(1.0-viewdir.a);
103 | }
104 | ENDCG
105 |
106 | SubShader {
107 | Cull Off
108 | ZTest LEqual
109 |
110 | Pass {
111 | CGPROGRAM
112 |
113 | #pragma vertex vert
114 | #pragma fragment frag
115 |
116 | fixed4 frag(v2f i) : SV_Target {
117 | fixed4 diffuse0 = tex2D( tDiffuse0x, i.uv );
118 | if (diffuse0.r == 0.0) discard;
119 | fixed4 diffuse1 = tex2D( tDiffuse1x, i.uv );
120 | fixed4 rayDir = fixed4(normalize(i.rayDirection), 1.0);
121 |
122 | // normalize range to [-1, 1]
123 | diffuse0.a = diffuse0.a * 2.0 - 1.0;
124 | diffuse1.a = diffuse1.a * 2.0 - 1.0;
125 |
126 | fixed4 fragColor;
127 | fragColor.rgb = evaluateNetwork(diffuse0,diffuse1,rayDir);
128 | fragColor.a = 1.0;
129 |
130 | #if(!UNITY_COLORSPACE_GAMMA)
131 | fragColor.rgb = GammaToLinearSpace(fragColor.rgb);
132 | #endif
133 |
134 | return fragColor;
135 | }
136 | ENDCG
137 | }
138 |
139 | // ------------------------------------------------------------------
140 | // Shadow rendering pass
141 | Pass {
142 | Tags {""LightMode"" = ""ShadowCaster""}
143 |
144 | CGPROGRAM
145 |
146 | #pragma vertex vert
147 | #pragma fragment fragShadowCaster
148 | #pragma multi_compile_shadowcaster
149 |
150 | fixed4 fragShadowCaster(v2f i) : SV_Target{
151 | fixed4 diffuse0 = tex2D(tDiffuse0x, i.uv);
152 | if (diffuse0.r == 0.0) discard;
153 | return 0;
154 | }
155 | ENDCG
156 | }
157 | }
158 | }";
159 | }
160 |
--------------------------------------------------------------------------------
/Editor/WebRequestAsyncUtility.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using Newtonsoft.Json;
3 | using UnityEngine.Networking;
4 | using System;
5 | using System.Threading.Tasks;
6 | using System.Text;
7 |
8 | public enum HTTPVerb { GET, POST };
9 |
10 | public static class WebRequestAsyncUtility {
11 |
12 | public static class WebRequestAsync {
13 |
14 | ///
15 | /// Performs a WebRequest with the given URL. The response is expected to be a JSON serialized
16 | /// object of type and is automatically being deserialized and returned.
17 | ///
18 | /// the type that this web request returns.
19 | public static async Task SendWebRequestAsync(string url, HTTPVerb verb = HTTPVerb.GET, string postData = null, params Tuple[] requestHeaders) {
20 | UnityWebRequest wr = GetRequest(url, verb, postData, requestHeaders);
21 | if (wr == null) {
22 | return default;
23 | }
24 |
25 | try {
26 | var asyncOp = wr.SendWebRequest();
27 | while (!asyncOp.webRequest.isDone) {
28 | await Task.Yield();
29 | }
30 |
31 | switch (asyncOp.webRequest.result) {
32 | case UnityWebRequest.Result.InProgress:
33 | break;
34 | case UnityWebRequest.Result.Success:
35 | return JsonConvert.DeserializeObject(asyncOp.webRequest.downloadHandler.text);
36 | case UnityWebRequest.Result.ConnectionError:
37 | case UnityWebRequest.Result.ProtocolError:
38 | case UnityWebRequest.Result.DataProcessingError:
39 | Debug.LogError($"{asyncOp.webRequest.result}: {asyncOp.webRequest.error}\nURL: {asyncOp.webRequest.url}");
40 | Debug.LogError($"{asyncOp.webRequest.downloadHandler.text}");
41 | break;
42 | default:
43 | break;
44 | }
45 |
46 | } catch (Exception e) {
47 | Debug.LogError(e);
48 | } finally {
49 | wr.Dispose();
50 | }
51 | return default;
52 | }
53 | }
54 |
55 | ///
56 | /// Simple WebRequest without JSON parsing. Returns plain text.
57 | ///
58 | public class WebRequestSimpleAsync {
59 |
60 | public static async Task SendWebRequestAsync(string url, HTTPVerb verb = HTTPVerb.GET, string postData = null, params Tuple[] requestHeaders) {
61 | UnityWebRequest wr = GetRequest(url, verb, postData, requestHeaders);
62 | if (wr == null) {
63 | return default;
64 | }
65 |
66 | try {
67 | var asyncOp = wr.SendWebRequest();
68 | while (!asyncOp.webRequest.isDone) {
69 | await Task.Yield();
70 | }
71 |
72 | switch (asyncOp.webRequest.result) {
73 | case UnityWebRequest.Result.InProgress:
74 | break;
75 | case UnityWebRequest.Result.Success:
76 | return asyncOp.webRequest.downloadHandler.text;
77 | case UnityWebRequest.Result.ConnectionError:
78 | case UnityWebRequest.Result.ProtocolError:
79 | case UnityWebRequest.Result.DataProcessingError:
80 | Debug.LogError($"{asyncOp.webRequest.result}: {asyncOp.webRequest.error}\nURL: {asyncOp.webRequest.url}");
81 | Debug.LogError($"{asyncOp.webRequest.downloadHandler.text}");
82 | break;
83 | default:
84 | break;
85 | }
86 |
87 | } catch (Exception e) {
88 | Debug.LogError(e);
89 | } finally {
90 | wr.Dispose();
91 | }
92 | return default;
93 | }
94 | }
95 |
96 | ///
97 | /// WebRequest for binary data.
98 | ///
99 | public class WebRequestBinaryAsync {
100 |
101 | public static async Task SendWebRequestAsync(string url, HTTPVerb verb = HTTPVerb.GET, string postData = null, params Tuple[] requestHeaders) {
102 | UnityWebRequest wr = GetRequest(url, verb, postData, requestHeaders);
103 | if (wr == null) {
104 | return default;
105 | }
106 |
107 | try {
108 | var asyncOp = wr.SendWebRequest();
109 | while (!asyncOp.webRequest.isDone) {
110 | await Task.Yield();
111 | }
112 |
113 | switch (asyncOp.webRequest.result) {
114 | case UnityWebRequest.Result.InProgress:
115 | break;
116 | case UnityWebRequest.Result.Success:
117 | return asyncOp.webRequest.downloadHandler.data;
118 | case UnityWebRequest.Result.ConnectionError:
119 | case UnityWebRequest.Result.ProtocolError:
120 | case UnityWebRequest.Result.DataProcessingError:
121 | Debug.LogError($"{asyncOp.webRequest.result}: {asyncOp.webRequest.error}\nURL: {asyncOp.webRequest.url}");
122 | Debug.LogError($"{asyncOp.webRequest.downloadHandler.text}");
123 | break;
124 | default:
125 | break;
126 | }
127 |
128 | } catch (Exception e) {
129 | Debug.LogError(e);
130 | } finally {
131 | wr.Dispose();
132 | }
133 | return default;
134 | }
135 | }
136 |
137 | private static UnityWebRequest GetRequest(string url, HTTPVerb verb, string postData, params Tuple[] requestHeaders) {
138 | UnityWebRequest webRequest;
139 |
140 | switch (verb) {
141 | case HTTPVerb.GET:
142 | webRequest = UnityWebRequest.Get(url);
143 | break;
144 | case HTTPVerb.POST:
145 | #if UNITY_2022_2_OR_NEWER
146 | webRequest = UnityWebRequest.PostWwwForm(url, postData);
147 | #else
148 | webRequest = UnityWebRequest.Post(url, postData);
149 | #endif
150 | byte[] rawBody = Encoding.UTF8.GetBytes(postData);
151 | webRequest.uploadHandler = new UploadHandlerRaw(rawBody);
152 | webRequest.downloadHandler = new DownloadHandlerBuffer();
153 | webRequest.SetRequestHeader("Content-Type", "application/json");
154 | break;
155 | default:
156 | Debug.LogError("Invalid HTTP request method.");
157 | return null;
158 | }
159 |
160 | // set optional headers
161 | if (requestHeaders != null) {
162 | foreach (var header in requestHeaders) {
163 | webRequest.SetRequestHeader(header.Item1, header.Item2);
164 | }
165 | }
166 |
167 | return webRequest;
168 | }
169 | }
--------------------------------------------------------------------------------