Added fog on the main scene
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
float pcg_hash3(uint3 p)
|
||||
{
|
||||
const uint M = 1664525u;
|
||||
const uint C = 1013904223u;
|
||||
|
||||
uint3 state = p * M + C;
|
||||
state = state ^ (state >> 16u);
|
||||
state *= M;
|
||||
state += C;
|
||||
state = state ^ (state >> 16u);
|
||||
|
||||
uint hash = state.x ^ state.y ^ state.z;
|
||||
|
||||
return float(hash) / 4294967296.0;
|
||||
}
|
||||
|
||||
struct VoronoiOutput {
|
||||
float distance;
|
||||
float3 color;
|
||||
float3 position;
|
||||
};
|
||||
|
||||
struct VoronoiParams {
|
||||
float randomness;
|
||||
float smoothness;
|
||||
float metric; // 0=Euclidean, 1=Manhattan, 2=Chebychev
|
||||
float scale;
|
||||
};
|
||||
|
||||
float3 hash_int3_to_float3(int3 p) {
|
||||
uint3 q = uint3(p) * uint3(1597334673u, 3812015801u, 2912667907u);
|
||||
q = (q.x ^ q.y ^ q.z) * uint3(1597334673u, 3812015801u, 2912667907u);
|
||||
return float3(q) / float(0xFFFFFFFFu);
|
||||
}
|
||||
|
||||
float voronoi_distance(float3 a, float3 b, VoronoiParams params) {
|
||||
float3 d = abs(a - b);
|
||||
|
||||
if (params.metric == 0.0) { // Euclidean
|
||||
return length(d);
|
||||
}
|
||||
else if (params.metric == 1.0) { // Manhattan
|
||||
return d.x + d.y + d.z;
|
||||
}
|
||||
else { // Chebychev
|
||||
return max(max(d.x, d.y), d.z);
|
||||
}
|
||||
}
|
||||
|
||||
VoronoiOutput voronoi_smooth_f1(VoronoiParams params, float3 coord) {
|
||||
coord *= params.scale;
|
||||
|
||||
const float3 cellPosition_f = floor(coord);
|
||||
const float3 localPosition = coord - cellPosition_f;
|
||||
const int3 cellPosition = int3(cellPosition_f);
|
||||
|
||||
float smoothDistance = 0.0;
|
||||
float3 smoothColor = float3(0.0, 0.0, 0.0);
|
||||
float3 smoothPosition = float3(0.0, 0.0, 0.0);
|
||||
float h = -1.0;
|
||||
|
||||
[unroll]
|
||||
for (int k = -2; k <= 2; k++) {
|
||||
[unroll]
|
||||
for (int j = -2; j <= 2; j++) {
|
||||
[unroll]
|
||||
for (int i = -2; i <= 2; i++) {
|
||||
const int3 cellOffset = int3(i, j, k);
|
||||
const float3 pointPosition = float3(cellOffset) +
|
||||
hash_int3_to_float3(cellPosition + cellOffset) *
|
||||
params.randomness;
|
||||
const float distanceToPoint = voronoi_distance(pointPosition, localPosition, params);
|
||||
|
||||
h = h == -1.0 ?
|
||||
1.0 :
|
||||
smoothstep(0.0, 1.0, 0.5 + 0.5 * (smoothDistance - distanceToPoint) / params.smoothness);
|
||||
|
||||
float correctionFactor = params.smoothness * h * (1.0 - h);
|
||||
smoothDistance = lerp(smoothDistance, distanceToPoint, h) - correctionFactor;
|
||||
correctionFactor /= 1.0 + 3.0 * params.smoothness;
|
||||
|
||||
const float3 cellColor = hash_int3_to_float3(cellPosition + cellOffset);
|
||||
smoothColor = lerp(smoothColor, cellColor, h) - correctionFactor;
|
||||
smoothPosition = lerp(smoothPosition, pointPosition, h) - correctionFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoronoiOutput octave;
|
||||
octave.distance = smoothDistance / params.scale;
|
||||
octave.color = smoothColor;
|
||||
octave.position = (cellPosition_f + smoothPosition) / params.scale;
|
||||
return octave;
|
||||
}
|
||||
|
||||
float voronoi_distance_fast(float3 a, float3 b, VoronoiParams params)
|
||||
{
|
||||
float3 diff = a - b;
|
||||
return dot(diff, diff);
|
||||
}
|
||||
|
||||
float3 hash_int3_to_float3_optimized(int3 cell)
|
||||
{
|
||||
uint3 p = uint3(cell);
|
||||
p = p * 1664525u + 1013904223u;
|
||||
p.x += p.y*p.z;
|
||||
p.y += p.z*p.x;
|
||||
p.z += p.x*p.y;
|
||||
p ^= p >> 16u;
|
||||
p = p * 1664525u + 1013904223u;
|
||||
return float3(p & uint3(0x00FFFFFFu, 0x00FFFFFFu, 0x00FFFFFFu)) / float(0x00FFFFFFu);
|
||||
}
|
||||
|
||||
VoronoiOutput voronoi_simple_f1(VoronoiParams params, float3 coord)
|
||||
{
|
||||
coord *= params.scale;
|
||||
|
||||
float3 cellPosition_f = floor(coord);
|
||||
float3 localPosition = coord - cellPosition_f;
|
||||
int3 cellPosition = int3(cellPosition_f);
|
||||
|
||||
int3 targetOffset = int3(0, 0, 0);
|
||||
float3 pointPosition = hash_int3_to_float3(cellPosition) * params.randomness;
|
||||
float minDistance = voronoi_distance_fast(pointPosition, localPosition, params);
|
||||
float3 targetPosition = pointPosition;
|
||||
|
||||
for (int k = -1; k <= 1; k++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
//manual unroll
|
||||
{
|
||||
int i = -1;
|
||||
int3 cellOffset = int3(i, j, k);
|
||||
pointPosition = float3(cellOffset) +
|
||||
hash_int3_to_float3(cellPosition + cellOffset) *
|
||||
params.randomness;
|
||||
float distanceToPoint = voronoi_distance_fast(pointPosition, localPosition, params);
|
||||
if (distanceToPoint < minDistance) {
|
||||
targetOffset = cellOffset;
|
||||
minDistance = distanceToPoint;
|
||||
targetPosition = pointPosition;
|
||||
}
|
||||
}
|
||||
{
|
||||
int i = 0;
|
||||
int3 cellOffset = int3(i, j, k);
|
||||
pointPosition = float3(cellOffset) +
|
||||
hash_int3_to_float3(cellPosition + cellOffset) *
|
||||
params.randomness;
|
||||
float distanceToPoint = voronoi_distance_fast(pointPosition, localPosition, params);
|
||||
if (distanceToPoint < minDistance) {
|
||||
targetOffset = cellOffset;
|
||||
minDistance = distanceToPoint;
|
||||
targetPosition = pointPosition;
|
||||
}
|
||||
}
|
||||
{
|
||||
int i = 1;
|
||||
int3 cellOffset = int3(i, j, k);
|
||||
pointPosition = float3(cellOffset) +
|
||||
hash_int3_to_float3(cellPosition + cellOffset) *
|
||||
params.randomness;
|
||||
float distanceToPoint = voronoi_distance_fast(pointPosition, localPosition, params);
|
||||
if (distanceToPoint < minDistance) {
|
||||
targetOffset = cellOffset;
|
||||
minDistance = distanceToPoint;
|
||||
targetPosition = pointPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VoronoiOutput octave;
|
||||
octave.distance = minDistance / params.scale;
|
||||
octave.color = hash_int3_to_float3(cellPosition + targetOffset);
|
||||
octave.position = (targetPosition + cellPosition_f) / params.scale;
|
||||
return octave;
|
||||
}
|
||||
|
||||
void PainterlyNormalsSimple_float(float3 normalOS, float randomness, float scale, out float3 normal, out float3 color, out float distance) {
|
||||
VoronoiParams params;
|
||||
params.randomness = randomness;
|
||||
params.scale = scale;
|
||||
|
||||
VoronoiOutput result = voronoi_simple_f1(params, normalOS);
|
||||
normal = result.position;
|
||||
color = result.color;
|
||||
distance = result.distance;
|
||||
}
|
||||
|
||||
void PainterlyNormalsSimple_half(half3 normalOS, half randomness, half scale, out half3 normal, out half3 color, out half distance) {
|
||||
VoronoiParams params;
|
||||
params.randomness = randomness;
|
||||
params.scale = scale;
|
||||
|
||||
VoronoiOutput result = voronoi_simple_f1(params, normalOS);
|
||||
normal = result.position;
|
||||
color = result.color;
|
||||
distance = result.distance;
|
||||
}
|
||||
|
||||
void PainterlyNormals_float(float3 normalOS, float randomness, float smoothness, float metric, float scale, out float3 normal, out float3 color, out float distance) {
|
||||
VoronoiParams params;
|
||||
params.randomness = randomness;
|
||||
params.smoothness = smoothness;
|
||||
params.metric = metric;
|
||||
params.scale = scale;
|
||||
|
||||
VoronoiOutput result = voronoi_smooth_f1(params, normalOS);
|
||||
normal = result.position;
|
||||
color = result.color;
|
||||
distance = result.distance;
|
||||
}
|
||||
|
||||
void PainterlyNormals_half(half3 normalOS, half randomness, half smoothness, half metric, half scale, out half3 normal, out half3 color, out half distance) {
|
||||
VoronoiParams params;
|
||||
params.randomness = randomness;
|
||||
params.smoothness = smoothness;
|
||||
params.metric = metric;
|
||||
params.scale = scale;
|
||||
|
||||
VoronoiOutput result = voronoi_smooth_f1(params, normalOS);
|
||||
normal = result.position;
|
||||
color = result.color;
|
||||
distance = result.distance;
|
||||
}
|
||||
Reference in New Issue
Block a user