38 Three.js高階材質THREE.ShaderMaterial
注意
看這一篇文章最好有webgl基礎的同學看,如果沒有webgl原生基礎,你會看得很懵逼。
簡介
THREE.ShaderMaterial是Three.js庫中最通用、最複雜的材質之一。通過它可以使用自己定製的著色器。直接在webgl環境中執行。著色器可以將Three.js中的JavaScript網格轉換為螢幕上的畫素。通過這些自定義的著色器,可以明確地指定物件如何渲染,以及如何覆蓋或修改Three.js庫中的預設值。
特別屬性
THREE.ShaderMaterial有一些前面見過的並且正常的屬性如wireframe、linewidth、shading、vertexColors、fog以外,還有一些特別的屬性,可以用來定製自己的著色器:
名稱 | 描述 |
---|---|
fragmentShader | 這個屬性是用來定義自己的片元著色器的 |
vertexShader | 這個屬性是定義自己的頂點著色器的 |
uniforms | 通過這個屬性可以給著色器傳入uniform變數的值 |
defaultAttributeValues(原來為:attributes) | 該屬性用於傳遞attribute變數的的值 |
defines | 轉換成#define程式碼片段。這些片段可以用來設定著色器程式裡的一些額外的全域性變數 |
lights | 該屬性定義光照資料是否傳遞給著色器,預設值為false |
一個例項化案例
var material = new THREE.ShaderMaterial( {
uniforms: {
time: { value: 1.0 },
resolution: { value: new THREE.Vector2() }
},
attributes: {
vertexOpacity: { value: [] }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
一個可執行的程式碼案例
案例檢視地址:http://www.wjceo.com/blog/threejs/2018-02-12/40.html
<!doctype html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ShaderMaterial案例</title>
<script src="https://johnson2heng.github.io/three.js-demo/lib/three.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>
<script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script>
<style type="text/css">
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
</style>
</head>
<body onload="draw()">
<script id="vertex-shader" type="x-shader/x-vertex">
uniform float time;
varying vec2 vUv;
void main(){
vec3 posChanged = position;
posChanged.x = posChanged.x*(abs(sin(time*1.0)));
posChanged.y = posChanged.y*(abs(cos(time*1.0)));
posChanged.z = posChanged.z*(abs(sin(time*1.0)));
//gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
}
</script>
<script id="fragment-shader-1" type="x-shader/x-fragment">
precision highp float;
uniform float time;
uniform float alpha;
uniform vec2 resolution;
varying vec2 vUv;
void main2(void)
{
vec2 position = vUv;
float red = 1.0;
float green = 0.25 + sin(time) * 0.25;
float blue = 0.0;
vec3 rgb = vec3(red, green, blue);
vec4 color = vec4(rgb, alpha);
gl_FragColor = color;
}
#define PI 3.14159
#define TWO_PI (PI*2.0)
#define N 68.5
void main(void)
{
vec2 center = (gl_FragCoord.xy);
center.x=-10.12*sin(time/200.0);
center.y=-10.12*cos(time/200.0);
vec2 v = (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0;
v.x=v.x-10.0;
v.y=v.y-200.0;
float col = 0.0;
for(float i = 0.0; i < N; i++)
{
float a = i * (TWO_PI/N) * 61.95;
col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 ));
}
col /= 5.0;
gl_FragColor = vec4(col*1.0, -col*1.0,-col*4.0, 1.0);
}
</script>
<script id="fragment-shader-2" type="x-shader/x-fragment">
// from http://glsl.heroku.com/e#7906.0
uniform float time;
uniform vec2 resolution;
// 2013-03-30 by @hintz
#define CGFloat float
#define M_PI 3.14159265359
vec3 hsvtorgb(float h, float s, float v)
{
float c = v * s;
h = mod((h * 6.0), 6.0);
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
vec3 color;
if (0.0 <= h && h < 1.0)
{
color = vec3(c, x, 0.0);
}
else if (1.0 <= h && h < 2.0)
{
color = vec3(x, c, 0.0);
}
else if (2.0 <= h && h < 3.0)
{
color = vec3(0.0, c, x);
}
else if (3.0 <= h && h < 4.0)
{
color = vec3(0.0, x, c);
}
else if (4.0 <= h && h < 5.0)
{
color = vec3(x, 0.0, c);
}
else if (5.0 <= h && h < 6.0)
{
color = vec3(c, 0.0, x);
}
else
{
color = vec3(0.0);
}
color += v - c;
return color;
}
void main(void)
{
vec2 position = (gl_FragCoord.xy - 0.5 * resolution) / resolution.y;
float x = position.x;
float y = position.y;
CGFloat a = atan(x, y);
CGFloat d = sqrt(x*x+y*y);
CGFloat d0 = 0.5*(sin(d-time)+1.5)*d;
CGFloat d1 = 5.0;
CGFloat u = mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5;
CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5;
CGFloat dd = sqrt(u*u+v*v);
CGFloat aa = atan(u, v);
CGFloat uu = mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5;
// CGFloat vv = mod(dd*4.0,1.0) - 0.5;
CGFloat d2 = sqrt(uu*uu+v*v)*1.5;
gl_FragColor = vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 );
}
</script>
<script id="fragment-shader-3" type="x-shader/x-fragment">
uniform vec2 resolution;
uniform float time;
vec2 rand(vec2 pos)
{
return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
}
vec2 rand2(vec2 pos)
{
return rand(rand(pos));
}
float softnoise(vec2 pos, float scale)
{
vec2 smplpos = pos * scale;
float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;
vec2 a = fract(smplpos);
return mix(
mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
smoothstep(0.0, 1.0, a.y));
}
void main(void)
{
vec2 pos = gl_FragCoord.xy / resolution.y;
pos.x += time * 0.1;
float color = 0.0;
float s = 1.0;
for(int i = 0; i < 8; i++)
{
color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
s *= 2.0;
}
gl_FragColor = vec4(color);
}
</script>
<script id="fragment-shader-4" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution;
vec2 rand(vec2 pos)
{
return
fract(
(
pow(
pos+2.0,
pos.yx+2.0
)*555555.0
)
);
}
vec2 rand2(vec2 pos)
{
return rand(rand(pos));
}
float softnoise(vec2 pos, float scale) {
vec2 smplpos = pos * scale;
float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;
vec2 a = fract(smplpos);
return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
smoothstep(0.0, 1.0, a.x));
}
void main( void ) {
vec2 pos = gl_FragCoord.xy / resolution.y - time * 0.4;
float color = 0.0;
float s = 1.0;
for (int i = 0; i < 6; ++i) {
color += softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0;
s *= 2.0;
}
gl_FragColor = vec4(color,mix(color,cos(color),sin(color)),color,1);
}
</script>
<script id="fragment-shader-5" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution;
// tie nd die by Snoep Games.
void main( void ) {
vec3 color = vec3(1.0, 0., 0.);
vec2 pos = (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5;
float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0;
float size1=2.0*cos(time/60.0);
float size2=2.5*sin(time/12.1);
float rot1=13.00; //82.0+16.0*sin(time/4.0);
float rot2=-50.00; //82.0+16.0*sin(time/8.0);
float t=sin(time);
float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time);
a += 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0));
a=a*(r/50.0);
a=200.0*sin(a*5.0)*(r/30.0);
if(a>5.0) a=a/200.0;
if(a<0.5) a=a*22.5;
gl_FragColor = vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 );
}
</script>
<script id="fragment-shader-6" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution;
void main( void )
{
vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis
//suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center
uPos.x -= 1.0;
uPos.y -= 0.5;
vec3 color = vec3(0.0);
float vertColor = 2.0;
for( float i = 0.0; i < 15.0; ++i )
{
float t = time * (0.9);
uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1;
float fTemp = abs(1.0 / uPos.y / 100.0);
vertColor += fTemp;
color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 );
}
vec4 color_final = vec4(color, 1.0);
gl_FragColor = color_final;
}
</script>
</body>
<script>
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
//告訴渲染器需要陰影效果
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 預設的是,沒有設定的這個清晰 THREE.PCFShadowMap
document.body.appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(30,30,30);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
//初始化dat.GUI簡化試驗流程
var gui;
function initGui() {
//宣告一個儲存需求修改的相關資料的物件
gui = {
};
var datGui = new dat.GUI();
//將設定屬性新增到gui當中,gui.add(物件,屬性,最小值,最大值)
}
var ambientLight,spotLight;
function initLight() {
ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
}
var cube;
function initModel() {
//宣告一個立方體幾何圖形
var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);
//建立立方體六個面的紋理
var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");
var material = [meshMaterial6, meshMaterial5, meshMaterial4, meshMaterial3, meshMaterial2, meshMaterial1];
//例項化一個網格
cube = new THREE.Mesh(cubeGeometry, material);
//將網格新增到場景當中
scene.add(cube);
}
//初始化效能外掛
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
var step = 0;
function render() {
cube.rotation.y = step += 0.01;
cube.rotation.x = step;
cube.rotation.z = step;
cube.material.forEach(function (e) {
e.uniforms.time.value += 0.01;
});
renderer.render(scene, camera);
}
//視窗變動觸發的函式
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
//更新控制器
render();
//更新效能外掛
stats.update();
requestAnimationFrame(animate);
}
function draw() {
initGui();
initRender();
initScene();
initCamera();
initLight();
initModel();
initStats();
animate();
window.onresize = onWindowResize;
}
//建立ShaderMaterial紋理的函式
function createMaterial(vertexShader, fragmentShader) {
var vertShader = document.getElementById(vertexShader).innerHTML; //獲取頂點著色器的程式碼
var fragShader = document.getElementById(fragmentShader).innerHTML; //獲取片元著色器的程式碼
//配置著色器裡面的attribute變數的值
var attributes = {};
//配置著色器裡面的uniform變數的值
var uniforms = {
time: {type: 'f', value: 0.2},
scale: {type: 'f', value: 0.2},
alpha: {type: 'f', value: 0.6},
resolution: {type: "v2", value: new THREE.Vector2(window.innerWidth, window.innerHeight)}
};
var meshMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
defaultAttributeValues : attributes,
vertexShader: vertShader,
fragmentShader: fragShader,
transparent: true
});
return meshMaterial;
}
</script>
</html>
著色器程式碼是偷的《three.js開發指南》裡面的,自己整理了一個程式碼,想學習這個的小朋友可以看一下。
相關文章
- Three.js開發指南(4):使用Three.js的材質JS
- OpenGL高階版本學習日誌2:光照模型&材質模型
- 材質
- 39 Three.js線性幾何體材質THREE.LineBasicMaterialJS
- 40 Three.js線性幾何體材質THREE.LineDashedMaterialJS
- 修改材質
- Three.js 進階之旅:全景漫遊-高階版線上看房 ?JS
- blender材質屬性:
- CesiumJS PrimitiveAPI 高階著色入門 - 從引數化幾何與 Fabric 材質到著色器 - 下篇JSMITAPI
- CesiumJS PrimitiveAPI 高階著色入門 - 從引數化幾何與 Fabric 材質到著色器 - 上篇JSMITAPI
- 材質優化:如何正確處理紋理和材質的關係優化
- Ticwatch 2智慧手錶高畫質圖賞 多材多技
- 41 Three.js高階幾何體THREE.ConvexGeometryJS
- 【Scala之旅】特質與高階型別型別
- 42 Three.js高階幾何體車床模型THREE.LatheGeometryJS模型
- [SceneKit專題]10-Materials材質
- JMonkeyEngine——材質檔案備註
- 閃耀暖暖手遊布料材質解析
- 一組材質面料展示模組參考
- three.js 著色器材質之紋理JS
- Three.js開發指南(8):建立、載入高階網格和幾何體JS
- java進階(38)--執行緒安全Java執行緒
- 韶關鋼材檢測 Q355B鑑定材質檢測
- 『高階篇』docker之kubernetes搭建叢集新增認證授權(上)(38)Docker
- Unity網格合併_材質合併[轉]Unity
- three.js 著色器材質內建變數JS變數
- three.js 著色器材質之變數(二)JS變數
- three.js 著色器材質之初識著色器JS
- three.js 著色器材質之變數(一)JS變數
- Node.js初中高階全棧高畫質影片教程Node.js全棧
- 次世代油燈“寫實風”高模製作技巧 模型拆分、卡線、sp材質,PBR流程模型
- 從頭學ShaderGraph :UV與基礎材質
- 高質量C/C++程式設計指南總結(八)—— C++高階特性C++程式設計
- 從高階函式--->高階元件函式元件
- C語言的本質(38)——makefile之變數C語言變數
- CSS高階進階CSS
- 前端3D引擎-Cesium自定義動態材質前端3D
- 工字電感磁芯材質型別深度詳解型別