three.jsで多色グラデーションを作る。
9頂点8平面で構成されるメッシュにShaderMaterialで作成した多色グラデーションを貼り付けている。多色グラデーションは頂点シェーダーとフラグメントシェーダーの組み合わせで実現する。
頂点シェーダー
attribute vec3 verpos; attribute vec3 verrgb; varying vec3 varingrgb; void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(verpos, 1.0); varingrgb = verrgb; }
フラグメントシェーダー
varying mediump vec3 varingrgb; void main() { gl_FragColor = vec4(varingrgb, 1.0); }
verposには頂点の座標、verrgbには頂点の色が渡り、varingrgbでフラグメントシェーダーに引き渡される。頂点シェーダーの処理はVertexに対するが、フラグメントシェーダーはピクセルに対するため、GLSLが色を案分することでグラデーションが実現する。
3D操作はOrbitControls.jsを使っている。
OrbitControls.js
以下は全ソース(html)です。
直下にthree.min.jsとOrbitControls.jsがあれば動作します。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>shade test</title> <script type="text/javascript" src="three.min.js"></script> <script type="text/javascript" src="OrbitControls.js"></script> <script type="text/javascript"> var renderer; var camera; var controls; var scene; var container; var light; var light2; var mesh; var geometry; function shadetest() { init_threejs(); init_scene(); init_camera(); init_light(); init_object(); reset_position(); loop(); } function init_threejs() { renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setClearColor(0xffffff, 1); renderer.setSize(1, 1); container = document.getElementById('canvas3d'); container.appendChild(renderer.domElement); } function init_scene() { scene = new THREE.Scene(); } function init_camera() { camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100000); camera.up.x = 0; camera.up.y = 0; camera.up.z = 1; camera.position.set(0, 0, 5); controls = new THREE.OrbitControls(camera, renderer.domElement); } function init_light() { light = new THREE.DirectionalLight(0xcccccc, 1.6); light.position = new THREE.Vector3(-100, 500, 800); scene.add(light); light2 = new THREE.AmbientLight(0x333333); scene.add(light2); } function init_object() { var vertexPositions = [ [-1.0, -1.0, 1.0], [0.0, -1.0, 1.0], [1.0, -1.0, 1.0], [-1.0, 0.0, 1.0], [0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [-1.0, 1.0, 1.0], [0.0, 1.0, 1.0], [1.0, 1.0, 1.0] ]; var vertexColors = [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], [1.0, 1.0, 0.0], [0.0, 1.0, 1.0], [1.0, 0.0, 1.0], [0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5] ]; var indices = new Uint16Array([ 0, 1, 4, 1, 2, 4, 2, 5, 4, 5, 8, 4, 8, 7, 4, 7, 6, 4, 6, 3, 4, 3, 0, 4 ]); var vertices = new Float32Array(vertexPositions.length * 3); var colors = new Float32Array(vertexPositions.length * 3); for (var i = 0; i < vertexPositions.length; i++) { vertices[i * 3 + 0] = vertexPositions[i][0]; vertices[i * 3 + 1] = vertexPositions[i][1]; vertices[i * 3 + 2] = vertexPositions[i][2]; colors[i * 3 + 0] = vertexColors[i][0]; colors[i * 3 + 1] = vertexColors[i][1]; colors[i * 3 + 2] = vertexColors[i][2]; } var shader = { fragmentShader: [ "varying mediump vec3 varingrgb;", "void main() {", "gl_FragColor = vec4(varingrgb, 1.0);", "}" ].join("\n"), vertexShader: [ "attribute vec3 verpos;", "attribute vec3 verrgb;", "varying vec3 varingrgb;", "void main() {", "gl_Position = projectionMatrix * modelViewMatrix * vec4(verpos, 1.0);", "varingrgb = verrgb;", "}" ].join("\n") } var material = new THREE.ShaderMaterial( { vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader } ); var geometry = new THREE.BufferGeometry(); geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3)); geometry.setIndex(new THREE.BufferAttribute(indices, 1)); geometry.addAttribute('verpos', new THREE.BufferAttribute(vertices, 3)); geometry.addAttribute('verrgb', new THREE.BufferAttribute(colors, 3)); var mesh = new THREE.Mesh(geometry, material); mesh.position.set(0, 0, 0); scene.add(mesh); } function reset_position() { var sz = {w:container.offsetWidth, h:container.offsetHeight}; renderer.setSize(sz.w, sz.h); camera.aspect = sz.w / sz.h; camera.updateProjectionMatrix(); } function loop() { requestAnimationFrame(loop); controls.update(); renderer.clear(); renderer.render(scene, camera); } </script> </head> <body onload="shadetest();" onresize="reset_position();"> <div id="canvas3d" style="width:300px;height:300px;"> </div> </body> </html>
1 thought on “three.jsで多色グラデーション”