CMH Studio

Raymarching Field

Raymarching Field


#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
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 fbm(in vec2 uv)       //亂數範圍 [-1,1]
{
    float f;                //fbm - fractal noise (4 octaves)
    mat2 m = mat2( 1.6,  1.2, -1.2,  1.6 );
    f   = 0.5000*gnoise( uv ); 
    uv = m*uv;		  
    f += 0.2500*gnoise( uv ); 
    uv = m*uv;
    f += 0.1250*gnoise( uv ); 
    uv = m*uv;
    f += 0.0625*gnoise( uv ); 
    uv = m*uv;
    return f;
}

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

vec3 sky_color_2315452051(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_2315452051(e);
}

vec3 hatching(vec3 p, vec3 n, float value){        
    vec3 col;
    //float str=10.0;
    float NdotL=(1.0-value)*10.0;
    vec3 col1 = vec3(texcube (p,n,NdotL)); // ⚠️ texcube undefined
    vec3 col2 = vec3(cubeproj(p,NdotL));
    col = mix(col1,col2, 3.0);
    return col;    
}

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, mouse.x); 
        vec3 ro= vec3(0.0, 0.0, 1.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, 0.0 );
        vec3 RayDir = ca*normalize(vec3(uv, 1.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); //position
    n=normalize(gradient(p)); //normal
    //n+=0.5*normalMap(p,n);    //add normal detail
    float VdotN=dot(-RayDir,n);
    float edge=min(max(smoothstep(-0.388,1.710,VdotN),0.0),1.0);
            
    //SHADING
        vec3 result;
        result=hatching(p, n, edge);
        // result=(n);
        
    //HDR環境貼圖
        vec3 BG=getSkyALL(RayDir);	   //或getSkyFBM(RayDir)

    gl_FragColor = vec4(vec3(result),1.0);    
    if(t<3.5) gl_FragColor = vec4(vec3(result),1.0); 
    else gl_FragColor = vec4(BG,1.0);
}