diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/ComputeShader.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/ComputeShader.cs index ddc64ff..0dd8741 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/Rendering/ComputeShader.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/ComputeShader.cs @@ -5,6 +5,7 @@ using Silk.NET.OpenGL; namespace EngineSharp.Core.Rendering; // https://learnopengl.com/Guest-Articles/2022/Compute-Shaders/Introduction +// USE THIS FOR SENDING DATA TO SHADER FOR MANIPULATION: https://wikis.khronos.org/opengl/Buffer_Object#Creation public class ComputeShader { private readonly string _computeShaderCode; diff --git a/src/EngineSharp/assets/shaders/planet_generator.comp b/src/EngineSharp/assets/shaders/planet_generator.comp index 5419c04..0e1a3ba 100644 --- a/src/EngineSharp/assets/shaders/planet_generator.comp +++ b/src/EngineSharp/assets/shaders/planet_generator.comp @@ -1,5 +1,124 @@ #version 430 core -void main() { +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +layout(std430, binding = 0) buffer verticesArray { + vec3 vertices[]; +}; + +vec3 mod289(vec3 x) +{ + return x - floor(x / 289.0) * 289.0; +} + +vec4 mod289(vec4 x) +{ + return x - floor(x / 289.0) * 289.0; +} + +vec4 permute(vec4 x) +{ + return mod289((x * 34.0 + 1.0) * x); +} + +vec4 taylorInvSqrt(vec4 r) +{ + return 1.79284291400159 - r * 0.85373472095314; +} + +float snoise(vec3 v) +{ + const vec2 C = vec2(1.0 / 6.0, 1.0 / 3.0); + + // First corner + vec3 i = floor(v + dot(v, C.yyy)); + vec3 x0 = v - i + dot(i, C.xxx); + + // Other corners + vec3 g = step(x0.yzx, x0.xyz); + vec3 l = 1.0 - g; + vec3 i1 = min(g.xyz, l.zxy); + vec3 i2 = max(g.xyz, l.zxy); + + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + vec3 x1 = x0 - i1 + C.xxx; + vec3 x2 = x0 - i2 + C.yyy; + vec3 x3 = x0 - 0.5; + + // Permutations + i = mod289(i); // Avoid truncation effects in permutation + vec4 p = + permute(permute(permute(i.z + vec4(0.0, i1.z, i2.z, 1.0)) + + i.y + vec4(0.0, i1.y, i2.y, 1.0)) + + i.x + vec4(0.0, i1.x, i2.x, 1.0)); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + vec4 j = p - 49.0 * floor(p / 49.0); // mod(p,7*7) + + vec4 x_ = floor(j / 7.0); + vec4 y_ = floor(j - 7.0 * x_); // mod(j,N) + + vec4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0; + vec4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0; + + vec4 h = 1.0 - abs(x) - abs(y); + + vec4 b0 = vec4(x.xy, y.xy); + vec4 b1 = vec4(x.zw, y.zw); + + //vec4 s0 = vec4(lessThan(b0, 0.0)) * 2.0 - 1.0; + //vec4 s1 = vec4(lessThan(b1, 0.0)) * 2.0 - 1.0; + vec4 s0 = floor(b0) * 2.0 + 1.0; + vec4 s1 = floor(b1) * 2.0 + 1.0; + vec4 sh = -step(h, 0.0); + + vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy; + vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww; + + vec3 g0 = vec3(a0.xy, h.x); + vec3 g1 = vec3(a0.zw, h.y); + vec3 g2 = vec3(a1.xy, h.z); + vec3 g3 = vec3(a1.zw, h.w); + + // Normalise gradients + vec4 norm = taylorInvSqrt(vec4(dot(g0, g0), dot(g1, g1), dot(g2, g2), dot(g3, g3))); + g0 *= norm.x; + g1 *= norm.y; + g2 *= norm.z; + g3 *= norm.w; + + // Mix final noise value + vec4 m = max(0.6 - vec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), 0.0); + m = m * m; + m = m * m; + + vec4 px = vec4(dot(x0, g0), dot(x1, g1), dot(x2, g2), dot(x3, g3)); + return 42.0 * dot(m, px); +} + +float simpleNoise(float3 pos) { + const float scale = 1; + const float multiplier = 1; + + return simpleNoise(pos, scale, multiplier); +} + +void main() { + uint idx = gl_GlobalInvocationID.x; + if (idx >= vertices.length()) // If out of range, return + { + return; + } + + vec3 pos = vertices[idx]; + + float noise = simpleNoise(pos); + noise = smoothMax(noise, -oceanSettings.x, oceanSettings.y); // oceanDepth and smoothing + + float finalHeight = 1 + noise * 0.01; + + vertices[idx] = pos * finalHeight; } \ No newline at end of file