three.js ~ Cylinder + Sphere Impostor Example
2016-14-03
by Ludovic Bailly
HTML
<script src="http://threejs.org/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script id="shaderCyl-vs" type="x-shader/x-vertex">
// Inherits from Phong Shading in ThreeJS, allows compatibility with chunks
#define PHONG
// Normalize diagonal matrix (1)
const mat4 D = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, -1.0)
);
const mat4 t1 = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 1.0)
);
const mat4 t2 = mat4(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, -1.0, 1.0)
);
// Create transpose method (not built-in OpenGL ES Shading Language)
highp mat4 transpose(in highp mat4 inMatrix) {
highp vec4 i0 = inMatrix[0];
highp vec4 i1 = inMatrix[1];
highp vec4 i2 = inMatrix[2];
highp vec4 i3 = inMatrix[3];
highp mat4 outMatrix = mat4(
vec4(i0.x, i1.x, i2.x, i3.x),
vec4(i0.y, i1.y, i2.y, i3.y),
vec4(i0.z, i1.z, i2.z, i3.z),
vec4(i0.w, i1.w, i2.w, i3.w)
);
return outMatrix;
}
#include <common>
#include <color_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>
attribute float radius;
attribute vec3 dir;
uniform vec4 viewport;
uniform mat4 modelViewMatrixInverse;
varying mat4 MTInverse;
varying mat4 VPInverse;
varying vec4 centernormclip;
// Near, far, width and height
varying float n, f, w, h;
varying float projMatrix11;
varying float projMatrix22;
// Compatibility with threejs chunks
varying vec3 vViewPosition;
varying vec3 vViewDirection;
varying float vLength;
void main() {
// Chunck to color vertex with vertex color attribute
#include <color_vertex>
// Chunck to compute position in world space
#include <begin_vertex>
#include <project_vertex>
#include <logdepthbuf_vertex>
...
JavaScript
var camera, scene, light, renderer, geometryCyl, geometrySphere, material, mesh1, mesh2, gl;
var WIDTH = window.innerWidth - 20;
var HEIGHT = window.innerHeight - 20;
var controls;
var impostorMaterialCyl;
var impostorMaterialSphere;
createImpostorMaterial();
init();
animate();
function init() {
scene = new THREE.Scene();
var axisHelper = new THREE.AxisHelper( 1 );
scene.add( axisHelper );
camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, 1, 100);
camera.position.z = 30;
camera.position.y = 0;
var ambient = new THREE.AmbientLight( 0x404040 );
scene.add(ambient);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.0 );
directionalLight.position.set( 0, 3, 3 );
scene.add( directionalLight );
var helper = new THREE.DirectionalLightHelper(directionalLight, 1);
scene.add(helper);
scene.add(camera);
// controls
controls = new THREE.OrbitControls( camera );
var geometry1 = createBufferGeometryCyl();
mesh1 = new THREE.Points(geometry1, impostorMaterialCyl);
scene.add(mesh1);
var geometry2 = createBufferGeometrySphere();
mesh2 = new THREE.Points(geometry2, impostorMaterialSphere);
scene.add(mesh2);
renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true});
renderer.setSize(WIDTH, HEIGHT);
renderer.autoClear = false;
renderer.sortObjects = true;
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// Clear renderer
renderer.clear();
// Update uniforms for outline
updateMaterialUniforms(scene, camera);
// Render the scene
renderer.render(scene, camera);
}
function createBufferGeometryCyl() {
var geometry = new THREE.BufferGeometry();
// Creating array buffers
var positionArray = [];
var colorArray = [];
var radiusArray = [];
var dirArray = [];
...