water shader を試す
Posted :
water shader を試す
ocean - Realistic water shader for Three.jsの basic のデモをもう少し分解して整理してみた。
利用手順
- 水面の凹凸に使うノーマルマップを読み込む
THREE.Water
のインスタンスを作る- インスタンスの
material
プロパティーを平面のマテリアルにしてメッシュを作る - 描画アップデート時 (requestAnimationFrame) に
- シェーダーに送るユニフォーム変数を更新する
water.material.uniforms.time.value = 経過時間;
インスタンス.render();
して反射用のテクスチャーを作る。ただし drawcall 回数が倍くらいになるので throttle したり、必要なければ実行しないほうがいい
- シェーダーに送るユニフォーム変数を更新する
コード例
<script src="http://ajax.googleapis.com/ajax/libs/threejs/r67/three.min.js"></script>
<script src="water-material.js"></script>
<script>
var width, height, clock, scene, camera, renderer,
directionalLight, ground, sphere, waterSurface,
water, colorMap1, colorMap2, waterNormals;
width = window.innerWidth;
height = window.innerHeight;
clock = new THREE.Clock();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 );
camera.position.set( 0, 5, 30 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( width, height );
document.body.appendChild( renderer.domElement );
colorMap1 = new THREE.ImageUtils.loadTexture( 'stone.jpg' );
colorMap1.wrapS = colorMap1.wrapT = THREE.RepeatWrapping;
colorMap1.repeat.set( 3, 3 );
ground = new THREE.Mesh(
new THREE.PlaneGeometry( 30, 30, 10, 10 ),
new THREE.MeshBasicMaterial( { map: colorMap1 } )
);
ground.position.set( 0, -3, 0 );
ground.rotation.x = THREE.Math.degToRad( -90 );
scene.add( ground );
colorMap2 = new THREE.ImageUtils.loadTexture( 'grass.jpg' );
sphere = new THREE.Mesh(
new THREE.SphereGeometry( 2, 16, 16 ),
new THREE.MeshBasicMaterial( { map: colorMap2 } )
);
scene.add( sphere );
directionalLight = new THREE.DirectionalLight( 0xffff55 );
directionalLight.position.set( -100, 30, 100 );
scene.add(directionalLight);
// Load textures
waterNormals = new THREE.ImageUtils.loadTexture( 'waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
// Create the water effect
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 256,
textureHeight: 256,
waterNormals: waterNormals,
distortionScale: 20,
noiseScale: .5,
alpha: .8,
sunDirection: directionalLight.position.normalize(),
sunColor: 0xffffff,
waterColor: 0x000000,
side: THREE.DoubleSide
} );
waterSurface = new THREE.Mesh(
new THREE.PlaneGeometry( 30, 30, 10, 10 ),
water.material
);
waterSurface.add(this.water);
waterSurface.rotation.x = - Math.PI * 0.5;
scene.add(waterSurface);
;( function update () {
var elapsed = clock.getElapsedTime()
requestAnimationFrame( update );
water.render();
renderer.render( scene, camera );
water.material.uniforms.time.value = elapsed;
} )();
</script>