Shader toy (順手寫兩個Gyro)(純程式碼寫3D)
Shader toy (A new world)
1.一個多月了,突然忘記CSDN的密碼了,因為每次輸密碼的時候都要計算一遍,於是沒有計算出來…
2.回頭發現都過了半年了,都快捏了一把汗,這百度何時不那麼踉踉蹌蹌,搜尋服務一直那麼差,百度網速又不給力了。
3.創新的思維很重要,那為了那死去活來還要被唾棄的文聘我值得嗎?
留一戳shadertoy地址:https://www.shadertoy.com/user/834144373 就 恬納微晰
C部落格做得還是可以,畢竟是技術論壇,有的是原創文章,而有的文章千金難求,所以C部落格沒有大量的廣告,以後C部落格的口碑還是可以……
快來看看吧!你的第一眼感覺!
My Smooth Gyro!
1.這個是誰呀
我怎麼也看著眼熟,gif為什麼這麼卡?那快去看看這兒吧! https://www.shadertoy.com/view/llfXz7
2.怎麼看著奇怪
這又是哪樣的節奏啊!
仔細看圖片的日期
一定要仔細看圖片上的日期
是那個畫在834144373旁邊的那個日期 \\//部落格釋出日期2015年7月23日
初步技術細節
- Gyro 旋轉之謎
也許你不相信,這gif有2.96MB大小,CSDN要求2MB,這個C到底怎麼了?
math可都家喻戶曉了,當然這個旋轉math也就要擺出來了,平時呼叫數學庫,這回可就完全靠自己了。。。。。。(A say:我靠,靠誰呀!老師沒有教?Super B say:–馬丹,不知道抄啊!要養成從小抄襲的良好習慣。)
//標準數學中的旋轉矩陣
vec3 rotate_y(vec3 v, float angle)//y軸旋轉
{
float ca = cos(angle); float sa = sin(angle);
return v*mat3(
ca, .0, -sa,
.0,1.0, .0,
sa, .0, ca);
}
vec3 rotate_x(vec3 v, float angle)//x軸旋轉
{
float ca = cos(angle); float sa = sin(angle);
return v*mat3(
1.0 , .0, .0,
.0, ca, -sa,
.0, sa, ca);
}
vec3 rotate_z(vec3 v,float angle){//z軸旋轉 這兒是我故意寫上的,就用不上節奏了
float ca = cos(angle),sa = sin(angle);
return v*mat3(
ca,-sa,0.,
sa, ca,0.,
0., 0.,0.
);
}
//當然對於程式來說,還有更簡的旋轉寫法,如果你經歷過。。。。。
所以你用的時候一定要注意了,讓物體旋轉的條件是滑鼠mouse為變數,以哪個軸旋轉
p如果看不懂就當做一條射線向量,我們這是在旋轉它,就如gif上滑鼠晃來晃去那樣。
(哎,怪我羅!趕快在這兒補補http://blog.csdn.net/baidu_26153715/article/details/46510703 3D基礎實現篇,馬丹,我都還沒找到這樣解析shadertoy上 三D,還是中文易懂不要錢的文章)
Gyro 背景之謎
可以仔細從圖中看出,一個背景是黑的,一個背景有點蹊蹺,那麼有點蹊蹺是怎麼實現的?col = textureCube(iChannel0,pp).rgb; //就是這麼實現的,pp為鏡頭向外射出的單位向量,這個就不需要想吧。
晉級技術
- Gyro 初步假光照,試探光照反應
col = vec3(max(0.,dot(nDir,-normalize(vec3(0.,1.,1.)))));
可以看到初步的光照反應是成立的。
最後用到常用的這種方法,這是最後新增上去的。
//fork diffuse
diff = 0.5*max(0.,dot(nDir,normalize(vec3(0.,1.,0.))))+0.5;
- Gyro 折射、透明、其他效果
factor = (1.- iMouse.y/iResolution.y)*0.1;
factor = pow(factor,1.1);
ref = normalize(reflect(pp,nDir));
fra0 = normalize(refract(pp,nDir,iMouse.y/iResolution.y));
fra1 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+factor);
fra2 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+2.*factor);
//col = nDir;
//fork diffuse
diff = 0.5*max(0.,dot(nDir,normalize(vec3(0.,1.,0.))))+0.5;
//custom fresnel
fresnel = pow(1.-max(0.,dot(pp,nDir)),2.);
refcol = textureCube(iChannel0,ref).rgb;
//tone-mapping
refcol /= vec3(1.)+refcol;
//fracol = textureCube(iChannel0,fra).rgb/1.5;
vec3 fracol = vec3(
textureCube(iChannel0,fra0).r,
textureCube(iChannel0,fra1).g,
textureCube(iChannel0,fra2).b
);
//Luminance
luminance = dot( fracol, vec3(0.22, 0.707, 0.071));
fracol *= diff*luminance;
//gamma
fracol = pow(fracol,vec3(1.3));
col = mix(fracol,refcol,fresnel);
//tone
col *= 2.3*vec3(1.1,1.1,1.);
//col = vec3(diff);
從程式碼片段可以看出,我用到了fresnel來混合折射與反射效果,其中Luminance來計算折射亮度,其他效果你懂得。
Gyro 折射率這樣的調節
factor = (1.- iMouse.y/iResolution.y)*0.1;
factor = pow(factor,1.1);
ref = normalize(reflect(pp,nDir));
fra0 = normalize(refract(pp,nDir,iMouse.y/iResolution.y));
fra1 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+factor);
fra2 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+2.*factor);
這兒的iMouse.y/iResolution.y作用 可以滑鼠上下滑動來調節折射率因子。
vec3 fracol = vec3(
textureCube(iChannel0,fra0).r,
textureCube(iChannel0,fra1).g,
textureCube(iChannel0,fra2).b
);
這兒就是經典的rgb三通道簡單位移實現折射產生的散色想象,當然你可以自己發明……
Shadertoy Gyro 程式碼最終總結
這個就是實現一款簡單3D的祕密,,,當然這是基於fragment shader直接實現的。。。
//thx for shadertoy give me a more interesting world
//The Transparent Gyro made by 834144373zhu
//https://www.shadertoy.com/view/MlfXz7
/////////////////////////////////////////////////
#define time iGlobalTime
vec3 rotate_y(vec3 v, float angle)
{
float ca = cos(angle); float sa = sin(angle);
return v*mat3(
ca, .0, -sa,
.0,1.0, .0,
sa, .0, ca);
}
vec3 rotate_x(vec3 v, float angle)
{
float ca = cos(angle); float sa = sin(angle);
return v*mat3(
1.0, .0, .0,
.0, ca, -sa,
.0, sa, ca);
}
vec3 rotate_z(vec3 v,float angle){
float ca = cos(angle),sa = sin(angle);
return v*mat3(
ca,-sa,0.,
sa, ca,0.,
0., 0.,0.
);
}
//distance function
float toSphere(in vec3 p){
p = rotate_y(p,-time*0.5);
p.y += 0.2;
return length(pow(abs(p),vec3(.7,0.68,0.4)))-1.5;
//you can try this another DE vertion
//return length(pow(abs(p),vec3(.7,0.68,0.4))-vec3(.6,0.35,0.4))-1.;
}
float toPlane( vec3 p )
{
return p.y;
}
//map the objects and return the distance
float map(in vec3 p){
return toSphere(p);
}
//the object's noraml
vec3 normal(in vec3 p){
vec2 offset = vec2(0.01,0.);
vec3 nDir = vec3(
map(p+offset.xyy)-map(p-offset.xyy),
map(p+offset.yxy)-map(p-offset.yxy),
map(p+offset.yyx)-map(p-offset.yyx)
);
return normalize(nDir);
}
//ray-marching the object and return the distance
float raymarching(in vec3 pos,in vec3 p){
float d = 0.;
float distance = 1.;
for(int i = 0;i<64;++i){
distance += d;
vec3 raysphere = pos + distance*p;
d = map(raysphere);
if(d<0.02 )break;
};
return distance;
}
/*vec3 thenewp (in vec3 pos,in vec3 p,in float an){
vec3 dian = vec3(0.);
vec3 z = normalize(dian-pos);
vec3 x = normalize(cross(z,vec3(sin(an),cos(an),0.)));
vec3 y = normalize(cross(z,x));
mat3 mat = mat3(x,y,z);
return p*mat;//;p.x*x+p.y*y+p.z*z;
}
*/
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 mouse = iMouse.xy/iResolution.xy*vec2(5.,0.);
vec2 uv = fragCoord.xy / iResolution.xy;
uv = uv*2.-1.;
uv.x *= iResolution.x/iResolution.y;
vec3 p = normalize(vec3(uv,2.));
//camera
vec3 pos = vec3(0.,0.,-5.);
pos = rotate_x(pos,mouse.y);
pos = rotate_y(pos,mouse.x);
//the new p
//vec3 pp = thenewp(pos,p,0.);
vec3 pp;
//pp = rotate_x(p,mouse.y);
pp = rotate_y(p,mouse.x);
vec3 col = vec3(0.);
float d = raymarching(pos,pp);
float diff,fresnel,luminance,factor;
vec3 nDir,ref, fra0,fra1,fra2;
vec3 refcol,fracol;
if(d<40.){
nDir = -normal(pos+d*pp);
if(dot(pp,nDir) > 0.){
factor = (1.- iMouse.y/iResolution.y)*0.1;
factor = pow(factor,1.1);
ref = normalize(reflect(pp,nDir));
fra0 = normalize(refract(pp,nDir,iMouse.y/iResolution.y));
fra1 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+factor);
fra2 = normalize(refract(pp,nDir,iMouse.y/iResolution.y)+2.*factor);
//col = nDir;
//fork diffuse
diff = 0.5*max(0.,dot(nDir,normalize(vec3(0.,1.,0.))))+0.5;
//custom fresnel
fresnel = pow(1.-max(0.,dot(pp,nDir)),2.);
refcol = textureCube(iChannel0,ref).rgb;
//tone-mapping
refcol /= vec3(1.)+refcol;
//fracol = textureCube(iChannel0,fra).rgb/1.5;
vec3 fracol = vec3(
textureCube(iChannel0,fra0).r,
textureCube(iChannel0,fra1).g,
textureCube(iChannel0,fra2).b
);
//Luminance
luminance = dot( fracol, vec3(0.22, 0.707, 0.071));
fracol *= diff*luminance;
//gamma
fracol = pow(fracol,vec3(1.3));
col = mix(fracol,refcol,fresnel);
//tone
col *= 2.3*vec3(1.1,1.1,1.);
//col = vec3(diff);
}
else{
discard;
}
}else{col = vec3(0.06);}
fragColor = vec4(col,1.0);
}
- 還有不放心的是:
以下就留給可愛的