升级6.4.升级水,升级天气
This commit is contained in:
@@ -8,6 +8,36 @@
|
||||
|
||||
m_UtilityNameSpace
|
||||
|
||||
// NOTE: We have to roll our own bilinear filter in Compute shaders when
|
||||
// reading from a RWTexture. The documentation below explains how SRV
|
||||
// and UAV mappings of the same texture cannot exist at the same time.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture2d
|
||||
float4 SampleBilinear(const RWTexture2DArray<float4> i_Texture, const float2 i_UV, const uint i_Slice, const float i_Resolution)
|
||||
{
|
||||
// Make relative to pixel centers.
|
||||
const float2 center = i_UV * i_Resolution - 0.5;
|
||||
|
||||
// Compute integral (bottom left) and fractional parts
|
||||
// Prevent overflow from possible negative cast to unsigned.
|
||||
const uint maximum = (uint)i_Resolution - 1;
|
||||
const uint2 integral = max((float2)0.0, floor(center));
|
||||
const uint2 opposite = uint2(min(integral.x + 1, maximum), min(integral.y + 1, maximum));
|
||||
const float2 fractional = frac(center);
|
||||
|
||||
// Clamp from below and above (desired?).
|
||||
const float4 bl = i_Texture[uint3(integral, i_Slice)];
|
||||
const float4 br = i_Texture[uint3(uint2(opposite.x, integral.y), i_Slice)];
|
||||
const float4 tl = i_Texture[uint3(uint2(integral.x, opposite.y), i_Slice)];
|
||||
const float4 tr = i_Texture[uint3(opposite, i_Slice)];
|
||||
|
||||
return lerp
|
||||
(
|
||||
lerp(bl, br, fractional.x),
|
||||
lerp(tl, tr, fractional.x),
|
||||
fractional.y
|
||||
);
|
||||
}
|
||||
|
||||
// Taken from:
|
||||
// https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
|
||||
//
|
||||
@@ -66,6 +96,67 @@ float4 SampleTextureCatmullRom(in Texture2D<float4> tex, in SamplerState linearS
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 CubicWeights(const float f)
|
||||
{
|
||||
const float f2 = f * f;
|
||||
const float f3 = f2 * f;
|
||||
|
||||
// Catmull–Rom (a = -0.5)
|
||||
return float4
|
||||
(
|
||||
-0.5 * f3 + f2 - 0.5 * f,
|
||||
1.5 * f3 - 2.5 * f2 + 1.0,
|
||||
-1.5 * f3 + 2.0 * f2 + 0.5 * f,
|
||||
0.5 * f3 - 0.5 * f2
|
||||
);
|
||||
}
|
||||
|
||||
float4 SampleBicubicRepeat
|
||||
(
|
||||
const Texture2DArray<float4> i_Texture,
|
||||
const float2 i_UV,
|
||||
const uint2 i_Size,
|
||||
const uint i_Slice
|
||||
)
|
||||
{
|
||||
// Convert to texel space (centered at pixel centers).
|
||||
const float2 samplePosition = i_UV * (float2)i_Size - 0.5;
|
||||
const int2 texelPosition = (int2)floor(samplePosition);
|
||||
const float2 f = samplePosition - (float2)texelPosition;
|
||||
|
||||
// Precompute weights.
|
||||
const float4 wx = CubicWeights(f.x);
|
||||
const float4 wy = CubicWeights(f.y);
|
||||
|
||||
const uint2 size = i_Size - 1;
|
||||
|
||||
const uint4 x = uint4
|
||||
(
|
||||
(texelPosition.x - 1) & size.x,
|
||||
(texelPosition.x + 0) & size.x,
|
||||
(texelPosition.x + 1) & size.x,
|
||||
(texelPosition.x + 2) & size.x
|
||||
);
|
||||
|
||||
// Horizontal pass.
|
||||
float4 row[4];
|
||||
[unroll]
|
||||
for (int j = -1; j <= 2; ++j)
|
||||
{
|
||||
const int y = (texelPosition.y + j) & size.y;
|
||||
|
||||
const float4 t0 = i_Texture[uint3(x.x, y, i_Slice)];
|
||||
const float4 t1 = i_Texture[uint3(x.y, y, i_Slice)];
|
||||
const float4 t2 = i_Texture[uint3(x.z, y, i_Slice)];
|
||||
const float4 t3 = i_Texture[uint3(x.w, y, i_Slice)];
|
||||
|
||||
row[j + 1] = t0 * wx.x + t1 * wx.y + t2 * wx.z + t3 * wx.w;
|
||||
}
|
||||
|
||||
// Vertical pass.
|
||||
return row[0] * wy.x + row[1] * wy.y + row[2] * wy.z + row[3] * wy.w;
|
||||
}
|
||||
|
||||
m_UtilityNameSpaceEnd
|
||||
|
||||
#endif // d_WaveHarmonic_Utility_Filtering
|
||||
|
||||
@@ -43,6 +43,16 @@ float2 WorldNormalToScreenDirection(const float3 i_PositionWS, const float3 i_No
|
||||
return direction;
|
||||
}
|
||||
|
||||
float3 SafeComputeWorldSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invViewProjMatrix)
|
||||
{
|
||||
float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth);
|
||||
float4 hpositionWS = mul(invViewProjMatrix, positionCS);
|
||||
|
||||
// w is sometimes zero when using oblique projection.
|
||||
// Zero is better than NaN.
|
||||
return hpositionWS.w > 0.0 ? hpositionWS.xyz / hpositionWS.w : 0.0;
|
||||
}
|
||||
|
||||
m_UtilityNameSpaceEnd
|
||||
|
||||
#endif // d_WaveHarmonic_Utility_Helpers
|
||||
|
||||
@@ -26,6 +26,15 @@
|
||||
#define SHADERPASS_MOTION_VECTORS (22)
|
||||
|
||||
|
||||
//
|
||||
// Motion Vector Pass Fix
|
||||
//
|
||||
|
||||
#if SHADERPASS == SHADERPASS_MOTION_VECTORS
|
||||
#undef VARYINGS_NEED_NORMAL_WS
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// Deferred Fix
|
||||
//
|
||||
@@ -86,6 +95,9 @@
|
||||
// Transparent Objects Receives Shadows
|
||||
//
|
||||
|
||||
// WebGPU does not like the binding.
|
||||
#ifndef SHADER_API_WEBGPU
|
||||
|
||||
#if _SURFACE_TYPE_TRANSPARENT
|
||||
#if _TRANSPARENT_RECEIVES_SHADOWS
|
||||
#if SHADERPASS == SHADERPASS_FORWARD || SHADERPASS == SHADERPASS_FORWARD_ADD
|
||||
@@ -108,4 +120,6 @@ float4 _ShadowMapTexture_TexelSize;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // SHADER_API_WEBGPU
|
||||
|
||||
#endif // d_WaveHarmonic_Utility_ShaderGraphDefines
|
||||
|
||||
@@ -21,39 +21,155 @@
|
||||
#define CLUSTER_LIGHT_LOOP_SUBTRACTIVE_LIGHT_CHECK FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
|
||||
#endif // FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
|
||||
|
||||
#if UNITY_VERSION >= 60000000
|
||||
#if defined(STEREO_INSTANCING_ON) || defined(STEREO_MULTIVIEW_ON)
|
||||
#if _ALPHATEST_ON
|
||||
#if !USE_CLUSTER_LIGHT_LOOP
|
||||
// If not clustered and additional light shadows and XR, the shading model
|
||||
// completely breaks. It is like shadow attenuation is NaN or some obscure
|
||||
// compiler issue. For 2022.3, it is broken for forward+ only, but cannot be fixed.
|
||||
#define d_ShadowMaskBroken 1
|
||||
#else
|
||||
#if _RECEIVE_SHADOWS_OFF
|
||||
// Right eye broken rendering similar to above.
|
||||
#define d_AdditionalLightsBroken 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // CREST_URP
|
||||
|
||||
#if CREST_HDRP
|
||||
#if CREST_HDRP_FORWARD_PASS
|
||||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
|
||||
|
||||
#if UNITY_VERSION < 202310
|
||||
#define GetMeshRenderingLayerMask GetMeshRenderingLightLayer
|
||||
#endif // UNITY_VERSION
|
||||
|
||||
#if d_Crest_AdditionalLights
|
||||
#if d_Crest_WaterSurface
|
||||
// Causes rendering issues at a distance with foreground objects.
|
||||
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
#define LIGHTLOOP_DISABLE_TILE_AND_CLUSTER 1
|
||||
#define d_Crest_LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
#endif // LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
// Adapted from: com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.hlsl
|
||||
half3 GetPunctualLights(float3 i_PositionWS, float2 i_PositionSS, const float4 i_ScreenPosition, const half3 i_Normal)
|
||||
{
|
||||
half3 color = 0.0;
|
||||
|
||||
BuiltinData builtinData;
|
||||
ZERO_INITIALIZE(BuiltinData, builtinData);
|
||||
|
||||
LightLoopContext context;
|
||||
context.sampleReflection = 0;
|
||||
context.shadowContext = InitShadowContext();
|
||||
context.contactShadow = 0;
|
||||
context.contactShadowFade = 0.0;
|
||||
context.shadowValue = 1;
|
||||
#if UNITY_VERSION < 60000000
|
||||
context.splineVisibility = -1;
|
||||
#endif
|
||||
#ifdef APPLY_FOG_ON_SKY_REFLECTIONS
|
||||
context.positionWS = i_PositionWS;
|
||||
#endif
|
||||
|
||||
float3 positionWS = GetCameraRelativePositionWS(i_PositionWS);
|
||||
ApplyCameraRelativeXR(positionWS);
|
||||
|
||||
PositionInputs posInput;
|
||||
ZERO_INITIALIZE(PositionInputs, posInput);
|
||||
|
||||
posInput.tileCoord = uint2(i_PositionSS) / GetTileSize();
|
||||
posInput.positionWS = positionWS;
|
||||
posInput.positionSS = i_PositionSS;
|
||||
posInput.positionNDC = i_ScreenPosition.xy / i_ScreenPosition.w;
|
||||
|
||||
const uint renderingLayers = GetMeshRenderingLayerMask();
|
||||
|
||||
uint lightCount, lightStart;
|
||||
|
||||
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, lightStart, lightCount);
|
||||
#else // LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
lightCount = _PunctualLightCount;
|
||||
lightStart = 0;
|
||||
#endif
|
||||
|
||||
bool fastPath = false;
|
||||
#if SCALARIZE_LIGHT_LOOP
|
||||
uint lightStartLane0;
|
||||
fastPath = IsFastPath(lightStart, lightStartLane0);
|
||||
|
||||
if (fastPath)
|
||||
{
|
||||
lightStart = lightStartLane0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Scalarized loop. All lights that are in a tile/cluster touched by any pixel in the wave are loaded (scalar load), only the one relevant to current thread/pixel are processed.
|
||||
// For clarity, the following code will follow the convention: variables starting with s_ are meant to be wave uniform (meant for scalar register),
|
||||
// v_ are variables that might have different value for each thread in the wave (meant for vector registers).
|
||||
// This will perform more loads than it is supposed to, however, the benefits should offset the downside, especially given that light data accessed should be largely coherent.
|
||||
// Note that the above is valid only if wave intriniscs are supported.
|
||||
uint v_lightListOffset = 0;
|
||||
uint v_lightIdx = lightStart;
|
||||
|
||||
#if NEED_TO_CHECK_HELPER_LANE
|
||||
// On some platform helper lanes don't behave as we'd expect, therefore we prevent them from entering the loop altogether.
|
||||
// IMPORTANT! This has implications if ddx/ddy is used on results derived from lighting, however given Lightloop is called in compute we should be
|
||||
// sure it will not happen.
|
||||
bool isHelperLane = WaveIsHelperLane();
|
||||
while (!isHelperLane && v_lightListOffset < lightCount)
|
||||
#else
|
||||
while (v_lightListOffset < lightCount)
|
||||
#endif
|
||||
{
|
||||
v_lightIdx = FetchIndex(lightStart, v_lightListOffset);
|
||||
#if SCALARIZE_LIGHT_LOOP
|
||||
uint s_lightIdx = ScalarizeElementIndex(v_lightIdx, fastPath);
|
||||
#else
|
||||
uint s_lightIdx = v_lightIdx;
|
||||
#endif
|
||||
if (s_lightIdx == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
LightData s_light = FetchLight(s_lightIdx);
|
||||
|
||||
// If current scalar and vector light index match, we process the light. The v_lightListOffset for current thread is increased.
|
||||
// Note that the following should really be ==, however, since helper lanes are not considered by WaveActiveMin, such helper lanes could
|
||||
// end up with a unique v_lightIdx value that is smaller than s_lightIdx hence being stuck in a loop. All the active lanes will not have this problem.
|
||||
if (s_lightIdx >= v_lightIdx)
|
||||
{
|
||||
v_lightListOffset++;
|
||||
if (IsMatchingLightLayer(s_light.lightLayers, renderingLayers))
|
||||
{
|
||||
float3 L; float4 distances; // {d, d^2, 1/d, d_proj}
|
||||
GetPunctualLightVectors(positionWS, s_light, L, distances);
|
||||
|
||||
// Is it worth evaluating the light?
|
||||
if (s_light.lightDimmer > 0)
|
||||
{
|
||||
float4 lightColor = EvaluateLight_Punctual(context, posInput, s_light, L, distances);
|
||||
lightColor.rgb *= lightColor.a * max(k_Crest_AdditionalLightLerp, dot(i_Normal, L)); // Composite
|
||||
|
||||
SHADOW_TYPE shadow = EvaluateShadow_Punctual(context, posInput, s_light, builtinData, i_Normal, L, distances);
|
||||
|
||||
lightColor.rgb *= ComputeShadowColor(shadow, s_light.shadowTint, s_light.penumbraTint);
|
||||
|
||||
color += lightColor.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
#ifdef d_Crest_LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
#undef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
|
||||
#endif
|
||||
#endif // d_Crest_WaterSurface
|
||||
#endif // d_Crest_AdditionalLights
|
||||
|
||||
#if UNITY_VERSION < 60000000
|
||||
#if PROBE_VOLUMES_L1
|
||||
// URP sets this to zero.
|
||||
#define AMBIENT_PROBE_BUFFER 1
|
||||
#endif // PROBE_VOLUMES_L1
|
||||
#endif // UNITY_VERSION
|
||||
#endif // CREST_HDRP
|
||||
#endif // CREST_HDRP_FORWARD_PASS
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
@@ -64,13 +180,19 @@ void PrimaryLight
|
||||
out half3 o_Direction
|
||||
)
|
||||
{
|
||||
#if CREST_HDRP
|
||||
// We could get the main light the same way we get the main light shadows,
|
||||
// but most of the data would be missing (including below horizon
|
||||
// attenuation) which would require re-running the light loop which is expensive.
|
||||
o_Direction = g_Crest_PrimaryLightDirection;
|
||||
o_Color = g_Crest_PrimaryLightIntensity;
|
||||
#elif CREST_URP
|
||||
o_Direction = half3(0.0, 1.0, 0.0);
|
||||
o_Color = 0.0;
|
||||
|
||||
#ifndef d_IsAdditionalLight
|
||||
if (g_Crest_PrimaryLightFallback)
|
||||
{
|
||||
o_Direction = g_Crest_PrimaryLightDirection;
|
||||
o_Color = g_Crest_PrimaryLightIntensity;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CREST_URP
|
||||
// Actual light data from the pipeline.
|
||||
Light light = GetMainLight();
|
||||
o_Direction = light.direction;
|
||||
@@ -78,7 +200,10 @@ void PrimaryLight
|
||||
#elif CREST_BIRP
|
||||
#ifndef USING_DIRECTIONAL_LIGHT
|
||||
// Yes. This function wants the world position of the surface.
|
||||
o_Direction = normalize(UnityWorldSpaceLightDir(i_PositionWS));
|
||||
o_Direction = UnityWorldSpaceLightDir(i_PositionWS);
|
||||
// Prevents divide by zero.
|
||||
if (all(o_Direction == 0)) o_Direction = half3(0.0, 1.0, 0.0);
|
||||
o_Direction = normalize(o_Direction);
|
||||
#else
|
||||
o_Direction = _WorldSpaceLightPos0.xyz;
|
||||
// Prevents divide by zero.
|
||||
@@ -100,7 +225,7 @@ half3 AmbientLight(const half3 i_AmbientLight)
|
||||
half3 ambient = i_AmbientLight;
|
||||
|
||||
#ifndef SHADERGRAPH_PREVIEW
|
||||
#if CREST_HDRP
|
||||
#if CREST_HDRP_FORWARD_PASS
|
||||
// Allows control of baked lighting through volume framework.
|
||||
// We could create a BuiltinData struct which would have rendering layers on it, but it seems more complicated.
|
||||
ambient *= GetIndirectDiffuseMultiplier(GetMeshRenderingLayerMask());
|
||||
@@ -123,7 +248,9 @@ half3 AmbientLight()
|
||||
return AmbientLight(ambient);
|
||||
}
|
||||
|
||||
half3 AdditionalLighting(const float3 i_PositionWS, const float4 i_ScreenPosition, const float2 i_StaticLightMapUV)
|
||||
#if d_Crest_AdditionalLights
|
||||
#if d_Crest_WaterSurface
|
||||
half3 AdditionalLighting(const float3 i_PositionWS, const float4 i_ScreenPosition, const float2 i_StaticLightMapUV, const float2 i_PositionSS, const half3 i_Normal)
|
||||
{
|
||||
half3 color = 0.0;
|
||||
|
||||
@@ -153,19 +280,11 @@ LIGHT_LOOP_BEGIN(pixelLightCount)
|
||||
// Includes shadows and cookies.
|
||||
Light light = GetAdditionalLight(lightIndex, inputData, shadowMask, aoFactor);
|
||||
|
||||
#if d_ShadowMaskBroken
|
||||
light.shadowAttenuation = 1.0;
|
||||
#endif
|
||||
|
||||
#if d_AdditionalLightsBroken
|
||||
light.color = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef _LIGHT_LAYERS
|
||||
if (IsMatchingLightLayer(light.layerMask, meshRenderingLayers))
|
||||
#endif
|
||||
{
|
||||
color += light.color * (light.distanceAttenuation * light.shadowAttenuation);
|
||||
color += light.color * max(k_Crest_AdditionalLightLerp, dot(i_Normal, light.direction)) * (light.distanceAttenuation * light.shadowAttenuation);
|
||||
}
|
||||
LIGHT_LOOP_END
|
||||
|
||||
@@ -188,11 +307,16 @@ LIGHT_LOOP_END
|
||||
#endif // _ADDITIONAL_LIGHTS
|
||||
#endif // CREST_URP
|
||||
|
||||
// HDRP todo.
|
||||
#if CREST_HDRP_FORWARD_PASS
|
||||
color = GetPunctualLights(i_PositionWS, i_PositionSS, i_ScreenPosition, i_Normal);
|
||||
#endif
|
||||
|
||||
// BIRP has additional lights as additional passes. Handled elsewhere.
|
||||
|
||||
return color;
|
||||
}
|
||||
#endif // d_Crest_WaterSurface
|
||||
#endif // d_Crest_AdditionalLights
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adapted from:
|
||||
// https://pastebin.com/sDrnzYxB
|
||||
|
||||
// License:
|
||||
// CC0 Creative Commons License
|
||||
// "Yes by all means use it how you wish. I'm sharing it as CC0."
|
||||
// https://www.reddit.com/r/Unity3D/comments/dhr5g2/comment/f3rz6rc/
|
||||
|
||||
#ifndef d_WaveHarmonic_Utility_Stochastic
|
||||
#define d_WaveHarmonic_Utility_Stochastic
|
||||
|
||||
m_UtilityNameSpace
|
||||
|
||||
float2 Hash2D2D(const float2 s)
|
||||
{
|
||||
// Magic numbers.
|
||||
return frac(sin(fmod(float2(dot(s, float2(127.1, 311.7)), dot(s, float2(269.5, 183.3))), PI)) * 43758.5453);
|
||||
}
|
||||
|
||||
float4 SampleStochastic(const Texture2D i_Texture, const SamplerState i_Sampler, const float2 i_UV)
|
||||
{
|
||||
// UV transformed into triangular grid space with UV scaled by approximation of 2 * sqrt(3)
|
||||
const float2 skewUV = mul(float2x2(1.0, 0.0, -0.57735027, 1.15470054), i_UV * 3.464);
|
||||
|
||||
// Vertex IDs and barycentric coords
|
||||
const float2 id = float2(floor(skewUV));
|
||||
float3 barry = float3(frac(skewUV), 0.0);
|
||||
barry.z = 1.0 - barry.x - barry.y;
|
||||
|
||||
// Triangle vertices and blend weights.
|
||||
// BW_vx[0...2].xyz = triangle verts
|
||||
// BW_vx[3].xy = blend weights (z is unused)
|
||||
const float4x3 BW_vx =
|
||||
(
|
||||
(barry.z > 0)
|
||||
? float4x3
|
||||
(
|
||||
float3(id, 0),
|
||||
float3(id + float2(0, 1), 0),
|
||||
float3(id + float2(1, 0), 0),
|
||||
barry.zyx
|
||||
)
|
||||
: float4x3
|
||||
(
|
||||
float3(id + float2(1, 1), 0),
|
||||
float3(id + float2(1, 0), 0),
|
||||
float3(id + float2(0, 1), 0),
|
||||
float3(-barry.z, 1.0 - barry.y, 1.0 - barry.x)
|
||||
)
|
||||
);
|
||||
|
||||
// Calculate derivatives to avoid triangular grid artifacts.
|
||||
const float2 dx = ddx(i_UV);
|
||||
const float2 dy = ddy(i_UV);
|
||||
|
||||
// Blend samples with calculated weights.
|
||||
return SAMPLE_TEXTURE2D_GRAD(i_Texture, i_Sampler, i_UV + Hash2D2D(BW_vx[0].xy), dx, dy) * BW_vx[3].x +
|
||||
SAMPLE_TEXTURE2D_GRAD(i_Texture, i_Sampler, i_UV + Hash2D2D(BW_vx[1].xy), dx, dy) * BW_vx[3].y +
|
||||
SAMPLE_TEXTURE2D_GRAD(i_Texture, i_Sampler, i_UV + Hash2D2D(BW_vx[2].xy), dx, dy) * BW_vx[3].z;
|
||||
}
|
||||
|
||||
m_UtilityNameSpaceEnd
|
||||
|
||||
#endif // d_WaveHarmonic_Utility_Stochastic
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90b04c86b94da4f6890d04a7b7fa5226
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user