From fda2ce879ccac56b3a11160d1bb66053837674dd Mon Sep 17 00:00:00 2001 From: Kseninia Mikhaylova Date: Tue, 1 Oct 2024 11:16:47 +0300 Subject: [PATCH] shader --- utils/dith.frag | 3 + utils/main.frag | 51 ++++++++++++++ utils/material.ts | 56 ++++++++++----- utils/normal.frag | 4 ++ utils/pnoise.glsl | 171 ++++++++++++++++++++++++++++++++++++++++++++++ utils/vertex.vert | 6 ++ 6 files changed, 275 insertions(+), 16 deletions(-) create mode 100644 utils/dith.frag create mode 100644 utils/main.frag create mode 100644 utils/normal.frag create mode 100644 utils/pnoise.glsl create mode 100644 utils/vertex.vert diff --git a/utils/dith.frag b/utils/dith.frag new file mode 100644 index 0000000..3ff65b5 --- /dev/null +++ b/utils/dith.frag @@ -0,0 +1,3 @@ +#include + +// gl_FragColor = vec4(normal, 1.0); \ No newline at end of file diff --git a/utils/main.frag b/utils/main.frag new file mode 100644 index 0000000..6af0c18 --- /dev/null +++ b/utils/main.frag @@ -0,0 +1,51 @@ +float random(in float x) { + return fract(sin(x) * 1e4); +} + + // Based on Morgan McGuire @morgan3d + // https://www.shadertoy.com/view/4dS3Wd +float noise(in vec3 p) { + const vec3 step = vec3(110.0, 241.0, 171.0); + + vec3 i = floor(p); + vec3 f = fract(p); + + // For performance, compute the base input to a + // 1D random from the integer part of the + // argument and the incremental change to the + // 1D based on the 3D -> 1D wrapping + float n = dot(i, step); + + vec3 u = f * f * (3.0 - 2.0 * f); + return mix(mix(mix(random(n + dot(step, vec3(0, 0, 0))), random(n + dot(step, vec3(1, 0, 0))), u.x), mix(random(n + dot(step, vec3(0, 1, 0))), random(n + dot(step, vec3(1, 1, 0))), u.x), u.y), mix(mix(random(n + dot(step, vec3(0, 0, 1))), random(n + dot(step, vec3(1, 0, 1))), u.x), mix(random(n + dot(step, vec3(0, 1, 1))), random(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); +} + +// +// by inigo quilez +// + +vec3 hash3(vec2 p) { + vec3 q = vec3(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)), dot(p, vec2(419.2, 371.9))); + return fract(sin(q) * 43758.5453); +} + +float iqnoise(in vec2 x, float u, float v) { + vec2 p = floor(x); + vec2 f = fract(x); + + float k = 1.0 + 63.0 * pow(1.0 - v, 4.0); + + float va = 0.0; + float wt = 0.0; + for(int j = -2; j <= 2; j++) for(int i = -2; i <= 2; i++) { + vec2 g = vec2(float(i), float(j)); + vec3 o = hash3(p + g) * vec3(u, u, 1.0); + vec2 r = g - f + o.xy; + float d = dot(r, r); + float ww = pow(1.0 - smoothstep(0.0, 1.414, sqrt(d)), k); + va += o.z * ww; + wt += ww; + } + + return va / wt; +} \ No newline at end of file diff --git a/utils/material.ts b/utils/material.ts index 94fa2ee..d2f0498 100644 --- a/utils/material.ts +++ b/utils/material.ts @@ -1,5 +1,15 @@ -import { Color, DataTexture, DoubleSide, MeshBasicMaterial, MeshStandardMaterial, RepeatWrapping, RGBFormat, Texture, TextureLoader, Vector2 } from "three" + +import { + Color, DataTexture, DoubleSide, + MeshStandardMaterial, RepeatWrapping, + Texture, TextureLoader, Vector3 +} from "three" import { useLoader, } from '@tresjs/core' +import vertexShader from './vertex.vert?raw' +import mainShader from './main.frag?raw' +import normalShader from './normal.frag?raw' +import dithShader from './dith.frag?raw' +import noiseShader from './pnoise.glsl?raw' import { getFilename, patterns, } from "~/components/pattern" @@ -55,40 +65,54 @@ const m = new MeshStandardMaterial({ side: DoubleSide, }) +const v = new Vector3() +v.setScalar(0.7) const m_onBeforeCompile = (shader) => { // Добавляем uniform переменную - shader.uniforms.customUniform = { value: 1.0 }; + shader.uniforms.u_resolution = { value: v }; // Изменяем вершинный шейдер shader.vertexShader = ` - uniform float customUniform; - varying vec2 vPosition; + uniform vec3 u_resolution; + + varying float vDistance; + varying vec3 vPosition; + + flat varying int vertexID; + + varying vec2 vUv; + varying float noise; + ${shader.vertexShader} `.replace( `#include `, `#include - vPosition = position.xy; + ${vertexShader} ` ); // Изменяем фрагментный шейдер shader.fragmentShader = ` - float random(float p) { - return fract(sin(p) * 10000.0); - } + uniform vec3 u_resolution; + + varying float vDistance; + varying vec3 vPosition; + int vertexID; - float noise(vec2 p) { - return random((p.x + p.y) * 10000.0); - } - ${shader.fragmentShader} - ` + ${noiseShader} + ${mainShader} + ${shader.fragmentShader}` + .replace( + '#include ', + `#include + ${normalShader} + ` + ) .replace( `#include `, `#include - float noise_v = noise(gl_FragColor.rg); - float clamped_noise = clamp(noise_v, 0.85, 1.0); - gl_FragColor.rgb *= vec3(clamped_noise); + ${dithShader} ` ); }; diff --git a/utils/normal.frag b/utils/normal.frag new file mode 100644 index 0000000..5a3f663 --- /dev/null +++ b/utils/normal.frag @@ -0,0 +1,4 @@ +float noise = pnoise( 1000.0 * vPosition, vec3( 1000.0 ) ); +vec3 modifiedNormal = normal - vec3(noise) * 0.05; +// modifiedNormal = vec3(noise); +normal = vec3(modifiedNormal); \ No newline at end of file diff --git a/utils/pnoise.glsl b/utils/pnoise.glsl new file mode 100644 index 0000000..cdc70be --- /dev/null +++ b/utils/pnoise.glsl @@ -0,0 +1,171 @@ +// +// GLSL textureless classic 3D noise "cnoise", +// with an RSL-style periodic variant "pnoise". +// Author: Stefan Gustavson (stefan.gustavson@liu.se) +// Version: 2011-10-11 +// +// Many thanks to Ian McEwan of Ashima Arts for the +// ideas for permutation and gradient selection. +// +// Copyright (c) 2011 Stefan Gustavson. All rights reserved. +// Distributed under the MIT license. See LICENSE file. +// https://github.com/stegu/webgl-noise +// + +vec3 mod289(vec3 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 mod289(vec4 x) { + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 permute(vec4 x) { + return mod289(((x * 34.0) + 10.0) * x); +} + +vec4 taylorInvSqrt(vec4 r) { + return 1.79284291400159 - 0.85373472095314 * r; +} + +vec3 fade(vec3 t) { + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +// Classic Perlin noise +float cnoise(vec3 P) { + vec3 Pi0 = floor(P); // Integer part for indexing + vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 + Pi0 = mod289(Pi0); + Pi1 = mod289(Pi1); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 * (1.0 / 7.0); + vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 * (1.0 / 7.0); + vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +// Classic Perlin noise, periodic variant +float pnoise(vec3 P, vec3 rep) { + vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period + vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period + Pi0 = mod289(Pi0); + Pi1 = mod289(Pi1); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 * (1.0 / 7.0); + vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 * (1.0 / 7.0); + vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} \ No newline at end of file diff --git a/utils/vertex.vert b/utils/vertex.vert new file mode 100644 index 0000000..1b3f21f --- /dev/null +++ b/utils/vertex.vert @@ -0,0 +1,6 @@ +vertexID = gl_VertexID; +vPosition = position.xyz + normal; +vUv = uv; + +float distanceToNextVertex = length(u_resolution - vec3(0.0, 0.0, 0.0)); +vDistance = distanceToNextVertex; \ No newline at end of file