1. 程式人生 > >基於threejs開發的卡通風格著色器(二)

基於threejs開發的卡通風格著色器(二)

        上次給球體添加了卡通風格著色器之後覺得還少些什麼,仔細觀察網上卡通風格的遊戲發現,卡通風格的3D任務往往除了明顯不平滑過渡的色塊以外,還都有著黑色描邊,這次我們就來修改著色器實現描邊的效果。

        描邊特效可以通過很多方法來實現,比如:判斷每個面片的朝向,當一條稜既出現在一個面片的正面又出現在反面時,說明該楞是分界線,將其塗黑即可。或者將每個點沿著法線方向延伸一定距離,相當於一個放大了的模型,然後將其塗黑,第二次正常繪製,就會出現黑邊,這裡面就要用到二次繪製了~最後再說我們使用的方法:計算每一個片元的法線與視線方向的夾角,當其大於閾值時將其塗黑,這樣方便快捷~(只能對於平滑過渡的物體使用,當物體表面過渡不平滑時描邊會很小几乎看不到)。

        這次直接貼著色器的程式碼,其他與上次的程式碼的一樣,(http://blog.csdn.net/srk19960903/article/details/67645302)。主要的區別在於片元著色器這裡,我們增加了浮點型一個變數dir,它的結果是視線方向對映到法線上的長度,也就是說該點越靠近邊緣,距離視線方向越遠,這個值也就越小(平滑物體)。當該值小於一定程度時則說明這個片元處在邊緣上,就將該片元的顏色值賦值為零也就是黑色。否則按照正常的卡通著色器賦值,這樣就完成了卡通風格的著色器~

<script id="fish-fragmentShader" type="x-shader/x-vertex"
> uniform vec3 light; varying vec3 vNormal; uniform vec3 color; void main() { float diffuse = dot(normalize(light), vNormal); float dir = length(vNormal * vec3(0.0, 0.0, 1.0)); if (dir < 0.5) { dir = 0.0; gl_FragColor = vec4(dir, dir, dir, 1.0); } else { if (diffuse > 0.8) { diffuse = 1.0; } else if (diffuse > 0.5) { diffuse = 0.6; } else if (diffuse > 0.2) { diffuse = 0.4; } else { diffuse = 0.2; } gl_FragColor = vec4( color* diffuse, 1.0); } } </script>
        下面是實現後的圖片,還是很有卡通的感覺~哈哈

最後github地址:https://github.com/StringKun/ThreeJSToonShader/tree/master/ThreeJSshader2