CMH Studio

Make Bumping

Make Bumping


#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
mat3 fromEuler(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 );
}

float sdTorus_1( 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_1(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));
}

vec2 pixel(vec2 p, float scale){
    return floor(p*scale)/scale;
    //floor : 無條件捨去
}
vec3 pixel(vec3 p, float scale){
    return floor(p*scale)/scale;
}

float trace(vec3 o, vec3 r, out vec3 p)
{
    float t=0.0;
    for (int i=0; i<32; ++i)
    {
        p= o+r*t;
        float d= map_1(p);
        t += d*0.3;
    }
    return t;
}

// Pixel effect
float trace(vec3 o, vec3 r, out vec3 p, out float d)
{
float t=0.0;
    for (int i=0; i<32; ++i)
    {
        p = o+r*t;
        p = pixel(p, 10.);//格化    
            
        d = map_1(p);
        if(d<0.0){
            break;
        }
            
        t += d*0.5; //影響輪廓精準程度
    }
    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_0(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_0(p+vec3(d,0,0))-map_0(p-vec3(d,0,0)),
                    map_0(p+vec3(0,d,0))-map_0(p-vec3(0,d,0)),
                    map_0(p+vec3(0,0,d))-map_0(p-vec3(0,0,d)));
    return grad;
}

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);
}

vec3 smoothSampling2(vec2 uv)
{
    const float T_RES = 32.0;
    return vec3(gnoise(uv*T_RES)); //讀取亂數函式
}

float triplanarSampling(vec3 p, vec3 n)
{
    float fTotal = abs(n.x)+abs(n.y)+abs(n.z);
    return  (abs(n.x)*smoothSampling2(p.yz).x
            +abs(n.y)*smoothSampling2(p.xz).x
            +abs(n.z)*smoothSampling2(p.xy).x)/fTotal;
}

const mat2 m2_0 = mat2(0.90,0.44,-0.44,0.90);
float triplanarNoise(vec3 p, vec3 n)
{
    const float BUMP_MAP_UV_SCALE = 0.2;
    float fTotal = abs(n.x)+abs(n.y)+abs(n.z);
    float f1 = triplanarSampling(p*BUMP_MAP_UV_SCALE,n);
    p.xy = m2_0*p.xy;
    p.xz = m2_0*p.xz;
    p *= 2.1;
    float f2 = triplanarSampling(p*BUMP_MAP_UV_SCALE,n);
    p.yx = m2_0*p.yx;
    p.yz = m2_0*p.yz;
    p *= 2.3;
    float f3 = triplanarSampling(p*BUMP_MAP_UV_SCALE,n);
    return f1+0.5*f2+0.25*f3;
}

vec3 triplanarMap(vec3 p, vec3 n)
{
  float d = 0.005;
  float po = triplanarNoise(p,n);
  float px = triplanarNoise(p+vec3(d,0,0),n);
  float py = triplanarNoise(p+vec3(0,d,0),n);
  float pz = triplanarNoise(p+vec3(0,0,d),n);
  return normalize(vec3((px-po)/d,
                        (py-po)/d,
                        (pz-po)/d));
}

vec3 hsv2rgb_smooth_2315452051( 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_2315452051(vec3((f-(2.25/6.))*(1.25/6.),f*1.25+.2,f*.95));
    }

vec3 sky_color_1535977339(vec3 e) {	//漸層藍天空色
    e.y = max(e.y,0.0);
    vec3 ret;
    ret.x = pow(1.0-e.y,3.0);
    ret.y = pow(1.0-e.y, 1.2);
    ret.z = 0.8+(1.0-e.y)*0.3;    
    return ret;
}

vec3 getSkyALL(vec3 e)
{	
    return sky_color_1535977339(e);
}

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;
    
    // camera option1  (模型應在原點,適用於物件)
        vec3 CameraRot=vec3(0.0, mouse.y*2., -mouse.x); 
        vec3 ro= vec3(0.0, 0.0, 2.0)*fromEuler(CameraRot);//CameraPos;
        vec3 ta =vec3(0.0, 0.0, 0.0); //TargetPos; 
        //vec3 ta =float3(CameraDir.x, CameraDir.z, CameraDir.y);
        //UE座標Z軸在上

        mat3 ca = setCamera( ro, ta, 01.0 );
        vec3 RayDir = ca*normalize(vec3(uv, 2.0));
        //z值越大則zoom in,可替換成iMouse.z
        
        vec3 RayOri = ro;
    
    // camera option2 (攝影機在原點,適用於場景)
    /*	
        vec3 CameraRot=vec3(0.0, -iMouse.y, -iMouse.x);
        vec3 RayOri= vec3(0.0, 0.0, 0.0);//CameraPos;
        vec3 RayDir = normalize(vec3(uv, -1.))*fromEuler(CameraRot);
    */
        
    vec3 p,n;
    float t = trace(RayOri, RayDir, p);
    n=normalize(gradient(p));
    
    //sol2
    /*
        float displacement = 10. * (noise_3(p*10.0)*2.0-1.0);
        p += n*displacement;
        n=normalize(gradient(p));
    */

    //sol3
    vec3 bump = triplanarMap(p*1.6,n);//調整bumping密度
    // n += bump*2.; // ⚠️ 這個數值會讓圖形渲染超出 canvas ,甚至超過 browser 範圍,讓整個螢幕看起來像是壞掉 ⚠️

    float edge = dot(-RayDir,n);
    //RayDir : 相機看出去的方向
    //-RayDir : 看向攝影機的方向
    //edge*=-1.;
    edge = smoothstep(.2,.4,edge);
    //smoothstep產生一點灰階 vs. step單純畫邊緣

    //SHADING
        vec3 result=n;
        result = vec3(edge)*flameColour(edge);
    
    //HDR環境貼圖
        vec3 BG=getSkyALL(RayDir);	   //或getSkyFBM(RayDir)
    
    //亂數作用雲霧(二維)
    //float fog= fbm(0.6*uv+vec2(-0.2*u_time, -0.02*u_time))*0.5+0.3;
    //vec3 fogFBM=getSkyFBM(reflect(RayDir,n));
    
    if(t<2.5) gl_FragColor = vec4(vec3(result),1.0); 
    else gl_FragColor = vec4(BG,1.0);
}