移除Unity参考代码

This commit is contained in:
2026-03-12 01:57:20 +08:00
parent 6ad7b022fa
commit cfdf2c749f
20 changed files with 0 additions and 4278 deletions

View File

@@ -1,61 +0,0 @@
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
class NanoVolumeCustomPass : CustomPass
{
const int NANO_VOLUME_PASS_ID = 0;
public NanoVolumeLoader nanoVolumeLoaderComponent;
public NanoVolumeSettings nanoVolumeSettings;
Material mat;
// To make sure the shader ends up in the build, we keep a reference to it
[SerializeField, HideInInspector]
Shader volumeShader;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
volumeShader = Shader.Find("FullScreen/NanoVolumePass");
mat = CoreUtils.CreateEngineMaterial(volumeShader);
}
protected override void Execute(CustomPassContext ctx)
{
if (!nanoVolumeLoaderComponent.IsLoaded())
{
return;
}
SetUniforms();
CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, ClearFlag.Color);
CoreUtils.DrawFullScreen(ctx.cmd, mat, ctx.propertyBlock, shaderPassId: NANO_VOLUME_PASS_ID);
}
protected override void Cleanup()
{
CoreUtils.Destroy(mat);
}
void SetUniforms()
{
mat.SetBuffer("buf", nanoVolumeLoaderComponent.GetGPUBuffer());
mat.SetFloat("_ClipPlaneMin", 0.01f);
mat.SetFloat("_ClipPlaneMax", 1500.0f);
mat.SetVector("_LightDir", nanoVolumeSettings.directionalLight.transform.forward);
mat.SetVector("_Light", nanoVolumeSettings.directionalLight.color);
mat.SetVector("_Scattering", nanoVolumeSettings.scatteringColor);
mat.SetFloat("_DensityScale", nanoVolumeSettings.DensitySlider.value);
mat.SetFloat("_LightAbsorbation", nanoVolumeSettings.LightAbsorbation.value);
mat.SetInt("_RayMarchSamples", (int)nanoVolumeSettings.RaymarchSamples.value);
mat.SetInt("_LightSamples", (int)nanoVolumeSettings.LightSteps.value);
mat.SetInt("_VisualizeSteps", nanoVolumeSettings.visualizeSteps);
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d93f84fcf6aa8704d91b42aced4fa025
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,42 +0,0 @@
Shader "FullScreen/NanoVolumePass"
{
HLSLINCLUDE
#pragma vertex Vert
#pragma target 5.0
#pragma use_dxc
// Commons, includes many others
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
#include "Assets/NanoVDB/PseudoRandom.hlsl"
#include "Assets/NanoVDB/NanoVolumePass.hlsl"
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
float4 color = NanoVolumePass(_WorldSpaceCameraPos, -viewDirection);
return float4(color.rgb, color.a);
}
ENDHLSL
SubShader
{
Tags{ "RenderPipeline" = "HDRenderPipeline" }
Pass
{
Name "Nano Volume Pass"
ZWrite Off Cull Off Blend One OneMinusSrcAlpha
HLSLPROGRAM
#pragma fragment FullScreenPass
ENDHLSL
}
}
}

View File

@@ -1,9 +0,0 @@
fileFormatVersion: 2
guid: a3e61447f8553dc419567904d4bede14
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,118 +0,0 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class NanoVolumeLoader : MonoBehaviour
{
[StructLayout(LayoutKind.Sequential)]
private unsafe struct NanoVolume
{
public uint* buf;
public ulong byteSize;
public ulong elementCount;
public ulong structStride;
};
unsafe NanoVolume* nanoVolume;
[Header("Assets/path/to/volume.nvdb")]
public string volumePath;
private ComputeBuffer gpuBuffer;
private uint[] buf;
private bool ok;
private bool loaded = false;
private void Awake()
{
SetDebugLogCallback(DebugLogCallback);
ok = PrepareVolume();
if (!ok) return;
unsafe
{
int bufferSize = (int)nanoVolume->elementCount;
int stride = (int)nanoVolume->structStride;
buf = new uint[bufferSize];
// Go through each element in nanoVolume buf and copy it to the buf array
for (int i = 0; i < bufferSize; i++)
{
buf[i] = nanoVolume->buf[i];
}
gpuBuffer = new ComputeBuffer(
bufferSize,
stride,
ComputeBufferType.Default
);
gpuBuffer.SetData(buf);
Debug.Log("GPU Buffer initialized");
loaded = true;
}
}
private unsafe bool PrepareVolume()
{
LoadNVDB(volumePath, out nanoVolume);
if (nanoVolume != null)
{
Debug.Log($"NanoVDB initialized successfully. size={nanoVolume->byteSize} bytes, " +
$"array length={nanoVolume->elementCount}, stride={nanoVolume->structStride}");
return true;
}
else
{
Debug.LogError("Failed to create NanoVolume, aborting.");
return false;
}
}
private void OnDestroy()
{
gpuBuffer?.Dispose();
unsafe
{
if (nanoVolume != null)
{
FreeNVDB(nanoVolume);
nanoVolume = null;
}
}
}
public ComputeBuffer GetGPUBuffer()
{
if (gpuBuffer == null)
{
Debug.LogError("Buffer is null. Make sure the NanoLoader is finished before accessing this buffer.");
return null;
}
return gpuBuffer;
}
public bool IsLoaded()
{
return loaded;
}
private delegate void DebugLogDelegate(IntPtr message);
private static void DebugLogCallback(IntPtr message) { Debug.Log($"[NanoVDBWrapper.dll]: {Marshal.PtrToStringAnsi(message)}"); }
[DllImport("NanoVDBWrapper", EntryPoint = "SetDebugLogCallback")]
private static extern void SetDebugLogCallback(DebugLogDelegate callback);
[DllImport("NanoVDBWrapper", EntryPoint = "LoadNVDB")]
private unsafe static extern void LoadNVDB(string path, out NanoVolume* ptrToStruct);
[DllImport("NanoVDBWrapper", EntryPoint = "FreeNVDB")]
private unsafe static extern void FreeNVDB(NanoVolume* ptrToStruct);
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: f8652d7dda47bd74ba2fe1af0981c096
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,276 +0,0 @@
#ifndef NANO_VOLUME_PASS
#define NANO_VOLUME_PASS
#define MIN_TRANSMITTANCE 0.05
#define MIN_DENSITY 0.01
#define CLOUD_COLOR float3(1, 1, 1)
#define COLOR_NONE float4(0, 0, 0, 0)
#define COLOR_RED float4(1, 0, 0, 1)
#define COLOR_GREEN float4(0, 1, 0, 1)
#define COLOR_BLUE float4(0, 0, 1, 1)
#define PNANOVDB_HLSL
#include "PNanoVDB.hlsl"
uniform pnanovdb_buf_t buf : register(t1);
uniform float4 _LightDir; // directionalLight.transform.forward
uniform float3 _Light;
uniform float3 _Scattering;
uniform float _DensityScale;
uniform float _LightRayLength;
uniform float _LightAbsorbation;
uniform float _ClipPlaneMin;
uniform float _ClipPlaneMax;
uniform int _RayMarchSamples;
uniform int _LightSamples;
uniform int _VisualizeSteps;
struct Ray
{
float3 origin;
float3 direction;
float tmin;
float tmax;
};
struct NanoVolume
{
pnanovdb_grid_handle_t grid;
pnanovdb_grid_type_t grid_type;
pnanovdb_readaccessor_t acc;
};
void initVolume(inout NanoVolume volume)
{
pnanovdb_grid_handle_t grid = { {0} };
pnanovdb_grid_type_t grid_type = pnanovdb_buf_read_uint32(buf, PNANOVDB_GRID_OFF_GRID_TYPE);
pnanovdb_tree_handle_t tree = pnanovdb_grid_get_tree(buf, grid);
pnanovdb_root_handle_t root = pnanovdb_tree_get_root(buf, tree);
pnanovdb_readaccessor_t acc;
pnanovdb_readaccessor_init(acc, root);
volume.grid = grid;
volume.grid_type = grid_type;
volume.acc = acc;
}
float get_value_coord(inout pnanovdb_readaccessor_t acc, pnanovdb_vec3_t pos)
{
pnanovdb_coord_t ijk = pnanovdb_hdda_pos_to_ijk(pos);
pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, ijk);
return pnanovdb_read_float(buf, address);
}
uint get_dim_coord(inout pnanovdb_readaccessor_t acc, pnanovdb_vec3_t pos)
{
pnanovdb_coord_t ijk = pnanovdb_hdda_pos_to_ijk(pos);
return pnanovdb_readaccessor_get_dim(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, ijk);
}
bool get_hdda_hit(inout pnanovdb_readaccessor_t acc, inout Ray ray, inout float valueAtHit)
{
float thit;
bool hit = pnanovdb_hdda_tree_marcher(
PNANOVDB_GRID_TYPE_FLOAT,
buf,
acc,
ray.origin, ray.tmin,
ray.direction, ray.tmax,
thit,
valueAtHit
);
ray.tmin = thit;
return hit;
}
void get_participating_media(out float sigmaS, out float sigmaE, float3 pos, inout pnanovdb_readaccessor_t acc)
{
sigmaS = get_value_coord(acc, pos) * _DensityScale;
sigmaE = max(0.000001, sigmaS);
}
// No inout to avoid breaking cache for main ray (Gaida 2022)
float volumetric_shadow(float3 pos, pnanovdb_readaccessor_t acc)
{
if (_LightSamples < 1) { return 0; }
float light_dir = -(_LightDir.xyz);
float shadow = 1;
float sigmaS = 0.0;
float sigmaE = 0.0;
int step = 0;
int steps = 10;
float step_size = 1;
while (step < steps)
{
float3 sample_pos = pos + step_size * light_dir;
get_participating_media(sigmaS, sigmaE, sample_pos, acc);
shadow *= exp(-sigmaE * step_size);
if (shadow < MIN_TRANSMITTANCE)
{
shadow = 0;
break;
}
step_size *= 2;
step++;
}
return shadow;
}
// Exp step with jitter
float volumetric_shadow_2(float3 pos, pnanovdb_readaccessor_t acc, float3 view_dir)
{
if (_LightSamples < 1) { return 0; }
float light_dir = -(_LightDir.xyz);
float shadow = 1.0;
float sigmaS = 0.0;
float sigmaE = 0.0;
float step_size = 1.0;
float jitter = 0;
int step = 0;
int steps = 10;
while (step < steps)
{
float3 sample_pos = pos + (jitter + step_size) * light_dir;
get_participating_media(sigmaS, sigmaE, sample_pos, acc);
sigmaE *= 0.3;
shadow *= exp(-sigmaE * step_size);
step++;
step_size *= (2 + random_float(sample_pos));
}
return shadow;
}
float phase_function()
{
return 1.0;///(4.0*3.14);
}
float4 raymarch_volume(Ray ray, inout NanoVolume volume, float step_size)
{
float transmittance = 1.0;
float sigmaS = 0.0;
float sigmaE = 0.0;
float acc_density = 0.0;
float3 direct_light = 0.0;
float3 ambient_light = 0.005;
float not_used;
bool hit = get_hdda_hit(volume.acc, ray, not_used);
if (!hit) { return COLOR_NONE; }
int step = 0;
float skip = 0;
while (step < _RayMarchSamples)
{
if (ray.tmin >= ray.tmax)
{
break;
}
// read density from ray position
float3 pos = ray.origin + ray.direction * ray.tmin;
get_participating_media(sigmaS, sigmaE, pos, volume.acc);
// Skip empty space.
uint dim = get_dim_coord(volume.acc, pos);
if (dim > 1)
{
step++;
float skip_step = 15;
ray.tmin += skip_step;
skip = skip_step;
continue;
}
if (sigmaS < MIN_DENSITY)
{
step++;
float skip_step = 5;
ray.tmin += skip_step;
skip = skip_step;
continue;
}
if (skip > 0) {
// backtrack a little bit
ray.tmin -= skip * 0.8;
pos = ray.origin + ray.direction * ray.tmin;
skip = 0;
}
acc_density += sigmaS;
// float3 S = sigmaS * phase_function() * volumetric_shadow_2(pos, volume.acc);
float3 S = sigmaS * phase_function() * volumetric_shadow_2(pos, volume.acc, ray.direction);
float3 Sint = (S - S * exp(-sigmaE * step_size)) / sigmaE;
direct_light += transmittance * Sint;
transmittance *= exp(-sigmaE * step_size);
if (acc_density > 1.0)
{
break;
}
// Early out if no more light is reaching this point
if (transmittance < MIN_TRANSMITTANCE)
{
transmittance = 0;
break;
}
step++;
ray.tmin += step_size;
}
// Low step count will be blue, high red.
if (_VisualizeSteps == 1)
{
float t = float(step) / float(_RayMarchSamples);
if (step <= 0)
{
return COLOR_NONE;
}
float3 final_color = lerp(COLOR_BLUE, COLOR_RED, t);
return float4(final_color, 1);
}
float3 final_color = (direct_light + ambient_light) * acc_density;
final_color = pow(final_color, 1.0 / 2.2);
return float4(final_color, acc_density);
}
float4 NanoVolumePass(float3 origin, float3 direction)
{
NanoVolume volume; initVolume(volume);
Ray ray;
ray.origin = origin;
ray.direction = direction;
ray.tmin = _ClipPlaneMin;
ray.tmax = _ClipPlaneMax;
float step_size = 0.57;
float4 final_color = raymarch_volume(ray, volume, step_size);
return final_color;
}
#endif // NANO_VOLUME_PASS

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 47dfc462aec4e4d46939d91412958fe4
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,35 +0,0 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class NanoVolumeSettings : MonoBehaviour
{
public Light directionalLight;
public TMP_Text vdbNameText;
public Slider RaymarchSamples;
public Slider TemporalFrames;
public Slider DensitySlider;
public Slider LightSteps;
public Slider LightAbsorbation;
public Color scatteringColor;
public int visualizeSteps = 0;
// Called from UI Button
public void VisualizeSteps()
{
if (visualizeSteps == 0)
{
visualizeSteps = 1;
}
else
{
visualizeSteps = 0;
}
}
// When clicking reset button
public void StopVisualizeSteps()
{
visualizeSteps = 0;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 04a3f5c1a0e0ba240ae40af9f0fcce17
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +0,0 @@
fileFormatVersion: 2
guid: 7fabb37c28af77741aff24d4ae1fe924
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 1
settings:
Exclude Editor: 0
Exclude Linux64: 0
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 0
Editor:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux64:
enabled: 1
settings:
CPU: AnyCPU
OSXUniversal:
enabled: 1
settings:
CPU: AnyCPU
Win:
enabled: 1
settings:
CPU: AnyCPU
Win64:
enabled: 1
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,19 +0,0 @@
// https://www.reedbeta.com/blog/quick-and-easy-gpu-random-numbers-in-d3d11/
uint rand_xorshift(uint seed)
{
// Xorshift algorithm from George Marsaglia's paper
seed ^= (seed << 13);
seed ^= (seed >> 17);
seed ^= (seed << 5);
return seed;
}
float random_float(float3 view_dir)
{
uint seed = asuint(view_dir.x + view_dir.y + view_dir.z);
float res = float(rand_xorshift(seed)) * (1.0 / 4294967296.0);
res = float(rand_xorshift(asuint(res))) * (1.0 / 4294967296.0);
res = float(rand_xorshift(asuint(res))) * (1.0 / 4294967296.0);
return res;
}

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 2159eccf73f568d458a47d19c6254765
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
#define NANOVDB_USE_OPENVDB
#define DLLExport __declspec(dllexport)
#include <iostream>
#include <nanovdb/util/IO.h>
struct NanoVolume {
uint32_t* buf;
uint64_t byteSize;
uint64_t elementCount;
uint64_t structStride;
} nanoVolumeStruct;
extern "C" {
typedef void(*DebugLogCallback)(const char*);
DLLExport void SetDebugLogCallback(DebugLogCallback callback);
DLLExport void LoadNVDB(const char* str, struct NanoVolume** volume);
DLLExport void FreeNVDB(struct NanoVolume* volume);
}
DebugLogCallback UnityLog = nullptr;
void SetDebugLogCallback(DebugLogCallback callback) {
UnityLog = callback;
}
nanovdb::GridHandle<nanovdb::HostBuffer> gridHandle;
void LoadNVDB(const char* path, struct NanoVolume** volume) {
try {
// reads first grid from file
gridHandle = nanovdb::io::readGrid(path);
// get a (raw) pointer to a NanoVDB grid of value type float
const nanovdb::FloatGrid* buf = gridHandle.grid<float>();
if (!buf) {
throw std::runtime_error("File did not contain a grid with value type float");
}
*volume = (struct NanoVolume*) malloc(sizeof(struct NanoVolume));
if (*volume == nullptr) {
UnityLog("Failed to allocate memory for NanoVolume struct.");
return;
}
const uint64_t byteSize = gridHandle.buffer().bufferSize();
const uint64_t elementCount = byteSize / sizeof(float);
const uint64_t structStride = sizeof(float);
uint32_t* buffer_ptr = (uint32_t*)gridHandle.buffer().data();
(*volume)->buf = buffer_ptr;
(*volume)->byteSize = byteSize;
(*volume)->elementCount = elementCount;
(*volume)->structStride = structStride;
}
catch (const std::exception& e) {
UnityLog("An exception occurred:");
UnityLog(e.what());
}
}
void FreeNVDB(struct NanoVolume* volume) {
free(volume);
volume = nullptr;
}

View File

@@ -1,46 +0,0 @@
fileFormatVersion: 2
guid: 44e340e1fd2f2d148a93e969247618ba
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
Any:
enabled: 1
settings:
Exclude Editor: 0
Exclude Linux64: 1
Exclude OSXUniversal: 0
Exclude Win: 1
Exclude Win64: 0
Editor:
enabled: 1
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
Linux64:
enabled: 0
settings:
CPU: None
OSXUniversal:
enabled: 1
settings:
CPU: None
Win:
enabled: 0
settings:
CPU: None
Win64:
enabled: 1
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -1,27 +0,0 @@
fileFormatVersion: 2
guid: bb0737f1c8a9f3343b05974ce7647fd8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
# Wrapper for NanoVDB to Unity
> See [NanoVDBWrapper.cpp](https://github.com/andersblomqvist/unity-nanovdb/blob/main/Assets/Plugins/NanoVDBWrapper.cpp) for source code.
The NanoVDB library is imported to Unity through a C++ wrapper. This wrapper exposes three functions, which we use in our Unity script [NanoVolumeLoader.cs](https://github.com/andersblomqvist/unity-nanovdb/blob/main/Assets/NanoVDB/NanoVolumeLoader.cs):
* `void SetDebugLogCallback(DebugLogCallback callback)`
* `void LoadNVDB(const char* str, struct NanoVolume** volume)`
* `void FreeNVDB(struct NanoVolume* volume)`
The `LoadNVDB` is most important, as it loads a `.nvdb` file from disk and enables Unity to access it through the `NanoVolume` struct. This struct mainly contains a pointer to the VDB grid buffer, which is uploaded to the GPU through the `NanoVolumeLoader.cs` script. That is basically it for the wrapper.
*Note:* it is not recommended by the author, Ken Museth, to store `.nvdb` files on disk. Instead it is suggested to convert an OpenVDB (`.vdb`) to NanoVDB (`.nvdb`) at runtime, but that requires importing all of OpenVDB. I decided to accept a larger file size on disk instead of bothering to import OpenVDB.
## Compile to Unity
The source is compiled to Unity with MSVC and CLR. In Visual Studio, the `Common Language Runtime Support` field is set to `.NET Framework Runtime Support (/clr)`, with the target version of `v4.8`. For Unity to accept version `4.8` we need to go into Unity, Edit, Project Settings, Player, Other Settings, and set `Api Compatibility Level*` to `.NET Framework`. This will make Unity import our DLL when we have a Unity script that uses it.
## References
* CLR: https://learn.microsoft.com/en-us/cpp/dotnet/dotnet-programming-with-cpp-cli-visual-cpp
* Logging from DLL in Unity: https://stackoverflow.com/questions/43732825/use-debug-log-from-c
* Unity Managed plugins: https://docs.unity3d.com/6000.0/Documentation/Manual/plug-ins-managed.html
* NanoVDB presentation by Ken Museth under Supplementary Material: https://dl.acm.org/doi/10.1145/3450623.3464653

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: aab0996318f585d43920e93dc5e3d2e5
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: