這篇郭先生在練習一下着色器變量,在度娘上面或者官網上經常看到類似水波一樣的效果,這篇就試着做一個這樣的效果,順便鞏固一下頂點着色器和片元着色器,畢竟多多練習才能更好地掌握。效果如下圖,在線案例請點擊博客原文。
這里用到了用到了頂點着色器和片元着色器。
1. 設置幾何體
設置一個幾何體,對於波浪效果,我們制作一個球幾何體(當然也可以設置其他的,可能有意想不到的效果哦!)。
var sphere = new THREE.SphereBufferGeometry(10, 120, 80);
2. 設置attribute屬性
這里我們使用一個叫做noise的attribute屬性來搞定它,同時我們在設置一個類型化數組boolArray來輔助它。
count = sphere.attributes.position.count;//頂點的數量 verticesArray = new Float32Array(count);//存放每一個點的噪聲值 boolArray = new Float32Array(count);//輔助類型數組 for(var v = 0; v < count; v++) { verticesArray[v] = Math.random() * 2 + 10;//隨機數[10,12) if(Math.random() >= 0.5) {//在創造一個隨機數,如果大於如果大於0.5,boolArray設置成10.5,boolArray設置成1。如果小於0.5,boolArray設置成-1 boolArray[v] = 1; } else { boolArray[v] = -1; } } var bufferAttribute = new THREE.BufferAttribute(verticesArray, 1); sphere.setAttribute('noise', bufferAttribute);
3. 設置着色器材質
var material = new THREE.ShaderMaterial({ vertexShader: ` attribute float noise;//着色器中定義noise屬性 varying vec3 vNormal;//定義兩個varying屬性,用於將頂點着色器中的屬性傳到片元着色器中 varying vec3 vPosition; void main() { vNormal = normal; vPosition = position; vec3 newPosition = position + normal * noise;//這里比較重要,頂點坐標加上球面法向量乘以噪聲,得到新的頂點坐標,新的坐標是和normal方向相同的。 gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 ); } `, fragmentShader: ` varying vec3 vPosition; varying vec3 vNormal; void main() { vec3 nml = (vNormal + 1.0) / 2.0;//這個使用了頂點坐標的法向量 vec3 cy = vec3((sin(vPosition.y * 3.0) + 1.0) / 2.0);//這個使用了頂點坐標 gl_FragColor=vec4(cy * nml, 1.0);//將兩種效果結合起來(上面兩種顏色你們不妨可以單個試一試哦) } ` });
4. 設置動態效果
上一篇我們使用了uniform傳遞了一個time值,這次我們另辟蹊徑,在render方法中改變attribute屬性。
for(var v = 0; v < count; v++) { if(verticesArray[v] < 10) {//如果噪聲小於10,就將對應的boolArray變成1,然后累加 boolArray[v] = 1; verticesArray[v] += 0.05; } else if(verticesArray[v] > 12) {//如果噪聲大於12,就將對應的boolArray變成-1,然后累減 boolArray[v] = -1; verticesArray[v] -= 0.05; } else if(boolArray[v] == 1) {//如果boolArray等於1,就繼續累加 verticesArray[v] += 0.05; } else {//如果boolArray等於-1,就繼續累減 verticesArray[v] -= 0.05; } } var bufferAttribute = new THREE.BufferAttribute(verticesArray, 1); //更新noise屬性值 mesh.geometry.setAttribute('noise', bufferAttribute);
這樣就做成了案例上面的效果,是不是很有意思,我們可以做各種效果,說不上有心儀的效果。
轉載請注明地址:郭先生的博客