Skip to content

Commit

Permalink
Improved 3D clouds shape some more + a few other things
Browse files Browse the repository at this point in the history
  • Loading branch information
zombye committed Aug 30, 2019
1 parent f9f0fd3 commit d72ea5e
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 48 deletions.
36 changes: 36 additions & 0 deletions scripts/gen2DNoise.py
@@ -0,0 +1,36 @@
import math
import numpy as np
import png

resolution = 256
shift = 97

# generate values then shuffle them, instead of just generating random values
# this ensures a flat histogram
noise = np.zeros(resolution * resolution, 'uint8')
for r in range(int(resolution * resolution / 256)):
for v in range(256):
noise[r * 256 + v] = v
np.random.shuffle(noise)
noise = np.reshape(noise, (resolution, resolution))

# TODO: turn into blue noise here?
# possible algorithm idea for that:
# a pixel exerts a "force" on similar nearby values to "push" them away
# two nearby pixels are swapped if the net force put on them would decrease after the swap
# idk how well this would work but i'm pretty sure it _should_ work, right?

image = np.zeros((resolution, resolution, 3), 'uint8')
for x in range(resolution):
for y in range(resolution):
image[x, y, 0] = noise[x, y]

for x in range(resolution):
for y in range(resolution):
image[x, y, 1] = image[(x + shift) % resolution, (y + shift) % resolution, 0]

image_reshaped = np.reshape(image, (resolution, resolution * 3))

writer = png.Writer(width=resolution, height=resolution)
with open('./noise.png', 'wb') as file:
writer.write(file, image_reshaped)
Binary file modified shaders/image/noise.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 14 additions & 13 deletions shaders/include/fragment/clouds3D.fsh
Expand Up @@ -12,13 +12,13 @@
#define CLOUDS3D_NOISE_OCTAVES_3D 3 // 3D noise octaves, adds detail.

// shape
#define CLOUDS3D_STATIC_COVERAGE 0.35 // [0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1]
#define CLOUDS3D_STATIC_COVERAGE 0.4 // [0 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1]

#define CLOUDS3D_USE_WORLD_TIME
#define CLOUDS3D_SPEED 4.8 // [0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3 3.2 3.4 3.6 3.8 4 4.2 4.4 4.6 4.8 5 5.2 5.4 5.6 5.8 6 6.2 6.4 6.6 6.8 7 7.2 7.4 7.6 7.8 8 8.2 8.4 8.6 8.8 9 9.2 9.4 9.6 9.8 10]
#define CLOUDS3D_ALTITUDE 500 // [300 400 500 600 700 800 900 1000]
#define CLOUDS3D_THICKNESS_MULT 1 // [0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2]
#define CLOUDS3D_SCALE 2 // [1 1.4 2 2.8 4]
#define CLOUDS3D_SPEED 3 // [0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2 2.2 2.4 2.6 2.8 3 3.2 3.4 3.6 3.8 4 4.2 4.4 4.6 4.8 5 5.2 5.4 5.6 5.8 6 6.2 6.4 6.6 6.8 7 7.2 7.4 7.6 7.8 8 8.2 8.4 8.6 8.8 9 9.2 9.4 9.6 9.8 10]
#define CLOUDS3D_ALTITUDE 700 // [300 400 500 600 700 800 900 1000]
#define CLOUDS3D_THICKNESS_MULT 0.7 // [0.5 0.6 0.7 0.8 0.9 1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2]
#define CLOUDS3D_SCALE 1.4 // [1 1.4 2 2.8 4]

#define CLOUDS3D_THICKNESS (CLOUDS3D_ALTITUDE * CLOUDS3D_THICKNESS_MULT)
#define CLOUDS3D_ALTITUDE_MIN CLOUDS3D_ALTITUDE
Expand Down Expand Up @@ -63,7 +63,7 @@ float Get3DCloudsDensity(vec3 position) {
float coverageFade = Clamp01(cloudAltitude);
coverageFade = 1.0 - coverageFade * coverageFade;
float coverage = mix(CLOUDS3D_STATIC_COVERAGE, 1.0, wetness) * coverageFade;
float cloudsMask = Clamp01(2.5 * (noise2D + coverage + 0.2 - 1.0));
float cloudsMask = Clamp01(2.5 * (noise2D + coverage + 0.125 - 1.0));

// return early if no clouds
if (cloudsMask <= 0.0) { return 0.0; }
Expand All @@ -72,17 +72,18 @@ float Get3DCloudsDensity(vec3 position) {

const int octaves3D = CLOUDS3D_NOISE_OCTAVES_3D;

vec3 noisePos3D = position * (3.0 / CLOUDS3D_THICKNESS) - cloudsTime * vec3(11.0, 4.0, 11.0);
vec3 noisePos3D = position * (4.5 / CLOUDS3D_THICKNESS) - cloudsTime * vec3(16.5, 6.0, 16.5);

//float noise3D = mix(abs(GetNoise3D(colortex7, noisePos3D * 0.015625).x * 2.0 - 1.0), 1.65 * GetNoise3D(colortex7, noisePos3D * 0.1).y, cloudAltitude);
float noise3D = mix(abs(GetNoise(noisePos3D) * 2.0 - 1.0), 1.65 * GetNoise3D(colortex7, noisePos3D * 0.1).y, cloudAltitude);
for (int i = 1; i < octaves3D; ++i) {
float noise3D = dot(GetNoise3D(colortex7, noisePos3D * 0.1), vec2(0.2, 1.0));

noisePos3D *= 6.4;
for (int i = 2; i < octaves3D; ++i) {
noisePos3D.xz *= rotateGoldenAngle;
noisePos3D = noisePos3D * pi - cloudsTime;
//noise3D += GetNoise3D(colortex7, noisePos3D * 0.015625).x * exp2(-i);
noise3D += GetNoise(noisePos3D) * exp2(-i);
} noise3D = noise3D * 0.5 + (0.5 * exp2(-octaves3D));
noise3D *= noise3D * (3.0 - 2.0 * noise3D);
noise3D += GetNoise(noisePos3D) * 0.5 * exp2(-i);
} noise3D += 0.5 * exp2(-octaves3D);
noise3D = max(noise3D - 0.25, 0.0);

float densityScale = Clamp01(cloudAltitude * 2.0);
return Clamp01(2.0 * cloudsMask - noise3D) * densityScale;
Expand Down
4 changes: 2 additions & 2 deletions shaders/include/fragment/waterNormal.fsh
Expand Up @@ -8,10 +8,10 @@ float GetSmoothNoise(vec2 coord) {
coord -= floored;
coord *= coord * (3.0 - 2.0 * coord);
coord += floored - 0.5;
return texture(noisetex, 0.015625 * coord).r;
return texture(noisetex, coord / 256.0).r;
//*/

vec4 samples = textureGather(noisetex, 0.015625 * floored); // textureGather is slightly offset (at least on nvidia) and this offset can change with driver versions, which is why i floor the coords
vec4 samples = textureGather(noisetex, floored / 256.0); // textureGather is slightly offset (at least on nvidia) and this offset can change with driver versions, which is why i floor the coords
vec4 weights = (coord - floored).xxyy;
weights.yw = 1.0 - weights.yw;
weights *= weights * (-2.0 * weights + 3.0);
Expand Down
12 changes: 6 additions & 6 deletions shaders/include/utility/noise.glsl
Expand Up @@ -4,14 +4,14 @@
//--// Texture noise //-------------------------------------------------------//

float GetNoise(sampler2D noiseSampler, vec2 position) {
return texture(noiseSampler, 0.015625 * position).x;
return texture(noiseSampler, position / 256.0).x;
}
vec2 GetNoise2HQ(sampler2D noiseSampler, vec2 position) {
vec2 f = fract(position);
ivec2 i = ivec2(position - f);

vec4 samples0 = textureGather(noiseSampler, 0.015625 * i, 0);
vec4 samples1 = textureGather(noiseSampler, 0.015625 * i, 1);
vec4 samples0 = textureGather(noiseSampler, i / 256.0, 0);
vec4 samples1 = textureGather(noiseSampler, i / 256.0, 1);

vec4 w = f.xxyy;
w.yw = 1.0 - w.yw;
Expand All @@ -22,7 +22,7 @@ vec2 GetNoise2HQ(sampler2D noiseSampler, vec2 position) {
float GetNoise(sampler2D noiseSampler, vec3 position) {
float flr = floor(position.z);

vec2 coord = (position.xy * 0.015625) + (flr * 0.265625); // 1/64 | 17/64
vec2 coord = (position.xy / 256.0) + (flr * (97.0/256.0));
vec2 noise = texture(noiseSampler, coord).xy;

return mix(noise.x, noise.y, position.z - flr);
Expand All @@ -38,15 +38,15 @@ float GetNoiseSmooth(sampler2D noiseSampler, vec2 position) {
vec2 frc = position - flr;
frc *= frc * (3.0 - 2.0 * frc);

vec2 coord = (flr.xy + frc.xy) * 0.015625; // 1/64
vec2 coord = (flr.xy + frc.xy) / 256.0;
return texture(noiseSampler, coord).x;
}
float GetNoiseSmooth(sampler2D noiseSampler, vec3 position) {
vec3 flr = floor(position);
vec3 frc = position - flr;
frc *= frc * (3.0 - 2.0 * frc);

vec2 coord = ((flr.xy + frc.xy) * 0.015625) + (flr.z * 0.265625); // 1/64 | 17/64
vec2 coord = ((flr.xy + frc.xy) / 256.0) + (flr.z * (97.0/256.0));
vec2 noise = texture(noiseSampler, coord).xy;

return mix(noise.x, noise.y, frc.z);
Expand Down
39 changes: 14 additions & 25 deletions shaders/include/vertex/animation.vsh
@@ -1,18 +1,6 @@
#if !defined INCLUDE_VERTEX_ANIMATION
#define INCLUDE_VERTEX_ANIMATION

vec4 TextureBilinear(sampler2D sampler, vec2 coord, ivec2 resolution) {
coord = coord * resolution - 0.5;
ivec2 i = ivec2(floor(coord));
vec2 f = coord - i;

vec4 s0 = texelFetch(sampler, (i + ivec2(0,0)) % resolution, 0);
vec4 s1 = texelFetch(sampler, (i + ivec2(1,0)) % resolution, 0);
vec4 s2 = texelFetch(sampler, (i + ivec2(0,1)) % resolution, 0);
vec4 s3 = texelFetch(sampler, (i + ivec2(1,1)) % resolution, 0);

return mix(mix(s0, s1, f.x), mix(s2, s3, f.x), f.y);
}
vec4 TextureBicubic(sampler2D sampler, vec2 coord) {
ivec2 res = textureSize(sampler, 0);

Expand All @@ -22,20 +10,21 @@ vec4 TextureBicubic(sampler2D sampler, vec2 coord) {
coord -= f;

vec2 ff = f * f;
vec4 w0, w1;
w0.xz = 1.0 - f; w0.xz *= w0.xz * w0.xz;
w1.yw = ff * f;
w1.xz = 3.0 * w1.yw + 4.0 - 6.0 * ff;
w0.yw = 6.0 - w1.xz - w1.yw - w0.xz;

vec4 s = w0 + w1;
vec4 c = coord.xxyy + vec4(-0.5, 1.5, -0.5, 1.5) + w1 / s;
c /= res.xxyy;
vec2 w0 = ff * f;
vec2 w3 = 1.0 - f; w3 *= w3 * w3;
vec2 w1 = w3 + 6.0 * f - 2.0 * w0;
vec2 w2 = 3.0 * w0 + 4.0 - 6.0 * ff;

vec4 s = vec4(w3, w1) + vec4(w2, w0);
vec4 c = coord.xyxy + vec4(w2, w0) / s;
c.xy -= 0.5; c.zw += 1.5;
c /= res.xyxy;

vec2 m = s.xz / (s.xz + s.yw);
vec2 m = s.zw / (s.xy + s.zw);
return mix(
mix(TextureBilinear(sampler, c.yw, res), TextureBilinear(sampler, c.xw, res), m.x),
mix(TextureBilinear(sampler, c.yz, res), TextureBilinear(sampler, c.xz, res), m.x),
mix(texture(sampler, c.xy), texture(sampler, c.zy), m.x),
mix(texture(sampler, c.xw), texture(sampler, c.zw), m.x),
m.y
);
}
Expand All @@ -62,8 +51,8 @@ vec3 AnimatePlant(
// 10.0 km/h ~= 2.78
// 15.0 km/h ~= 4.16

vec2 noiseUv = worldPosition.xz + mod(time * 2.0, 64.0); // 7.2 km/h
vec2 noise = TextureBicubic(noisetex, noiseUv / 64.0).xy * 1.5 - 1.0;
vec2 noiseUv = worldPosition.xz + mod(time * 2.0, 256.0); // 7.2 km/h
vec2 noise = TextureBicubic(noisetex, noiseUv / 256.0).xy * 1.5 - 1.0;
vec2 rotation = vec2(atan(noise.y, noise.x), length(noise.xy) * MaxOf(abs(normalize(noise.xy))) * 0.2);
if (isTopHalf && isTopEdge) {
rotation *= 1.5;
Expand Down
2 changes: 1 addition & 1 deletion shaders/internalSettings.glsl
@@ -1,5 +1,5 @@
/*
const int noiseTextureResolution = 64; // Needed for noisetex to work at all.
const int noiseTextureResolution = 256; // Needed for noisetex to work at all.
const float sunPathRotation = -35; // [-80 -79 -78 -77 -76 -75 -74 -73 -72 -71 -70 -69 -68 -67 -66 -65 -64 -63 -62 -61 -60 -59 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -32 -31 -30 -29 -28 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80]
const float ambientOcclusionLevel = 1.0;
Expand Down
2 changes: 1 addition & 1 deletion shaders/settings.glsl
Expand Up @@ -16,7 +16,7 @@
#define RESOURCE_FORMAT_CONTINUUM2 3
#define RESOURCE_FORMAT_LAB 4
#define RESOURCE_FORMAT_WIP 5
#define RESOURCE_FORMAT RESOURCE_FORMAT_CONTINUUM2 // [RESOURCE_FORMAT_GREYSCALE RESOURCE_FORMAT_OPBR RESOURCE_FORMAT_CONTINUUM2 RESOURCE_FORMAT_LAB RESOURCE_FORMAT_WIP]
#define RESOURCE_FORMAT RESOURCE_FORMAT_LAB // [RESOURCE_FORMAT_GREYSCALE RESOURCE_FORMAT_OPBR RESOURCE_FORMAT_CONTINUUM2 RESOURCE_FORMAT_LAB RESOURCE_FORMAT_WIP]

//--// Ambient Occlusion //---------------------------------------------------//

Expand Down

0 comments on commit d72ea5e

Please sign in to comment.