Unified Volumetric Flow

Modified stardust & nebula shaders such that flow velocity is consistent: Volumetric:flow now represents global velocity in meters per second
This commit is contained in:
Reinier Vens 2022-07-17 05:27:50 +01:00
commit c3329cecc4
19 changed files with 527 additions and 67 deletions

View file

@ -86,7 +86,7 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Scale: 4.5182247
- _Scale: 0.5
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

BIN
Assets/Resources/Settings.asset (Stored with Git LFS)

Binary file not shown.

View file

@ -16182,7 +16182,7 @@ MonoBehaviour:
ParticleCalculation: {fileID: 7200000, guid: f53a4ba56f0db2a49ad9f68150bf298a, type: 3}
ParticleMaterial: {fileID: 2100000, guid: fc00c35c3c370774c88d55240b6538ce, type: 2}
Span: 256
Speed: -0.5
Period: 2
MinimumSize: 0
MaximumSize: 0.75
Spacing: 6

View file

@ -860,9 +860,9 @@ MonoBehaviour:
ParticleCalculation: {fileID: 7200000, guid: f53a4ba56f0db2a49ad9f68150bf298a, type: 3}
ParticleMaterial: {fileID: 2100000, guid: fc00c35c3c370774c88d55240b6538ce, type: 2}
Span: 128
Speed: -0.05
Period: 2
MinimumSize: 0
MaximumSize: 0.5
MaximumSize: 0.75
Spacing: 6
Ceiling: -0.1
Floor: -30

View file

@ -43,7 +43,7 @@ public class FlowSettings
[JsonProperty("scale"), Key(0)] public float Scale;
[JsonProperty("amplitude"), Key(1)] public float Amplitude;
[JsonProperty("scrollSpeed"), Key(2)] public float ScrollSpeed;
[JsonProperty("velocity"), Key(3)] public float Speed;
[JsonProperty("period"), Key(3)] public float Period;
}
[Serializable, MessagePackObject, JsonObject(MemberSerialization.OptIn)]

View file

@ -110,7 +110,7 @@ public class VolumeCloudRenderer : EffectBase
/* Some code is from playdead TAA. */
//1. Pass1, Render a undersampled buffer. The buffer is dithered using bayer matrix(every 3x3 pixel) and halton sequence.
//1. Pass1, Render a undersampled buffer. The buffer is dithered using blue noise and halton sequence.
//If it's first frame, force a high quality sample to make the initial history buffer good enough.
if (firstFrame || quality == Quality.Ultra) {
mat.EnableKeyword("ULTRA_QUALITY");

View file

@ -67,6 +67,6 @@ public class VolumeSampling : MonoBehaviour
Shader.SetGlobalFloat("_FlowAmplitude", Settings.DefaultEnvironment.Flow.Amplitude);
_flowScroll += Settings.DefaultEnvironment.Flow.ScrollSpeed * Time.deltaTime;
Shader.SetGlobalFloat("_FlowScroll", _flowScroll);
Shader.SetGlobalFloat("_FlowSpeed", Settings.DefaultEnvironment.Flow.Speed);
Shader.SetGlobalFloat("_FlowPeriod", Settings.DefaultEnvironment.Flow.Period);
}
}

View file

@ -13,16 +13,11 @@ struct Particle
RWStructuredBuffer<Particle> particles;
// Use this texture to spawn particles over terrain
Texture2D Heightmap;
SamplerState samplerHeightmap;
// Use this texture to choose the color of the particle
Texture2D HueTexture;
SamplerState samplerHueTexture;
//uniform float4x4 noiseOffsetMatrix;
SamplerState samplerHueTexture;
float period;
float time;
float spacing;
float ceilingHeight;
@ -121,20 +116,20 @@ void UpdateParticles(uint3 id : SV_DispatchThreadID, int3 groupID : SV_GroupThre
uint xp = x + xt + offset;
uint yp = y + yt + offset;
const float lifetime = frac(time+RandomFirst(xp, yp));
const float lifetime = frac(time / period + RandomFirst(xp, yp));
particles[id.x].position = float3(
x * spacing + xt * spacing + perlinNoise1D(RandomValue()*1024)*spacing, 0,
y * spacing + yt * spacing + perlinNoise1D(RandomValue()*1024)*spacing);
const float2 puv = float2(.5,.5) - (particles[id.x].position.xz - _GridTransform.xy) / _GridTransform.z;
const float gravHeight = -Heightmap.SampleLevel(samplerHeightmap, puv, 0.0f).r + _NebulaFloorOffset;
const float2 puv = getUV(particles[id.x].position.xz);
const float gravHeight = -tex2Dlod(_NebulaSurfaceHeight, float4(puv, 0, 0)).x + _NebulaFloorOffset;
const float headroom = ceilingHeight - gravHeight;
particles[id.x].position.y = gravHeight + floorHeight + headroom *
pow(RandomValue(), max(1, heightExponent/(headroom*headroom))) +
perlinNoise1D(RandomValue()*1024)*spacing/2;
float noise;
const float3 flowDir = flow(particles[id.x].position, noise);
particles[id.x].position += flowDir * (lifetime * noise);
const float3 flowVec = flow(particles[id.x].position, noise);
particles[id.x].position -= flowVec * lifetime * period;
const float fade = smoothstep(0,ceilingHeight, particles[id.x].position.y);
const float d = pow(density(particles[id.x].position) + .01, 0.1);
particles[id.x].size = lerp(minimumSize, maximumSize, saturate(RandomValue()*fade)) * parabola(lifetime, 2);

View file

@ -15,7 +15,7 @@ public class Stardust : MonoBehaviour
public ComputeShader ParticleCalculation;
public Material ParticleMaterial;
public int Span = 512;
public float Speed = .25f;
public float Period = .25f;
public float MinimumSize = .1f;
public float MaximumSize = 2;
@ -99,12 +99,11 @@ public class Stardust : MonoBehaviour
{
//Bind resources to compute shader
ParticleCalculation.SetBuffer(_updateParticlesKernel, "particles", _particlesBuffer);
// ParticleCalculation.SetBuffer(_updateParticlesKernel, "temperature", _temperature);
ParticleCalculation.SetFloat("time", Time.time * Speed);
ParticleCalculation.SetFloat("time", Time.time);
var pos = GravityCamera.transform.position;
ParticleCalculation.SetVector("_GridTransform", new Vector4(pos.x,pos.z,GravityCamera.orthographicSize*2));
ParticleCalculation.SetFloat("period", Period);
ParticleCalculation.SetFloat("spacing", Spacing);
ParticleCalculation.SetFloat("ceilingHeight", Ceiling);
ParticleCalculation.SetFloat("floorHeight", Floor);
@ -113,31 +112,7 @@ public class Stardust : MonoBehaviour
ParticleCalculation.SetFloat("minimumSize", MinimumSize);
ParticleCalculation.SetInt("span", Span);
ParticleCalculation.SetTexture(_updateParticlesKernel, "Heightmap", Heightmap);
ParticleCalculation.SetTexture(_updateParticlesKernel, "HueTexture", ParticleColors);
ParticleCalculation.SetTexture(_updateParticlesKernel, "_NebulaSurfaceHeight", NebulaSurfaceHeight);
ParticleCalculation.SetTexture(_updateParticlesKernel, "_NebulaPatchHeight", NebulaPatchHeight);
ParticleCalculation.SetTexture(_updateParticlesKernel, "_NebulaPatch", NebulaPatch);
ParticleCalculation.SetTexture(_updateParticlesKernel, "_NebulaTint", NebulaTint);
ParticleCalculation.SetFloat("_NebulaFillDensity", Settings.DefaultEnvironment.Nebula.FillDensity);
ParticleCalculation.SetFloat("_SafetyDistance", Settings.DefaultEnvironment.Nebula.SafetyDistance);
ParticleCalculation.SetFloat("_NebulaFloorDensity", Settings.DefaultEnvironment.Nebula.FloorDensity);
ParticleCalculation.SetFloat("_NebulaPatchDensity", Settings.DefaultEnvironment.Nebula.PatchDensity);
ParticleCalculation.SetFloat("_NebulaFloorOffset", Settings.DefaultEnvironment.Nebula.FloorOffset);
ParticleCalculation.SetFloat("_NebulaFloorBlend", Settings.DefaultEnvironment.Nebula.FloorBlend);
ParticleCalculation.SetFloat("_NebulaPatchBlend", Settings.DefaultEnvironment.Nebula.PatchBlend);
// Shader.SetGlobalFloat("_TintExponent", Settings.DefaultEnvironment.);
ParticleCalculation.SetFloat("_NoiseScale", Settings.DefaultEnvironment.Noise.Scale);
ParticleCalculation.SetFloat("_NoiseExponent", Settings.DefaultEnvironment.Noise.Exponent);
ParticleCalculation.SetFloat("_NoiseAmplitude", Settings.DefaultEnvironment.Noise.Amplitude);
ParticleCalculation.SetFloat("_NoiseSpeed", Settings.DefaultEnvironment.Noise.Speed);
ParticleCalculation.SetFloat("_FlowScale", Settings.DefaultEnvironment.Flow.Scale);
ParticleCalculation.SetFloat("_FlowAmplitude", Settings.DefaultEnvironment.Flow.Amplitude);
_flowScroll += Settings.DefaultEnvironment.Flow.ScrollSpeed * Time.deltaTime;
ParticleCalculation.SetFloat("_FlowScroll", _flowScroll);
ParticleCalculation.SetFloat("_FlowSpeed", Settings.DefaultEnvironment.Flow.Speed);
//Dispatch, launch threads on GPU
int numberOfGroups = Mathf.CeilToInt((float)Span * Span / GROUP_SIZE);

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 992fcf67b7a8501419a78ce324844bce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,156 @@
// Based on https://github.com/keijiro/StableFluids
#include "Assets/Shaders/Volumetric.cginc"
#pragma kernel Advect
#pragma kernel Force
#pragma kernel PSetup
#pragma kernel PFinish
#pragma kernel Jacobi1
#pragma kernel Jacobi2
#pragma kernel Adjust
// Common parameter
float Time;
float DeltaTime;
// Adjustment
int2 Delta;
float Fade;
// External force
float2 ForceOrigin;
float2 ForceVector;
float ForceExponent;
// U (velocity field)
Texture2D<float2> U_in;
SamplerState samplerU_in;
RWTexture2D<float2> U_out;
// W (velocity field; working)
Texture2D<float2> W_in;
RWTexture2D<float2> W_out;
// Div W
RWTexture2D<float> DivW_out;
// P (pressure field)
Texture2D<float> P_in;
RWTexture2D<float> P_out;
// Color map
Texture2D<half4> C_in;
SamplerState samplerC_in;
RWTexture2D<half4> C_out;
// Jacobi method arguments
float Alpha, Beta;
Texture2D<float> X1_in;
Texture2D<float> B1_in;
RWTexture2D<float> X1_out;
Texture2D<float2> X2_in;
Texture2D<float2> B2_in;
RWTexture2D<float2> X2_out;
// Adjust step (translate & fade towards global velocity field)
[numthreads(8, 8, 1)]
void Adjust(uint2 tid : SV_DispatchThreadID)
{
uint2 dim;
W_out.GetDimensions(dim.x, dim.y);
float2 uv = (tid + 0.5) / dim;
float2 globalUV = (uv - .5) * _FluidTransform.z + _FluidTransform.xy;
float2 gravUV = getUV(globalUV);
float3 globalPos = float3(globalUV.x, -tex2Dlod(_NebulaSurfaceHeight, float4(gravUV, 0, 0)).x, globalUV.x);
float noise;
float3 f = flow(globalPos, noise);
float2 prevUV = uv - Delta;
if(any(prevUV<0)||any(prevUV>1))
W_out[tid] = f.xz;
else W_out[tid] = lerp(U_in.SampleLevel(samplerU_in, prevUV, 0), f.xz, Fade);
}
// Advect step
[numthreads(8, 8, 1)]
void Advect(uint2 tid : SV_DispatchThreadID)
{
uint2 dim;
W_out.GetDimensions(dim.x, dim.y);
float2 uv = (tid + 0.5) / dim;
float2 duv = U_in[tid] * float2((float)dim.y / dim.x, 1) * DeltaTime;
W_out[tid] = U_in.SampleLevel(samplerU_in, uv - duv, 0);
}
// Add-force step
[numthreads(8, 8, 1)]
void Force(uint2 tid : SV_DispatchThreadID)
{
uint2 dim;
W_out.GetDimensions(dim.x, dim.y);
float2 pos = (tid + 0.5) / dim.y;
float amp = exp(-ForceExponent * distance(ForceOrigin, pos));
W_out[tid] = W_in[tid] + ForceVector * amp;
}
// Setup for Project step (divW calculation)
[numthreads(8, 8, 1)]
void PSetup(uint2 tid : SV_DispatchThreadID)
{
uint2 dim;
W_in.GetDimensions(dim.x, dim.y);
DivW_out[tid] = (W_in[tid + int2(1, 0)].x - W_in[tid - int2(1, 0)].x +
W_in[tid + int2(0, 1)].y - W_in[tid - int2(0, 1)].y) * dim.y / 2;
P_out[tid] = 0;
}
// Finishing for Project step (divergence free field calculation)
[numthreads(8, 8, 1)]
void PFinish(uint2 tid : SV_DispatchThreadID)
{
uint2 dim;
W_in.GetDimensions(dim.x, dim.y);
if (any(tid == 0) || any(tid == dim - 1)) return;
float P1 = P_in[max(tid - int2(1, 0), 1)];
float P2 = P_in[min(tid + int2(1, 0), dim - 2)];
float P3 = P_in[max(tid - int2(0, 1), 1)];
float P4 = P_in[min(tid + int2(0, 1), dim - 2)];
float2 u = W_in[tid] - float2(P2 - P1, P4 - P3) * dim.y / 2;
U_out[tid] = u;
if (tid.x == 1) U_out[int2(0, tid.y)] = -u;
if (tid.y == 1) U_out[int2(tid.x, 0)] = -u;
if (tid.x == dim.x - 2) U_out[int2(dim.x - 1, tid.y)] = -u;
if (tid.y == dim.y - 2) U_out[int2(tid.x, dim.y - 1)] = -u;
}
// Jacobi method with a scalar field
[numthreads(8, 8, 1)]
void Jacobi1(uint2 tid : SV_DispatchThreadID)
{
X1_out[tid] = (X1_in[tid - int2(1, 0)] + X1_in[tid + int2(1, 0)] +
X1_in[tid - int2(0, 1)] + X1_in[tid + int2(0, 1)] + Alpha * B1_in[tid]) / Beta;
}
// Jacobi method with a vector field
[numthreads(8, 8, 1)]
void Jacobi2(uint2 tid : SV_DispatchThreadID)
{
X2_out[tid] = (X2_in[tid - int2(1, 0)] + X2_in[tid + int2(1, 0)] +
X2_in[tid - int2(0, 1)] + X2_in[tid + int2(0, 1)] + Alpha * B2_in[tid]) / Beta;
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cd1f70f1f6b4beb45a02e1c088f0a109
ComputeShaderImporter:
externalObjects: {}
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,215 @@
// StableFluids - A GPU implementation of Jos Stam's Stable Fluids on Unity
// https://github.com/keijiro/StableFluids
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using static Unity.Mathematics.math;
using int2 = Unity.Mathematics.int2;
using Random = UnityEngine.Random;
namespace StableFluids
{
public class Fluid : MonoBehaviour
{
#region Editable attributes
[SerializeField] int _resolution = 512;
[SerializeField] float _viscosity = 1e-6f;
[SerializeField] float _range = 512;
[SerializeField] Transform _camera;
#endregion
#region Internal resources
[SerializeField, HideInInspector] ComputeShader _compute;
[SerializeField, HideInInspector] Shader _shader;
#endregion
#region Private members
Material _shaderSheet;
int2 _previousCameraIntPosition = int2.zero;
private List<Force> _forces = new List<Force>();
struct Force
{
public float2 Position;
public float2 Vector;
public float Exponent;
}
static class Kernels
{
public const int Advect = 0;
public const int Force = 1;
public const int PSetup = 2;
public const int PFinish = 3;
public const int Jacobi1 = 4;
public const int Jacobi2 = 5;
}
int ThreadCount { get { return (_resolution + 7) / 8; } }
int Resolution { get { return ThreadCount * 8; } }
// Vector field buffers
static class VFB
{
public static RenderTexture V1;
public static RenderTexture V2;
public static RenderTexture V3;
public static RenderTexture P1;
public static RenderTexture P2;
}
RenderTexture AllocateBuffer(int componentCount)
{
var format = RenderTextureFormat.ARGBHalf;
if (componentCount == 1) format = RenderTextureFormat.RHalf;
if (componentCount == 2) format = RenderTextureFormat.RGHalf;
var rt = new RenderTexture(Resolution, Resolution, 0, format);
rt.enableRandomWrite = true;
rt.Create();
return rt;
}
#endregion
#region MonoBehaviour implementation
public void AddForce(float2 position, float2 vector, float exponent)
{
_forces.Add(new Force { Position = position, Vector = vector, Exponent = exponent });
}
void OnValidate()
{
_resolution = Mathf.Max(_resolution, 8);
}
void Start()
{
_shaderSheet = new Material(_shader);
VFB.V1 = AllocateBuffer(2);
VFB.V2 = AllocateBuffer(2);
VFB.V3 = AllocateBuffer(2);
VFB.P1 = AllocateBuffer(1);
VFB.P2 = AllocateBuffer(1);
}
void OnDestroy()
{
Destroy(_shaderSheet);
Destroy(VFB.V1);
Destroy(VFB.V2);
Destroy(VFB.V3);
Destroy(VFB.P1);
Destroy(VFB.P2);
}
void Update()
{
var dt = Time.deltaTime;
var dx = 1.0f / Resolution;
var snapLength = _range / _resolution;
// Input point
var cameraIntPosition = int2(
(int)(_camera.position.x / snapLength),
(int)(_camera.position.z / snapLength)
);
var cameraPosition = float2(
cameraIntPosition.x * snapLength,
cameraIntPosition.y * snapLength
);
Shader.SetGlobalVector("_FluidTransform", new Vector4(cameraPosition.x, cameraPosition.y, _range));
var delta = (float2)(cameraIntPosition - _previousCameraIntPosition) / Resolution;
// Common variables
_compute.SetFloat("Time", Time.time);
_compute.SetFloat("DeltaTime", dt);
// Advection
_compute.SetTexture(Kernels.Advect, "U_in", VFB.V1);
_compute.SetTexture(Kernels.Advect, "W_out", VFB.V2);
_compute.Dispatch(Kernels.Advect, ThreadCount, ThreadCount, 1);
// Diffuse setup
var dif_alpha = dx * dx / (_viscosity * dt);
_compute.SetFloat("Alpha", dif_alpha);
_compute.SetFloat("Beta", 4 + dif_alpha);
Graphics.CopyTexture(VFB.V2, VFB.V1);
_compute.SetTexture(Kernels.Jacobi2, "B2_in", VFB.V1);
// Jacobi iteration
for (var i = 0; i < 20; i++)
{
_compute.SetTexture(Kernels.Jacobi2, "X2_in", VFB.V2);
_compute.SetTexture(Kernels.Jacobi2, "X2_out", VFB.V3);
_compute.Dispatch(Kernels.Jacobi2, ThreadCount, ThreadCount, 1);
_compute.SetTexture(Kernels.Jacobi2, "X2_in", VFB.V3);
_compute.SetTexture(Kernels.Jacobi2, "X2_out", VFB.V2);
_compute.Dispatch(Kernels.Jacobi2, ThreadCount, ThreadCount, 1);
}
float2 getUV(float2 pos, float2 camPos, float scale)
{
return -(pos-camPos)/scale + float2(.5f,.5f);
}
// Add external forces
foreach(var force in _forces)
{
var uv = getUV(force.Position, cameraIntPosition, _range);
_compute.SetVector("ForceOrigin", new Vector4(uv.x,uv.y));
_compute.SetFloat("ForceExponent", force.Exponent);
_compute.SetTexture(Kernels.Force, "W_in", VFB.V2);
_compute.SetTexture(Kernels.Force, "W_out", VFB.V3);
_compute.SetVector("ForceVector", new Vector4(force.Vector.x,force.Vector.y));
_compute.Dispatch(Kernels.Force, ThreadCount, ThreadCount, 1);
}
// Projection setup
_compute.SetTexture(Kernels.PSetup, "W_in", VFB.V3);
_compute.SetTexture(Kernels.PSetup, "DivW_out", VFB.V2);
_compute.SetTexture(Kernels.PSetup, "P_out", VFB.P1);
_compute.Dispatch(Kernels.PSetup, ThreadCount, ThreadCount, 1);
// Jacobi iteration
_compute.SetFloat("Alpha", -dx * dx);
_compute.SetFloat("Beta", 4);
_compute.SetTexture(Kernels.Jacobi1, "B1_in", VFB.V2);
for (var i = 0; i < 20; i++)
{
_compute.SetTexture(Kernels.Jacobi1, "X1_in", VFB.P1);
_compute.SetTexture(Kernels.Jacobi1, "X1_out", VFB.P2);
_compute.Dispatch(Kernels.Jacobi1, ThreadCount, ThreadCount, 1);
_compute.SetTexture(Kernels.Jacobi1, "X1_in", VFB.P2);
_compute.SetTexture(Kernels.Jacobi1, "X1_out", VFB.P1);
_compute.Dispatch(Kernels.Jacobi1, ThreadCount, ThreadCount, 1);
}
// Projection finish
_compute.SetTexture(Kernels.PFinish, "W_in", VFB.V3);
_compute.SetTexture(Kernels.PFinish, "P_in", VFB.P1);
_compute.SetTexture(Kernels.PFinish, "U_out", VFB.V1);
_compute.Dispatch(Kernels.PFinish, ThreadCount, ThreadCount, 1);
_previousCameraIntPosition = cameraIntPosition;
}
#endregion
}
}

View file

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 68b35f6f5dea6274db0eda640e08abc2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- _compute: {fileID: 7200000, guid: cd1f70f1f6b4beb45a02e1c088f0a109, type: 3}
- _shader: {fileID: 4800000, guid: 0486f5f9fa757fa49a5b9613050036fb, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,80 @@
// StableFluids - A GPU implementation of Jos Stam's Stable Fluids on Unity
// https://github.com/keijiro/StableFluids
Shader "Hidden/StableFluids"
{
Properties
{
_MainTex("", 2D) = ""
_VelocityField("", 2D) = ""
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_TexelSize;
sampler2D _VelocityField;
float2 _ForceOrigin;
float _ForceExponent;
half4 frag_advect(v2f_img i) : SV_Target
{
// Time parameters
float time = _Time.y;
float deltaTime = unity_DeltaTime.x;
// Aspect ratio coefficients
float2 aspect = float2(_MainTex_TexelSize.y * _MainTex_TexelSize.z, 1);
float2 aspect_inv = float2(_MainTex_TexelSize.x * _MainTex_TexelSize.w, 1);
// Color advection with the velocity field
float2 delta = tex2D(_VelocityField, i.uv).xy * aspect_inv * deltaTime;
float3 color = tex2D(_MainTex, i.uv - delta).xyz;
// Dye (injection color)
float3 dye = saturate(sin(time * float3(2.72, 5.12, 4.98)) + 0.5);
// Blend dye with the color from the buffer.
float2 pos = (i.uv - 0.5) * aspect;
float amp = exp(-_ForceExponent * distance(_ForceOrigin, pos));
color = lerp(color, dye, saturate(amp * 100));
return half4(color, 1);
}
half4 frag_render(v2f_img i) : SV_Target
{
half3 rgb = tex2D(_MainTex, i.uv).rgb;
// Mixing channels up to get slowly changing false colors
//rgb = sin(float3(3.43, 4.43, 3.84) * rgb +
// float3(0.12, 0.23, 0.44) * _Time.y) * 0.5 + 0.5;
return half4(GammaToLinearSpace(rgb), 1);
}
ENDCG
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag_advect
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag_render
ENDCG
}
}
}

View file

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

View file

@ -44,6 +44,7 @@ uniform sampler2D _NebulaTint;
float4 _NebulaTint_TexelSize;
uniform float3 _GridTransform;
uniform float3 _FluidTransform;
uniform half _NebulaFillDensity,
_NebulaFillDistance,
@ -64,7 +65,7 @@ uniform half _NebulaFillDensity,
_FlowScale,
_FlowAmplitude,
_FlowScroll,
_FlowSpeed,
_FlowPeriod,
_SafetyDistance,
_DynamicLodRange,
_DynamicLodBias,
@ -99,14 +100,14 @@ float parabola( float x, float k )
return pow( 4.0*x*(1.0-x), k );
}
float2 getUV(float3 pos)
float2 getUV(float2 pos)
{
return -(pos.xz-_GridTransform.xy)/_GridTransform.z + float2(.5,.5);
return -(pos-_GridTransform.xy)/_GridTransform.z + float2(.5,.5);
}
float cloudDensity(float3 pos, float surfaceDisp)
{
float2 uv = getUV(pos);
float2 uv = getUV(pos.xz);
const float dist = pos.y + surfaceDisp - _NebulaFloorOffset;
const float patch = tex2Dlod(_NebulaPatch, half4(uv, 0, 0)).r;
const float patchDisp = tex2Dlod(_NebulaPatchHeight, half4(uv, 0, 0)).r;
@ -129,7 +130,7 @@ float tri2(in float x){return 1-2*abs(frac(x)-.5);}
float density(float3 pos)
{
float2 uv = getUV(pos);
float2 uv = getUV(pos.xz);
const float surfaceDisp = tex2Dlod(_NebulaSurfaceHeight, half4(uv, 0, 0)).r;
const float dist = pos.y + surfaceDisp;
float d = pow(abs(dist+_NebulaFillOffset)/_NebulaFillDistance,-_NebulaFillExponent) * _NebulaFillDensity;
@ -139,15 +140,15 @@ float density(float3 pos)
const float heightFade = smoothstep(_SafetyDistance,_SafetyDistance*.75,dist);
float noise;
const float3 fl = flow(pos, noise);
const float lerp1 = frac(_Time.x * _FlowSpeed + noise);
const float lerp2 = frac(_Time.x * _FlowSpeed + .5 + noise);
const float noise1 = pow(triNoise3d((pos+fl * lerp1) / _NebulaNoiseScale),_NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp1);
const float noise2 = pow(triNoise3d((pos+fl * lerp2) / _NebulaNoiseScale),_NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp2);
const float lerp1 = frac(_Time.y / _FlowPeriod + noise);
const float lerp2 = frac(_Time.y / _FlowPeriod + .5 + noise);
const float noise1 = pow(triNoise3d((pos+fl * lerp1 * _FlowPeriod) / _NebulaNoiseScale),_NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp1);
const float noise2 = pow(triNoise3d((pos+fl * lerp2 * _FlowPeriod) / _NebulaNoiseScale),_NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp2);
pos.y += (noise1 + noise2) * heightFade;
const float lerp3 = frac(_Time.x * _FlowSpeed * 2);
const float lerp4 = frac(_Time.x * _FlowSpeed * 2 + .5);
const float noise3 = pow(triNoise3d((pos+fl * lerp3) / _NebulaNoiseScale * 8), _NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp3) / 2;
const float noise4 = pow(triNoise3d((pos+fl * lerp4) / _NebulaNoiseScale * 8), _NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp4) / 2;
const float lerp3 = frac(_Time.y / _FlowPeriod);
const float lerp4 = frac(_Time.y / _FlowPeriod + .5);
const float noise3 = pow(triNoise3d((pos+fl * lerp3 * _FlowPeriod) / _NebulaNoiseScale * 8), _NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp3) / 2;
const float noise4 = pow(triNoise3d((pos+fl * lerp4 * _FlowPeriod) / _NebulaNoiseScale * 8), _NebulaNoiseExponent) * _NebulaNoiseAmplitude * tri2(lerp4) / 2;
pos.y -= (noise3 + noise4) * heightFade;
d += cloudDensity(pos, surfaceDisp);
}
@ -157,7 +158,7 @@ float density(float3 pos)
float4 VolumeSampleColor(float3 pos)
{
float d = density(pos);
float2 uv = getUV(pos);
float2 uv = getUV(pos.xz);
float3 tint = tex2Dlod(_NebulaTint, float4(uv.x, uv.y, 0, pow(max(.01,d), _TintLodExponent)));
const float albedo = smoothstep(0,-250,pos.y) * pow(max(.1,d), _TintExponent) * _NebulaLuminance;
return float4(albedo*tint, d);
@ -173,7 +174,7 @@ float2 tintGradient (float2 uv)
float3 VolumeSampleColorSimple(float3 pos, float3 normal)
{
float2 uv = getUV(pos);
float2 uv = getUV(pos.xz);
float3 low = tex2Dlod(_NebulaTint, float4(uv.x, uv.y, 0, _DynamicLodBias)).rgb;
float3 high = tex2Dlod(_NebulaTint, float4(uv.x, uv.y, 0, _DynamicLodBias + _DynamicLodRange)).rgb * _DynamicSkyBoost;
float upness = dot(normal, float3(0,1,0));

BIN
GameData/PlayerSettings.msgpack (Stored with Git LFS)

Binary file not shown.

BIN
UserSettings/EditorUserSettings.asset (Stored with Git LFS)

Binary file not shown.