<script id="fragShader" type="shader-code">
uniform sampler2D tex;//The main texture
uniform sampler2D norm;//The normal texture
uniform vec2 res;//Our screen dimensions
uniform vec4 light;//Our light source information
void main() {
vec2 pixel = gl_FragCoord.xy / res.xy;
vec4 color = texture2D(tex,pixel);
vec4 normalVector = texture2D(norm,pixel);//We get the normal value of this pixel
vec2 lightPosition = light.xy / res.xy;//We normalize the light source
lightPosition.y = 1.0 - lightPosition.y;
//We calculate the direction from the light to this pixel
vec3 LightVector = vec3(lightPosition.x - pixel.x,lightPosition.y - pixel.y,light.z);
//By "up" direction of our normal map has the value (0.5,0.5,1.0) in terms of rgb
//So we offset by that amount
normalVector.x -= 0.5;
normalVector.y -= 0.5;
//We normalize our vectors to compute the direction
vec3 NormalVector = normalize(normalVector.xyz);
LightVector = normalize(LightVector);
// Compute the diffuse term for the Phong equation
float diffuse = 1.5 * max(dot( NormalVector, LightVector ),0.0);
//Toggle light system on or off
if(light.w == 0.0){
gl_FragColor = color;
} else {
gl_FragColor = color * diffuse;
}
}
</script>
/* We want our scene to span the entire window */
body { margin: 0; }
//@author Omar Shehata. 2015.
//We are loading the Three.js library from the cdn here: https://cdnjs.com/libraries/three.js/
var scene;
var camera;
var renderer;
function scene_setup(){
//This is all code needed to set up a basic ThreeJS scene
//First we initialize the scene and our camera
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
//We create the WebGL renderer and add it to the document
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
//Initialize the Threejs scene
scene_setup();
//Pull the shader code from the html
var shaderCode = document.getElementById("fragShader").innerHTML;
//Our textures are up on github
var textureURL = "https://raw.githubusercontent.com/tutsplus/Beginners-Guide-to-Shaders/master/Part3/images/blocks.JPG"
var normalURL = "https://raw.githubusercontent.com/tutsplus/Beginners-Guide-to-Shaders/master/Part3/normal_maps/blocks_normal.JPG"
THREE.ImageUtils.crossOrigin = '';//Allows us to load an external image
//Load in the texture and the normal
var texture = THREE.ImageUtils.loadTexture(textureURL);
var normal = THREE.ImageUtils.loadTexture(normalURL);
//Set up the uniforms we'll send to our share
//More info on uniform types: https://threejs.org/docs/#Reference/Materials/ShaderMaterial
var uniforms = {
tex : {type:'t',value:texture},//The texture
norm: {type:'t',value:normal},//Normal
res : {type: 'v2',value:new THREE.Vector2(window.innerWidth,window.innerHeight)},//Keeps the resolution
light: {type: 'v4',value:new THREE.Vector4()}//Our light source, we will use the 3 numbers as have x,y and height away from the screen. 4th value is whether the light is on or not
}
//We stick our shader onto a 2d plane big enough to fill the screen
var material = new THREE.ShaderMaterial({uniforms:uniforms,fragmentShader:shaderCode})
var geometry = new THREE.PlaneGeometry( 10, 10 );
var sprite = new THREE.Mesh( geometry,material );
//Add it to the scene
scene.add( sprite );
//Move the camera back so we can see it
camera.position.z = 2;
uniforms.light.value.z = 0.3;//How high up our light source should be
uniforms.light.value.w = 1.0;//Turn light on
//Render everything!
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
document.onmousemove = function(event){
//Update the light source to follow our mouse
uniforms.light.value.x = event.clientX;
uniforms.light.value.y = event.clientY;
}
document.onmousedown = function(event){
//Toggle lighting system
if( uniforms.light.value.w)
uniforms.light.value.w = 0.0;
else uniforms.light.value.w = 1.0;
}
This Pen doesn't use any external CSS resources.