Example 2
Example 2
#ifdef GL_ES
precision mediump float;
#define GLSLIFY 1
#endif
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
#define GLSLIFY 1
#define USE_TORUS
float hash12_1(vec2 p) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
float noise_3_782122993(in vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
vec3 u = f*f*(3.0-2.0*f);
vec2 ii = i.xy + i.z * vec2(5.0);
float a = hash12_1( ii + vec2(0.0,0.0) );
float b = hash12_1( ii + vec2(1.0,0.0) );
float c = hash12_1( ii + vec2(0.0,1.0) );
float d = hash12_1( ii + vec2(1.0,1.0) );
float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
ii += vec2(5.0);
a = hash12_1( ii + vec2(0.0,0.0) );
b = hash12_1( ii + vec2(1.0,0.0) );
c = hash12_1( ii + vec2(0.0,1.0) );
d = hash12_1( ii + vec2(1.0,1.0) );
float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
return max(mix(v1,v2,u.z),0.0);
}
float sdBox_0( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdBox_0( vec3 p)
{
vec3 b=vec3(0.4);
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdSphere_0( vec3 p, float s )
{
return length(p)-s;
}
float sdTorus_1( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xy)-t.x,p.z);
return length(q)-t.y;
}
mat3 fromEuler_0(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
vec3 m0 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,
a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
vec3 m1 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
vec3 m2 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,
a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return mat3(m0, m1, m2);
}
float map_3(in vec3 p)
{
float bump=0.002 * (noise_3_782122993(p*60.0)*2.0-1.0);
#ifdef USE_SPIN
mat3 rot=fromEuler_0(vec3(0.0,0.0,u_time*0.5));
#else
mat3 rot=fromEuler_0(vec3(0.0,0.0,0.5));
#endif
vec3 p1=(p+vec3(0.0,-0.0,1.5))*rot;
vec3 p2=(p+vec3(1.5,-0.5,0.0))*-rot;
vec3 p3=(p+vec3(-1.5,-0.8,0.0))*-rot;
vec3 p4=(p+vec3(0.0,-0.3,-1.5))*rot;
#ifdef USE_BOX
return sdBox_0(p1,vec3(0.4));
#elif defined(USE_SPHERE)
return sdSphere_0(p1+vec3(0.,0.,0.0), 0.5)+bump;
#elif defined(USE_TORUS)
return sdTorus_1(p+vec3(0.,0.,1.5),vec2(0.4,0.2))+bump;
#else
return sdBox_0(p1,vec3(0.4));
#endif
//return min(min(min(sdBox(p1),sdBox(p2)),sdBox(p3)),sdBox(p4));
}
float trace(vec3 o, vec3 r, out vec3 p)
{
float d=0.0, t=0.0;
for (int i=0; i<32; ++i)
{
p= o+r*t;
d=map_3(p);
if(d<0.0) break;
t += d*0.8; //
}
return t;
}
float sdTorus_0( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xy)-t.x,p.z);
return length(q)-t.y;
}
float map_1(in vec3 p)
{
//return sdSphere(p+vec3(0.,0.,1.0), 0.4);
return sdTorus_0(p+vec3(0.,0.,0.0),vec2(0.4,0.1));
//return sdBox(p+vec3(0.0,0.0,1.0), vec3(0.2, 0.2, 0.2));
//方形中挖掉圓形
// return max(boxSDF(p+vec3(0.0,0.0,1.0), vec3(0.3, 0.3, 0.3)), -sphereSDF(p+vec3(0.,0.,1.0), 0.5));
}
vec3 gradient( in vec3 p ) //尚未normalize
{
const float d = 0.001;
vec3 grad = vec3(map_1(p+vec3(d,0,0))-map_1(p-vec3(d,0,0)),
map_1(p+vec3(0,d,0))-map_1(p-vec3(0,d,0)),
map_1(p+vec3(0,0,d))-map_1(p-vec3(0,0,d)));
return grad;
}
mat3 fromEuler_3(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
vec3 m0 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,
a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
vec3 m1 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
vec3 m2 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,
a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return mat3(m0, m1, m2);
}
mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
{
vec3 cw = normalize(ta-ro);
vec3 cp = vec3(sin(cr), cos(cr),0.0);
vec3 cu = normalize( cross(cw,cp) );
vec3 cv = normalize( cross(cu,cw) );
return mat3( cu, cv, cw );
}
vec3 hsv2rgb_smooth_1460171947( in vec3 c )
{
vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );
rgb = rgb*rgb*(3.0-2.0*rgb); // cubic smoothing
return c.z * mix( vec3(1.0), rgb, c.y);
}
vec3 flameColour(float f)
{
return hsv2rgb_smooth_1460171947(vec3((f-(2.25/6.))*(1.25/6.),f*1.25+.2,f*.95));
}
mat3 fromEuler_1(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
vec3 m0 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,
a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
vec3 m1 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
vec3 m2 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,
a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return mat3(m0, m1, m2);
}
float hash12_0(vec2 p) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
float noise_3_2658629798(in vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
vec3 u = f*f*(3.0-2.0*f);
vec2 ii = i.xy + i.z * vec2(5.0);
float a = hash12_0( ii + vec2(0.0,0.0) );
float b = hash12_0( ii + vec2(1.0,0.0) );
float c = hash12_0( ii + vec2(0.0,1.0) );
float d = hash12_0( ii + vec2(1.0,1.0) );
float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
ii += vec2(5.0);
a = hash12_0( ii + vec2(0.0,0.0) );
b = hash12_0( ii + vec2(1.0,0.0) );
c = hash12_0( ii + vec2(0.0,1.0) );
d = hash12_0( ii + vec2(1.0,1.0) );
float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
return max(mix(v1,v2,u.z),0.0);
}
float sdBox_2( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdBox_2( vec3 p)
{
vec3 b=vec3(0.4);
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdSphere_2( vec3 p, float s )
{
return length(p)-s;
}
float sdTorus_3( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xy)-t.x,p.z);
return length(q)-t.y;
}
mat3 fromEuler_2(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
vec3 m0 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,
a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
vec3 m1 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
vec3 m2 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,
a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return mat3(m0, m1, m2);
}
float map_2(in vec3 p)
{
float bump=0.002 * (noise_3_2658629798(p*60.0)*2.0-1.0);
#ifdef USE_SPIN
mat3 rot=fromEuler_2(vec3(0.0,0.0,u_time*0.5));
#else
mat3 rot=fromEuler_2(vec3(0.0,0.0,0.5));
#endif
vec3 p1=(p+vec3(0.0,-0.0,1.5))*rot;
vec3 p2=(p+vec3(1.5,-0.5,0.0))*-rot;
vec3 p3=(p+vec3(-1.5,-0.8,0.0))*-rot;
vec3 p4=(p+vec3(0.0,-0.3,-1.5))*rot;
#ifdef USE_BOX
return sdBox_2(p1,vec3(0.4));
#elif defined(USE_SPHERE)
return sdSphere_2(p1+vec3(0.,0.,0.0), 0.5)+bump;
#elif defined(USE_TORUS)
return sdTorus_3(p+vec3(0.,0.,1.5),vec2(0.4,0.2))+bump;
#else
return sdBox_2(p1,vec3(0.4));
#endif
//return min(min(min(sdBox(p1),sdBox(p2)),sdBox(p3)),sdBox(p4));
}
float density_0(vec3 p){
return (1.0-smoothstep(0.,0.1,map_2(p)))*2.0;
//return (smoothstep(0.,0.1,map(p)))*0.5;
}
vec2 hash2( vec2 x ) //亂數範圍 [-1,1]
{
const vec2 k = vec2( 0.3183099, 0.3678794 );
x = x*k + k.yx;
return -1.0 + 2.0*fract( 16.0 * k*fract( x.x*x.y*(x.x+x.y)) );
}
float gnoise( in vec2 p ) //亂數範圍 [-1,1]
{
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash2( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash2( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash2( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash2( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float hash12_2(vec2 p) {
float h = dot(p,vec2(127.1,311.7));
return fract(sin(h)*43758.5453123);
}
float noise_3_409528883(in vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
vec3 u = f*f*(3.0-2.0*f);
vec2 ii = i.xy + i.z * vec2(5.0);
float a = hash12_2( ii + vec2(0.0,0.0) );
float b = hash12_2( ii + vec2(1.0,0.0) );
float c = hash12_2( ii + vec2(0.0,1.0) );
float d = hash12_2( ii + vec2(1.0,1.0) );
float v1 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
ii += vec2(5.0);
a = hash12_2( ii + vec2(0.0,0.0) );
b = hash12_2( ii + vec2(1.0,0.0) );
c = hash12_2( ii + vec2(0.0,1.0) );
d = hash12_2( ii + vec2(1.0,1.0) );
float v2 = mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
return max(mix(v1,v2,u.z),0.0);
}
float sdBox_1( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdBox_1( vec3 p)
{
vec3 b=vec3(0.4);
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
float sdSphere_1( vec3 p, float s )
{
return length(p)-s;
}
float sdTorus_2( vec3 p, vec2 t )
{
vec2 q = vec2(length(p.xy)-t.x,p.z);
return length(q)-t.y;
}
mat3 fromEuler_4(vec3 ang) {
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
vec3 m0 = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,
a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
vec3 m1 = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
vec3 m2 = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,
a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
return mat3(m0, m1, m2);
}
float map_0(in vec3 p)
{
float bump=0.002 * (noise_3_409528883(p*60.0)*2.0-1.0);
#ifdef USE_SPIN
mat3 rot=fromEuler_4(vec3(0.0,0.0,u_time*0.5));
#else
mat3 rot=fromEuler_4(vec3(0.0,0.0,0.5));
#endif
vec3 p1=(p+vec3(0.0,-0.0,1.5))*rot;
vec3 p2=(p+vec3(1.5,-0.5,0.0))*-rot;
vec3 p3=(p+vec3(-1.5,-0.8,0.0))*-rot;
vec3 p4=(p+vec3(0.0,-0.3,-1.5))*rot;
#ifdef USE_BOX
return sdBox_1(p1,vec3(0.4));
#elif defined(USE_SPHERE)
return sdSphere_1(p1+vec3(0.,0.,0.0), 0.5)+bump;
#elif defined(USE_TORUS)
return sdTorus_2(p+vec3(0.,0.,1.5),vec2(0.4,0.2))+bump;
#else
return sdBox_1(p1,vec3(0.4));
#endif
//return min(min(min(sdBox(p1),sdBox(p2)),sdBox(p3)),sdBox(p4));
}
/*
contributors: [Stefan Gustavson, Ian McEwan]
description: modulus of 289
use: <float|vec2|vec3|vec4> mod289(<float|vec2|vec3|vec4> x)
*/
#ifndef FNC_MOD289
#define FNC_MOD289
float mod289(const in float x) { return x - floor(x * (1. / 289.)) * 289.; }
vec2 mod289(const in vec2 x) { return x - floor(x * (1. / 289.)) * 289.; }
vec3 mod289(const in vec3 x) { return x - floor(x * (1. / 289.)) * 289.; }
vec4 mod289(const in vec4 x) { return x - floor(x * (1. / 289.)) * 289.; }
#endif
/*
contributors: [Stefan Gustavson, Ian McEwan]
description: permute
use: <float|vec2|vec3|vec4> permute(<float|vec2|vec3|vec4> x)
examples:
- https://raw.githubusercontent.com/patriciogonzalezvivo/lygia_examples/main/math_functions.frag
*/
#ifndef FNC_PERMUTE
#define FNC_PERMUTE
float permute(const in float v) { return mod289(((v * 34.0) + 1.0) * v); }
vec2 permute(const in vec2 v) { return mod289(((v * 34.0) + 1.0) * v); }
vec3 permute(const in vec3 v) { return mod289(((v * 34.0) + 1.0) * v); }
vec4 permute(const in vec4 v) { return mod289(((v * 34.0) + 1.0) * v); }
#endif
/*
contributors: [Stefan Gustavson, Ian McEwan]
description: Fast, accurate inverse square root.
use: <float|vec2|vec3|vec4> taylorInvSqrt(<float|vec2|vec3|vec4> x)
*/
#ifndef FNC_TAYLORINVSQRT
#define FNC_TAYLORINVSQRT
float taylorInvSqrt(in float r) { return 1.79284291400159 - 0.85373472095314 * r; }
vec2 taylorInvSqrt(in vec2 r) { return 1.79284291400159 - 0.85373472095314 * r; }
vec3 taylorInvSqrt(in vec3 r) { return 1.79284291400159 - 0.85373472095314 * r; }
vec4 taylorInvSqrt(in vec4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
#endif
/*
contributors: [Stefan Gustavson, Ian McEwan]
description: grad4, used for snoise(vec4 v)
use: grad4(<float> j, <vec4> ip)
*/
#ifndef FNC_GRAD4
#define FNC_GRAD4
vec4 grad4(float j, vec4 ip) {
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
vec4 p,s;
p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
s = vec4(lessThan(p, vec4(0.0)));
p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;
return p;
}
#endif
/*
contributors: [Stefan Gustavson, Ian McEwan]
description: Simplex Noise https://github.com/stegu/webgl-noise
use: snoise(<vec2|vec3|vec4> pos)
license: |
Copyright 2021-2023 by Stefan Gustavson and Ian McEwan.
Published under the terms of the MIT license:
https://opensource.org/license/mit/
examples:
- /shaders/generative_snoise.frag
*/
#ifndef FNC_SNOISE
#define FNC_SNOISE
float snoise(in vec2 v) {
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0
// First corner
vec2 i = floor(v + dot(v, C.yy) );
vec2 x0 = v - i + dot(i, C.xx);
// Other corners
vec2 i1;
//i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//i1.y = 1.0 - i1.x;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
// x0 = x0 - 0.0 + 0.0 * C.xx ;
// x1 = x0 - i1 + 1.0 * C.xx ;
// x2 = x0 - 1.0 + 2.0 * C.xx ;
vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;
// Permutations
i = mod289(i); // Avoid truncation effects in permutation
vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
+ i.x + vec3(0.0, i1.x, 1.0 ));
vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
m = m*m ;
m = m*m ;
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;
// Normalise gradients implicitly by scaling m
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
// Compute final noise value at P
vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}
float snoise(in vec3 v) {
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
const vec4 D = vec4(0.0, 0.5, 1.0, 2.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 );
// x0 = x0 - 0.0 + 0.0 * C.xxx;
// 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; // 2.0*C.x = 1/3 = C.y
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
// Permutations
i = mod289(i);
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)
float n_ = 0.142857142857; // 1.0/7.0
vec3 ns = n_ * D.wyz - D.xzx;
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
vec4 x_ = floor(j * ns.z);
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
vec4 x = x_ *ns.x + ns.yyyy;
vec4 y = y_ *ns.x + ns.yyyy;
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, vec4(0.0));
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
vec3 p0 = vec3(a0.xy,h.x);
vec3 p1 = vec3(a0.zw,h.y);
vec3 p2 = vec3(a1.xy,h.z);
vec3 p3 = vec3(a1.zw,h.w);
//Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= 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;
return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
dot(p2,x2), dot(p3,x3) ) );
}
float snoise(in vec4 v) {
const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4
0.276393202250021, // 2 * G4
0.414589803375032, // 3 * G4
-0.447213595499958); // -1 + 4 * G4
// First corner
vec4 i = floor(v + dot(v, vec4(.309016994374947451)) ); // (sqrt(5) - 1)/4
vec4 x0 = v - i + dot(i, C.xxxx);
// Other corners
// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
vec4 i0;
vec3 isX = step( x0.yzw, x0.xxx );
vec3 isYZ = step( x0.zww, x0.yyz );
// i0.x = dot( isX, vec3( 1.0 ) );
i0.x = isX.x + isX.y + isX.z;
i0.yzw = 1.0 - isX;
// i0.y += dot( isYZ.xy, vec2( 1.0 ) );
i0.y += isYZ.x + isYZ.y;
i0.zw += 1.0 - isYZ.xy;
i0.z += isYZ.z;
i0.w += 1.0 - isYZ.z;
// i0 now contains the unique values 0,1,2,3 in each channel
vec4 i3 = clamp( i0, 0.0, 1.0 );
vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );
// x0 = x0 - 0.0 + 0.0 * C.xxxx
// x1 = x0 - i1 + 1.0 * C.xxxx
// x2 = x0 - i2 + 2.0 * C.xxxx
// x3 = x0 - i3 + 3.0 * C.xxxx
// x4 = x0 - 1.0 + 4.0 * C.xxxx
vec4 x1 = x0 - i1 + C.xxxx;
vec4 x2 = x0 - i2 + C.yyyy;
vec4 x3 = x0 - i3 + C.zzzz;
vec4 x4 = x0 + C.wwww;
// Permutations
i = mod289(i);
float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x);
vec4 j1 = permute( permute( permute( permute (
i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
+ i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
+ i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
+ i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));
// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;
vec4 p0 = grad4(j0, ip);
vec4 p1 = grad4(j1.x, ip);
vec4 p2 = grad4(j1.y, ip);
vec4 p3 = grad4(j1.z, ip);
vec4 p4 = grad4(j1.w, ip);
// Normalise gradients
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
p0 *= norm.x;
p1 *= norm.y;
p2 *= norm.z;
p3 *= norm.w;
p4 *= taylorInvSqrt(dot(p4,p4));
// Mix contributions from the five corners
vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0);
m0 = m0 * m0;
m1 = m1 * m1;
return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
+ dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;
}
vec2 snoise2( vec2 x ){
float s = snoise(vec2( x ));
float s1 = snoise(vec2( x.y - 19.1, x.x + 47.2 ));
return vec2( s , s1 );
}
vec3 snoise3( vec3 x ){
float s = snoise(vec3( x ));
float s1 = snoise(vec3( x.y - 19.1 , x.z + 33.4 , x.x + 47.2 ));
float s2 = snoise(vec3( x.z + 74.2 , x.x - 124.5 , x.y + 99.4 ));
return vec3( s , s1 , s2 );
}
vec3 snoise3( vec4 x ){
float s = snoise(vec4( x ));
float s1 = snoise(vec4( x.y - 19.1 , x.z + 33.4 , x.x + 47.2, x.w ));
float s2 = snoise(vec4( x.z + 74.2 , x.x - 124.5 , x.y + 99.4, x.w ));
return vec3( s , s1 , s2 );
}
#endif
/*
contributors: Isaac Cohen
description: https://github.com/cabbibo/glsl-curl-noise/blob/master/curl.glsl
use: curl(<vec3|vec4> pos)
examples:
- /shaders/generative_curl.frag
*/
#ifndef FNC_CURL
#define FNC_CURL
#ifndef CURL_FNC
vec2 curl( vec2 p ) {
const float e = .1;
vec2 dx = vec2( e , 0.0 );
vec2 dy = vec2( 0.0 , e );
vec2 p_x0 = snoise2( p - dx );
vec2 p_x1 = snoise2( p + dx );
vec2 p_y0 = snoise2( p - dy );
vec2 p_y1 = snoise2( p + dy );
float x = p_x1.y + p_x0.y;
float y = p_y1.x - p_y0.x;
const float divisor = 1.0 / ( 2.0 * e );
#ifndef CURL_UNNORMALIZED
return normalize( vec2(x, y) * divisor );
#else
return vec2(x, y) * divisor;
#endif
}
#else
vec2 curl( vec2 p ) {
vec2 e = vec2(0.1, 0.0);
vec3 pos = vec3(p, 0.0);
vec2 C = vec2( (CURL_FNC(pos+e.yxy)-CURL_FNC(pos-e.yxy))/(2.0*e.x),
-(CURL_FNC(pos+e.xyy)-CURL_FNC(pos-e.xyy))/(2.0*e.x));
#ifndef CURL_UNNORMALIZED
return normalize(C);
#else
float divisor = 1.0 / (2.0 * e.x);
return C * divisor;
#endif
}
#endif
vec3 curl( vec3 p ){
const float e = .1;
vec3 dx = vec3( e , 0.0 , 0.0 );
vec3 dy = vec3( 0.0 , e , 0.0 );
vec3 dz = vec3( 0.0 , 0.0 , e );
vec3 p_x0 = snoise3( p - dx );
vec3 p_x1 = snoise3( p + dx );
vec3 p_y0 = snoise3( p - dy );
vec3 p_y1 = snoise3( p + dy );
vec3 p_z0 = snoise3( p - dz );
vec3 p_z1 = snoise3( p + dz );
float x = p_y1.z - p_y0.z - p_z1.y + p_z0.y;
float y = p_z1.x - p_z0.x - p_x1.z + p_x0.z;
float z = p_x1.y - p_x0.y - p_y1.x + p_y0.x;
const float divisor = 1.0 / ( 2.0 * e );
#ifndef CURL_UNNORMALIZED
return normalize( vec3( x , y , z ) * divisor );
#else
return vec3( x , y , z ) * divisor;
#endif
}
vec3 curl( vec4 p ){
const float e = .1;
vec4 dx = vec4( e , 0.0 , 0.0 , 1.0 );
vec4 dy = vec4( 0.0 , e , 0.0 , 1.0 );
vec4 dz = vec4( 0.0 , 0.0 , e , 1.0 );
vec3 p_x0 = snoise3( p - dx );
vec3 p_x1 = snoise3( p + dx );
vec3 p_y0 = snoise3( p - dy );
vec3 p_y1 = snoise3( p + dy );
vec3 p_z0 = snoise3( p - dz );
vec3 p_z1 = snoise3( p + dz );
float x = p_y1.z - p_y0.z - p_z1.y + p_z0.y;
float y = p_z1.x - p_z0.x - p_x1.z + p_x0.z;
float z = p_x1.y - p_x0.y - p_y1.x + p_y0.x;
const float divisor = 1.0 / ( 2.0 * e );
#ifndef CURL_UNNORMALIZED
return normalize( vec3( x , y , z ) * divisor );
#else
return vec3( x , y , z ) * divisor;
#endif
}
#endif
//=======Fur texture========
const float uvScale = 10.0; //from 1.0->12.0
//const float colorUvScale = 0.1;
const float furDepth = 0.2;
//const int furLayers = 64;
//const float rayStep = furDepth*2.0 / float(furLayers);
const float furThreshold = 0.15; //from 0.4->0.6
vec2 cartesianToSpherical(vec3 p)
{
float r = length(p);
float t = (r - (0.5 - furDepth)) / furDepth;//1.0->0.5
p /= r; //normalize
vec2 uv = vec2(atan(p.y, p.x), acos(p.z));
//uv.x += cos(u_time*1.5)*t*t*0.4;// curl
//uv.y += sin(u_time*1.7)*t*t*0.2;
uv.y -= t*t*0.1;// curl down
return uv;
}
// returns fur density at given position
float furDensity(vec3 pos)
{
vec2 uv = cartesianToSpherical(pos.xzy);
vec3 tex=vec3(gnoise(uv*uvScale)*0.5+0.5);
// thin out hair
float density = smoothstep(furThreshold, 1.0, tex.x);
float r1=map_0(pos);
density *= clamp(smoothstep(-furDepth, 0., r1),0.0,1.0);
return density;
}
float density_1(vec3 p){
p+=0.05*curl(10.0*p);
//p=pixel(p,30.0);
float weight=1.0;
weight=furDensity(p)*1.5;
//weight=noise_3(10.0*p);
//weight=smoothstep(0.3, 1.0, cellular(12.0*p).y);
return (1.0-smoothstep(0.,0.1,map_0(p)))*3.0*weight;
//return (smoothstep(0.,0.1,map(p)))*0.5;
}
/*
contributors: Patricio Gonzalez Vivo
description: some useful math constants
license:
- Copyright (c) 2021 Patricio Gonzalez Vivo under Prosperity License - https://prosperitylicense.com/versions/3.0.0
- Copyright (c) 2021 Patricio Gonzalez Vivo under Patron License - https://lygia.xyz/license
*/
#ifndef EIGHTH_PI
#define EIGHTH_PI 0.39269908169
#endif
#ifndef QTR_PI
#define QTR_PI 0.78539816339
#endif
#ifndef HALF_PI
#define HALF_PI 1.5707963267948966192313216916398
#endif
#ifndef PI
#define PI 3.1415926535897932384626433832795
#endif
#ifndef TWO_PI
#define TWO_PI 6.2831853071795864769252867665590
#endif
#ifndef TAU
#define TAU 6.2831853071795864769252867665590
#endif
#ifndef INV_PI
#define INV_PI 0.31830988618379067153776752674503
#endif
#ifndef INV_SQRT_TAU
#define INV_SQRT_TAU 0.39894228040143267793994605993439 // 1.0/SQRT_TAU
#endif
#ifndef SQRT_HALF_PI
#define SQRT_HALF_PI 1.25331413732
#endif
#ifndef PHI
#define PHI 1.618033988749894848204586834
#endif
#ifndef EPSILON
#define EPSILON 0.0000001
#endif
#ifndef GOLDEN_RATIO
#define GOLDEN_RATIO 1.6180339887
#endif
#ifndef GOLDEN_RATIO_CONJUGATE
#define GOLDEN_RATIO_CONJUGATE 0.61803398875
#endif
#ifndef GOLDEN_ANGLE // (3.-sqrt(5.0))*PI radians
#define GOLDEN_ANGLE 2.39996323
#endif
#ifndef DEG2RAD
#define DEG2RAD (PI / 180.0)
#endif
#ifndef RAD2DEG
#define RAD2DEG (180.0 / PI)
#endif
// Henyey-Greenstein phase function factor [-1, 1]
// represents the average cosine of the scattered directions
// 0 is isotropic scattering
// > 1 is forward scattering, < 1 is backwards
#ifndef HENYEYGREENSTEIN_SCATTERING
#define HENYEYGREENSTEIN_SCATTERING 0.76
#endif
#ifndef FNC_HENYEYGREENSTEIN
#define FNC_HENYEYGREENSTEIN
float henyeyGreenstein(const in float mu) {
return max(0.0, (1.0 - HENYEYGREENSTEIN_SCATTERING*HENYEYGREENSTEIN_SCATTERING) / ((4. + PI) * pow(1.0 + HENYEYGREENSTEIN_SCATTERING*HENYEYGREENSTEIN_SCATTERING - 2.0 * HENYEYGREENSTEIN_SCATTERING * mu, 1.5)));
}
float henyeyGreenstein(float mu, float g) {
float gg = g * g;
return (1.0 / (4.0 * PI)) * ((1.0 - gg) / pow(1.0 + gg - 2.0 * g * mu, 1.5));
}
float henyeyGreenstein(float mu, float g, float dual_lobe_weight) {
return mix(henyeyGreenstein( mu, -g), henyeyGreenstein(mu, g), dual_lobe_weight);
}
#endif
vec4 VolumetricRaymarch(vec3 samplePosition, vec3 marchDirection, int stepCount, float stepSize) {
float ambientLight=9.;
float directLight=15.0;
#ifdef USE_SPIN
vec3 l=vec3(0.5,0.3,-0.8)*fromEuler_1(vec3(0.0,0.0,u_time*0.2));
#else
vec3 l=vec3(0.5,0.3,-0.8)*fromEuler_1(vec3(0.0,0.0,0.2));
#endif
float absorptionCoef=0.01;
float scatteringCoef=0.04;
float extinctionCoef = absorptionCoef + scatteringCoef;
float transmittance = 1.0;
vec3 illumination = vec3(0.0);
for (int i = 0; i < 32; i++) {
samplePosition += marchDirection * stepSize;
#ifdef USE_FUR_DENSITY
float currentDensity = density_1(1.0*samplePosition);
#else
float currentDensity = density_0(1.0*samplePosition);
#endif
transmittance *= exp(-currentDensity * extinctionCoef * stepSize);
float inScattering= ambientLight +
directLight * henyeyGreenstein(0.6,dot(-marchDirection,-l)); //directLight * phase(marchDirection, -l)
float outScattering = scatteringCoef * currentDensity;
vec3 currentLight = vec3(inScattering * outScattering);
illumination += transmittance * currentLight * stepSize;
}
return vec4(illumination, transmittance);
}
vec3 render( in vec3 RayOri, in vec3 RayDir ){
/*
//First Ray
vec3 p,n;
float t = trace(RayOri, RayDir, p);
n=normalize(gradient(p))
//Second Ray
float IOR=1.33;
vec3 Rd_2=refract(RayDir,n,1.0/IOR);
*/
//SHADING
vec3 result;
result= VolumetricRaymarch(RayOri, RayDir,32,0.1).xyz;
//result= VolumetricRaymarch(p, Rd_2,32,0.1).xyz;;
result= flameColour(clamp(result.x*1.0,0.0,1.0));
//result= viridis_quintic(result.x);
return result;
}
// =========================================================
void main()
{
vec2 uv = gl_FragCoord.xy/u_resolution.xy;
uv = uv*2.0-1.0;
uv.x*= u_resolution.x/u_resolution.y;
uv.y*=-1.0;//校正 預設值uv v軸朝下,轉成v軸朝上相同於y軸朝上為正
//vec2 mouse=(u_mouse.xy/u_resolution.xy)*2.0-1.0;
vec2 mouse=(u_mouse.xy/u_resolution.xy)*2.0-1.0;
// camera option1 (模型應在原點,適用於物件)
//vec3 CameraRot=vec3(0.0, mouse.y*1.0, -mouse.x*1.0);
vec3 CameraRot=vec3(0.0, 0.0, 0.0);
vec3 ro= vec3(0.0, 0.0, 1.5);//CameraPos;
vec3 ta =vec3(0.0, 0.0, -1.0)*fromEuler_3(CameraRot); //TargetPos;
//vec3 ta =float3(CameraDir.x, CameraDir.z, CameraDir.y);//UE座標Z軸在上
mat3 ca = setCamera( ro, ta, 0.0 );
vec3 RayDir = ca*normalize(vec3(uv, 2.0));//z值越大,zoom in! 可替換成iMouse.z
vec3 RayOri = ro;
vec3 col = render(RayOri,RayDir);
gl_FragColor = vec4( col, 1.0 );
}