亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用three.js怎么實現一個露珠滴落動畫效果

發布時間:2021-03-01 16:41:54 來源:億速云 閱讀:177 作者:Leah 欄目:開發技術

本篇文章為大家展示了使用three.js怎么實現一個露珠滴落動畫效果,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

首先將相機換成正交相機,再將平面的長度調整為2,使其填滿屏幕

class RayMarching extends Base {
 constructor(sel: string, debug: boolean) {
 super(sel, debug);
 this.clock = new THREE.Clock();
 this.cameraPosition = new THREE.Vector3(0, 0, 0);
 this.orthographicCameraParams = {
  left: -1,
  right: 1,
  top: 1,
  bottom: -1,
  near: 0,
  far: 1,
  zoom: 1
 };
 }
 // 初始化
 init() {
 this.createScene();
 this.createOrthographicCamera();
 this.createRenderer();
 this.createRayMarchingMaterial();
 this.createPlane();
 this.createLight();
 this.trackMousePos();
 this.addListeners();
 this.setLoop();
 }
 // 創建平面
 createPlane() {
 const geometry = new THREE.PlaneBufferGeometry(2, 2, 100, 100);
 const material = this.rayMarchingMaterial;
 this.createMesh({
  geometry,
  material
 });
 }
}

使用three.js怎么實現一個露珠滴落動畫效果

創建材質

創建好著色器材質,里面定義好所有要傳遞給著色器的參數

const matcapTextureUrl = "https://i.loli.net/2021/02/27/7zhBySIYxEqUFW3.png";

class RayMarching extends Base {
 // 創建光線追蹤材質
 createRayMarchingMaterial() {
 const loader = new THREE.TextureLoader();
 const texture = loader.load(matcapTextureUrl);
 const rayMarchingMaterial = new THREE.ShaderMaterial({
  vertexShader: rayMarchingVertexShader,
  fragmentShader: rayMarchingFragmentShader,
  side: THREE.DoubleSide,
  uniforms: {
  uTime: {
   value: 0
  },
  uMouse: {
   value: new THREE.Vector2(0, 0)
  },
  uResolution: {
   value: new THREE.Vector2(window.innerWidth, window.innerHeight)
  },
  uTexture: {
   value: texture
  },
  uProgress: {
   value: 1
  },
  uVelocityBox: {
   value: 0.25
  },
  uVelocitySphere: {
   value: 0.5
  },
  uAngle: {
   value: 1.5
  },
  uDistance: {
   value: 1.2
  }
  }
 });
 this.rayMarchingMaterial = rayMarchingMaterial;
 }
}

頂點著色器 rayMarchingVertexShader ,這個只要用模板現成的就可以了

重點是片元著色器 rayMarchingFragmentShader

片元著色器

背景

作為熱身運動,先創建一個輻射狀的背景吧

varying vec2 vUv;

vec3 background(vec2 uv){
 float dist=length(uv-vec2(.5));
 vec3 bg=mix(vec3(.3),vec3(.0),dist);
 return bg;
}

void main(){
 vec3 bg=background(vUv);
 vec3 color=bg;
 gl_FragColor=vec4(color,1.);
}

使用three.js怎么實現一個露珠滴落動畫效果

sdf

如何在光照模型中創建物體呢?我們需要sdf。

sdf的意思是符號距離函數:若傳遞給函數空間中的某個坐標,則返回那個點與某些平面之間的最短距離,返回值的符號表示點在平面的內部還是外部,故稱符號距離函數。

如果我們要創建一個球,就得用球的sdf來創建。球體方程可以用如下的glsl代碼來表示

float sdSphere(vec3 p,float r)
{
 return length(p)-r;
}

方塊的代碼如下

float sdBox(vec3 p,vec3 b)
{
 vec3 q=abs(p)-b;
 return length(max(q,0.))+min(max(q.x,max(q.y,q.z)),0.);
}

看不懂怎么辦?沒關系,國外已經有大牛把 常用的sdf公式 都整理出來了

在sdf里先創建一個方塊

float sdf(vec3 p){
 float box=sdBox(p,vec3(.3));
 return box;
}

畫面上仍舊一片空白,因為我們的嘉賓——光線還尚未入場。

光線步進

接下來就是本文的頭號人物——光線步進了。在介紹她之前,我們先來看看她的好姬友光線追蹤吧。

使用three.js怎么實現一個露珠滴落動畫效果

首先,我們需要知道光線追蹤是如何進行的:給相機一個位置 eye ,在前面放一個網格,從相機的位置發射一束射線 ray ,穿過網格打在物體上,所成的像的每一個像素對應著網格上的每一個點。

而在光線步進中,整個場景會由一系列的sdf的角度定義。為了找到場景和視線之間的邊界,我們會從相機的位置開始,沿著射線,一點一點地移動每個點,每一步都會判斷這個點在不在場景的某個表面內部,如果在則完成,表示光線擊中了某東西,如果不在則光線繼續步進。

使用three.js怎么實現一個露珠滴落動畫效果

上圖中,p0是相機位置,藍色的線代表射線。可以看出光線的第一步p0p1就邁的非常大,它也恰好是此時光線到表面的最短距離。表面上的點盡管是最短距離,但并沒有沿著視線的方向,因此要繼續檢測到p4這個點

shadertoy上有一個 可交互的例子

以下是光線步進的glsl代碼實現

const float EPSILON=.0001;

float rayMarch(vec3 eye,vec3 ray,float end,int maxIter){
 float depth=0.;
 for(int i=0;i<maxIter;i++){
  vec3 pos=eye+depth*ray;
  float dist=sdf(pos);
  depth+=dist;
  if(dist<EPSILON||dist>=end){
   break;
  }
 }
 return depth;
}

在主函數中創建一條射線,將其投喂給光線步進算法,即可獲得光線到表面的最短距離

void main(){
 ...
 vec3 eye=vec3(0.,0.,2.5);
 vec3 ray=normalize(vec3(vUv,-eye.z));
 float end=5.;
 int maxIter=256;
 float depth=rayMarch(eye,ray,end,maxIter);
 if(depth<end){
  vec3 pos=eye+depth*ray;
  color=pos;
 }
 ...
}

使用three.js怎么實現一個露珠滴落動畫效果

在光線步進的引誘下,野生的方塊出現了!

居中材質

目前的方塊有2個問題:1. 沒有居中 2. x軸方向上被拉伸

居中+拉伸素質2連走起

vec2 centerUv(vec2 uv){
 uv=2.*uv-1.;
 float aspect=uResolution.x/uResolution.y;
 uv.x*=aspect;
 return uv;
}

void main(){
 ...
 vec2 cUv=centerUv(vUv);
 vec3 ray=normalize(vec3(cUv,-eye.z));
 ...
}

使用three.js怎么實現一個露珠滴落動畫效果

方塊瞬間飄到了畫面的正中央,但此時的她還沒有顏色

計算表面法線

在光照模型中,我們需要 計算出表面法線 ,才能給材質賦予顏色

vec3 calcNormal(in vec3 p)
{
 const float eps=.0001;
 const vec2 h=vec2(eps,0);
 return normalize(vec3(sdf(p+h.xyy)-sdf(p-h.xyy),
 sdf(p+h.yxy)-sdf(p-h.yxy),
 sdf(p+h.yyx)-sdf(p-h.yyx)));
}

void main(){
 ...
 if(depth<end){
  vec3 pos=eye+depth*ray;
  vec3 normal=calcNormal(pos);
  color=normal;
 }
 ...
}

使用three.js怎么實現一個露珠滴落動畫效果

此時方塊被賦予了藍色,但我們還看不出她是個立體圖形

動起來

讓方塊360°旋轉起來吧,3D旋轉函數直接在 gist 上搜一下就有了

uniform float uVelocityBox;

mat4 rotationMatrix(vec3 axis,float angle){
 axis=normalize(axis);
 float s=sin(angle);
 float c=cos(angle);
 float oc=1.-c;
 
 return mat4(oc*axis.x*axis.x+c,oc*axis.x*axis.y-axis.z*s,oc*axis.z*axis.x+axis.y*s,0.,
  oc*axis.x*axis.y+axis.z*s,oc*axis.y*axis.y+c,oc*axis.y*axis.z-axis.x*s,0.,
  oc*axis.z*axis.x-axis.y*s,oc*axis.y*axis.z+axis.x*s,oc*axis.z*axis.z+c,0.,
 0.,0.,0.,1.);
}

vec3 rotate(vec3 v,vec3 axis,float angle){
 mat4 m=rotationMatrix(axis,angle);
 return(m*vec4(v,1.)).xyz;
}

float sdf(vec3 p){
 vec3 p1=rotate(p,vec3(1.),uTime*uVelocityBox);
 float box=sdBox(p1,vec3(.3));
 return box;
}

使用three.js怎么實現一個露珠滴落動畫效果

融合效果

單單一個方塊太孤單了,創建一個球來陪陪她吧

如何讓球和方塊貼在一起呢,你需要 smin 這個函數

uniform float uProgress;

float smin(float a,float b,float k)
{
 float h=clamp(.5+.5*(b-a)/k,0.,1.);
 return mix(b,a,h)-k*h*(1.-h);
}

float sdf(vec3 p){
 vec3 p1=rotate(p,vec3(1.),uTime*uVelocityBox);
 float box=sdBox(p1,vec3(.3));
 float sphere=sdSphere(p,.3);
 float sBox=smin(box,sphere,.3);
 float mixedBox=mix(sBox,box,uProgress);
 return mixedBox;
}

uProgress 的值設為0,她們成功地貼在了一起

使用three.js怎么實現一個露珠滴落動畫效果

uProgress 的值調回1,她們又分開了

動態融合

接下來就是露珠滴落的動畫實現了,其實就是對融合圖形應用了一個位移變換

uniform float uAngle;
uniform float uDistance;
uniform float uVelocitySphere;

const float PI=3.14159265359;

float movingSphere(vec3 p,float shape){
 float rad=uAngle*PI;
 vec3 pos=vec3(cos(rad),sin(rad),0.)*uDistance;
 vec3 displacement=pos*fract(uTime*uVelocitySphere);
 float gotoCenter=sdSphere(p-displacement,.1);
 return smin(shape,gotoCenter,.3);
}

float sdf(vec3 p){
 vec3 p1=rotate(p,vec3(1.),uTime*uVelocityBox);
 float box=sdBox(p1,vec3(.3));
 float sphere=sdSphere(p,.3);
 float sBox=smin(box,sphere,.3);
 float mixedBox=mix(sBox,box,uProgress);
 mixedBox=movingSphere(p,mixedBox);
 return mixedBox;
}

使用three.js怎么實現一個露珠滴落動畫效果

matcap貼圖

默認的材質太土了?我們有帥氣的matcap貼圖來助陣

uniform sampler2D uTexture;

vec2 matcap(vec3 eye,vec3 normal){
 vec3 reflected=reflect(eye,normal);
 float m=2.8284271247461903*sqrt(reflected.z+1.);
 return reflected.xy/m+.5;
}

float fresnel(float bias,float scale,float power,vec3 I,vec3 N)
{
 return bias+scale*pow(1.+dot(I,N),power);
}

void main(){
 ...
 if(depth<end){
  vec3 pos=eye+depth*ray;
  vec3 normal=calcNormal(pos);
  vec2 matcapUv=matcap(ray,normal);
  color=texture2D(uTexture,matcapUv).rgb;
  float F=fresnel(0.,.4,3.2,ray,normal);
  color=mix(color,bg,F);
 }
 ...
}

上述內容就是使用three.js怎么實現一個露珠滴落動畫效果,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兰州市| 卢湾区| 石河子市| 邯郸县| 渝中区| 大田县| 彭水| 曲阜市| 长白| 西贡区| 井陉县| 砀山县| 驻马店市| 兖州市| 永春县| 襄汾县| 内丘县| 班戈县| 田林县| 濮阳市| 额尔古纳市| 博乐市| 虞城县| 体育| 临沧市| 上栗县| 彰化县| 集安市| 河池市| 资讯| 淮阳县| 凭祥市| 天祝| 安溪县| 利辛县| 永修县| 沈阳市| 运城市| 呼和浩特市| 富阳市| 元氏县|