1. 程式人生 > 實用技巧 >three.js 著色器材質之變數(三)

three.js 著色器材質之變數(三)

這篇郭先生在練習一下著色器變數,在度娘上面或者官網上經常看到類似水波一樣的效果,這篇就試著做一個這樣的效果,順便鞏固一下頂點著色器和片元著色器,畢竟多多練習才能更好地掌握。效果如下圖,線上案例請點選部落格原文

這裡用到了用到了頂點著色器和片元著色器。

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

這樣就做成了案例上面的效果,是不是很有意思,我們可以做各種效果,說不上有心儀的效果。

轉載請註明地址:郭先生的部落格