JSFiddle - React, Tailwind, and code Playground
by YouTingKuo
HTML
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script id="vertex_shader" type="x-shader/x-vertex">
#define NVERTS 4
varying vec3 vNormal;
varying vec3 vViewPosition;
void main() {
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
vNormal = normalize( normalMatrix * normal );
vViewPosition = -mvPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
#define NVERTS 4
uniform vec3 color;
uniform vec3 lightColor;
uniform float lightIntensity;
uniform vec3 lightverts[ NVERTS ]; // in local space
uniform mat4 lightMatrixWorld;
varying vec3 vNormal; // in camera space
varying vec3 vViewPosition; // in camera space
void main() {
vec3 normal = normalize( vNormal );
vec4 lPosition[ NVERTS ];
vec3 lVector[ NVERTS ];
// stub in some ambient reflectance
vec3 ambient = color * vec3( 0.2 );
// direction vectors from point to area light corners
for( int i = 0; i < NVERTS; i ++ ) {
lPosition[ i ] = viewMatrix * lightMatrixWorld * vec4( lightverts[ i ], 1.0 ); // in camera space
lVector[ i ] = normalize( lPosition[ i ].xyz + vViewPosition.xyz ); // dir from vertex to areaLight
}
// bail if the point is on the wrong side of the light... there must be a better way...
float tmp = dot( lVector[ 0 ], cross( ( lPosition[ 2 ] - lPosition[ 0 ] ).xyz, ( lPosition[ 1 ] - lPosition[ 0 ] ).xyz ) );
if ( tmp > 0.0 ) {
gl_FragColor = vec4( ambient, 1.0 );
return;
}
// vector irradiance at point
vec3 lightVec = vec3( 0.0 );
for( int i = 0; i < NVERTS; i ++ ) {
vec3 v0 = lVector[ i ];
vec3 v1 = lVector[ int( mod( float( i + 1 ), float( NVERTS ) ) ) ]; // ugh...
lightVec += acos( dot( v0, v1 ) ) * normalize( cross( v0, v1 ) );
}
// irradiance factor at point
float factor = max( dot( lightVec, normal ), 0.0 ) / ( 2.0...
CSS
body {
background-color: #000;
margin: 0px;
overflow: hidden;
}
JavaScript
// Area Light Shader for three.js r.58
// WestLangley
var renderer, scene, camera, controls;
var areaLight, material, mesh;
var t = 0, delta = 0.004;
init();
animate();
function init() {
// info
info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '30px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.color = '#fff';
info.style.fontWeight = 'bold';
info.style.backgroundColor = 'transparent';
info.style.zIndex = '1';
info.style.fontFamily = 'Monospace';
info.innerHTML = 'Drag mouse to rotate camera; scroll to zoom';
document.body.appendChild( info );
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.physicallyBasedShading = true;
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 150, 50, 150 );
// controls
controls = new THREE.OrbitControls( camera );
// axes
scene.add( new THREE.AxisHelper( 200 ) );
// area light
var lightColor = 0xffffff;
var lightIntensity = 1;
var geometry = new THREE.PlaneGeometry( 100, 50 );
var material = new THREE.MeshBasicMaterial( {
color: lightColor, transparent: true, opacity: 0.7, side: THREE.FrontSide } );
areaLight = new THREE.Mesh( geometry, material );
areaLight.position.set( 0, 25, -25 );
areaLight.rotation.set( 0, 0, 0 );
areaLight.scale.set( 1, 1, 1 );
scene.add( areaLight );
// wireframe hack
areaLight.add( new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { wireframe: true } ) ) );
// areaLight verts
var vertices = areaLight.geometry.vertices;
var verts = [];
verts.push( vertices[ 0 ] );
verts.push( vertices[ 1 ] );
verts.push( vertices[ 3 ] ); // swap 2 & 3; must be in clockwise order; they are not
verts.push( vertices[ 2 ] );
// uniforms
var...