Tutorial 14: Outline fonts

 

Tutorial 15: Texture Mapped Outline Fonts

This tutorial assumes, that you have read and understood lesson 14.
To see the lessons result, you can jump to the live example.
This tutorial has been created by Ric Wright, www.geofx.com.
 
WebGL
Screenshot of the WebGL renderer
Chrome Firefox Safari Opera Internet Explorer
Canvas renderer is not supported
Advertisement
 
Tutorial
  1 <!DOCTYPE html> 
  2 <!-- The previous line tells the browser that the page uses the HTML5 standard. --> 
  3 <html><head> 
  4         <!-- ------------------------------------- 
  5               Roughly based (or inspired by) NeHe Tutorial 15   
  6               Original:  http://nehe.gamedev.net/tutorial/texture_mapped_outline_fonts/18001/ 
  7    
  8               @author: rkwright@geofx.com 
  9         -------------------------------------- --> 
 10         <title>NEHE Tutorial 15</title> 
 11         <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
 12  
 13         <!-- The following meta line optimizes the site for mobile devices. It sets the viewport size 
 14         to the screen size, so it will be displayed maximized, but unscaled. --> 
 15         <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"> 
 16         <link rel="stylesheet" type="text/css" href="../css/NEHE.css">  
 17  
 18         <!-- Include several libraries from THREE.js and the Scene class  --> 
 19         <script src="../js/r69/three.js" type="text/javascript"></script> 
 20         <script src="../js/r69/Detector.js" type="text/javascript"></script> 
 21         <script src="../js/r69/OrbitControls-Touch.js" type="text/javascript"></script> 
 22         <script src="../js/r69/Stats.js" type="text/javascript"></script> 
 23         <script src="../js/r69/Scene.js" type="text/javascript"></script> 
 24  
 25         <!-- include the JSON format font files we will use --> 
 26         <script src="../fonts/gentilis_bold.js"></script> 
 27         <script src="../fonts/gentilis_regular.js"></script> 
 28          
 29         <!-- the shaders -------------------------------------------------- --> 
 30         <script id="vertexShader" type="x-shader/x-vertex"> 
 31             varying vec3         vNormal; 
 32             varying vec2         vUv; 
 33          
 34             /** 
 35              * Multiply each vertex by the model-view matrix and the projection  
 36              * matrix (both provided by Three.js) to get a final vertex position
 37              */ 
 38             void main() { 
 39                  
 40                 // set the variables passed (behind the scenes) by three.js to our 
 41                 // "varying" variables, which makes them available to the other shader 
 42                 vNormal = normal; 
 43                 vUv = uv; 
 44  
 45                 gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); 
 46             } 
 47         </script> 
 48              
 49         <script id="fragmentShader" type="x-shader/x-fragment"> 
 50             // create the shared variables. which are set in the vertex shader 
 51             varying vec3         vNormal; 
 52             varying vec2         vUv; 
 53             uniform sampler2D     texImage; 
 54  
 55             void main(void) { 
 56              
 57                 gl_FragColor = texture2D(texImage, vUv); 
 58             } 
 59         </script> 
 60          
 61         <script id="fragmentShader-L" type="x-shader/x-fragment"> 
 62             // create the shared variables. which are set in the vertex shader 
 63             varying vec3         vNormal; 
 64             varying vec2         vUv; 
 65             uniform sampler2D     leatherImage; 
 66  
 67             void main(void) { 
 68              
 69                 gl_FragColor = texture2D(leatherImage, vUv); 
 70             } 
 71         </script> 
 72     <!-- --------------------------------------------------------------- --> 
 73     </head> 
 74     <body>     
 75         <script> 
 76             // global variables 
 77             var     textGeom; 
 78          
 79             var     size = 1;                // this is actually the HEIGHT of the text. in user-space 
 80             var     height = 0.2;            // this is TOTALLY misnamed.  It is the thickness of the extruded text 
 81             var        curveSegments = 10;        // number of points on "the curve" - which curve? 
 82             var     font = "gentilis"; 
 83             var        weight = "bold"; 
 84             var        style = "normal"; 
 85  
 86             var        bevelThickness = 0.05; 
 87             var        bevelSize = 0.05; 
 88             var     bevelEnabled = false; 
 89  
 90             var        textMat = 0; 
 91             var     extrudeMaterial = 0; 
 92             var        text= "Shazaam!"; 
 93             var     texture; 
 94             var     leather; 
 95              
 96             // allocate the Scene object, request orbitControls, some of 3D axes 10 units high and the stats 
 97             var nScene = new Scene( { axisHeight:10, controls:true, displayStats:true }); 
 98              
 99             // set up the THREE.js scene via our Scene object 
100             nScene.initialize(); 
101              
102             // then initialize our demo's stuff 
103             initializeDemo(); 
104  
105             // Animate the scene 
106             animateScene(); 
107  
108             /** 
109              * Initialize the Demo.   
110              */ 
111             function initializeDemo() { 
112  
113                 createText(); 
114             }; 
115                  
116             /** 
117              * Here we actually create the text.  Not too much to it, actually.
118              */ 
119             function createText() { 
120  
121                 // Note that one has to create a Material for both the face the side of the font. 
122                 // Three.js has some bugs, as does the font-converter software at typface.js  
123                 // http://typeface.neocracy.org/fonts.html.  The converter doesn't always keep the 
124                 // same winding order for nested or adjacent paths and then three.js gets confused 
125                 // In addition, with release 69 of three.js, you should not use smooth shading on the face  
126                 // of the font. If you do, you will get some pretty odd artifacts.  Try it and see. 
127                 // However, the face of the font is flat anyway, so flat shading is fine. 
128                 // In addition, you shouldn't use Phong material on the sides.  Again, you'll get odd 
129                 // artifacts. 
130                 // Finally, go easy on the beveling as large bevels tend to look odd (more bugs?) 
131                  
132                 // load the image as a texture 
133                 texture = new THREE.ImageUtils.loadTexture("images/wood-grain.jpg"); 
134                 leather = new THREE.ImageUtils.loadTexture("images/green-pebbled-leather.jpg"); 
135                 // ensure that our texture gets wrapped so the coverage is complete and uniform 
136                 // also note that the texture needs to be big enough (e.g. at least 512x512) or 
137                 // the sharper curvers will be so stretched it will blur 
138                 texture.wrapS = texture.wrapT = THREE.RepeatWrapping; 
139                 leather.wrapS = leather.wrapT = THREE.RepeatWrapping; 
140  
141                 // add a uniform for the texture.  This is the read-only  
142                 // variables that get passed to our shaders 
143                 var uniforms = { 
144                         texImage:    { type: 't', value: texture } 
145                 }; 
146  
147                 var uniformsL = { 
148                         leatherImage:    { type: 't', value: leather } 
149                 }; 
150  
151                 // find the shaders 
152                 var vs = document.getElementById("vertexShader").textContent; 
153                 var fs = document.getElementById("fragmentShader").textContent; 
154                 var fsL = document.getElementById("fragmentShader-L").textContent; 
155  
156                 // and create our shader material... 
157                 var shaderMaterial = new THREE.ShaderMaterial({ 
158                         uniforms:         uniforms,            // pass the "uniforms" vars 
159                         shading:        THREE.FlatShading, 
160                         side:           THREE.DoubleSide,    // want the texture on both sides? 
161                         vertexShader:   vs,                    // pointers to the shaders 
162                         fragmentShader: fs 
163                     }); 
164  
165                 var shaderMaterialL = new THREE.ShaderMaterial({ 
166                     uniforms:         uniformsL,            // pass the "uniforms" vars 
167                     shading:        THREE.FlatShading, 
168                     side:           THREE.DoubleSide,    // want the texture on both sides? 
169                     vertexShader:   vs,                    // pointers to the shaders 
170                     fragmentShader: fsL 
171                 }); 
172  
173                 var materialFront = shaderMaterial; 
174                 var materialSide  = shaderMaterialL; 
175                 var materialArray = [ materialFront, materialSide ]; 
176  
177                 textGeom = new THREE.TextGeometry( text , { 
178                     size: size,                        // actually the height of the font, in user-space 
179                     height: height,                    // THICKNESS of the extruded font, in user-space 
180                     curveSegments: curveSegments, 
181                     font: font,                        // name of the font 
182                     weight: weight,                    // bold or normal 
183                     style: style,                    // regular, italic or bold 
184                     bevelThickness: bevelThickness, 
185                     bevelSize: bevelSize, 
186                     bevelEnabled: bevelEnabled, 
187                     material: 0,                    // index in the array of the face 
188                     extrudeMaterial: 1                // index in the array of the extruded sides 
189                 }); 
190                  
191                 var textMaterial = new THREE.MeshFaceMaterial(materialArray); 
192                 var textMesh = new THREE.Mesh(textGeom, textMaterial ); 
193  
194                 textGeom.computeBoundingBox(); 
195                 textGeom.computeVertexNormals(); 
196                  
197                 nScene.addToScene(textMesh); 
198                  
199                 // get the width of the string so we can center it on the origin 
200                 textGeom.computeBoundingBox(); 
201                  
202                 var textWidth = textGeom.boundingBox.max.x - textGeom.boundingBox.min.x; 
203                  
204                 textMesh.position.set(-0.5 * textWidth, 0, 0.5 ); 
205                 nScene.addToScene(textMesh); 
206             } 
207  
208             /** 
209              * Animate the scene and call rendering. 
210              */ 
211             function animateScene() { 
212  
213                 // Tell the browser to call this function when page is visible 
214                 requestAnimationFrame(animateScene); 
215                  
216                 // Map the 3D scene down to the 2D screen (render the frame) 
217                 nScene.renderScene(); 
218             } 
219         </script><div><canvas style="width: 1537px; height: 526px;" height="526" width="1537"></canvas><div style="cursor: pointer; width: 80px; opacity: 0.9; z-index: 100; position: absolute; bottom: 0px;"><div style="text-align: left; line-height: 1.2em; background-color: rgb(8, 8, 24); padding: 0px 0px 3px 3px;"><div style="font-family: Helvetica,Arial,sans-serif; font-size: 9px; color: rgb(0, 255, 255); font-weight: bold;">9 FPS (3-9)</div><div style="position: relative; width: 74px; height: 30px; background-color: rgb(0, 255, 255);"><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 30px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 29.1px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 28.5px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.6px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.9px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.3px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.6px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 28.5px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.9px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.6px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.9px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.3px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.3px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 28.2px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 28.2px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.6px; float: left; background-color: rgb(16, 16, 48);"></span><span style="width: 1px; height: 27.3px; float: left; background-color: rgb(16, 16, 48);"></span></div></div><div style="text-align: left; line-height: 1.2em; background-color: rgb(8, 24, 8); padding: 0px 0px 3px 3px; display: none;"><div style="font-family: Helvetica,Arial,sans-serif; font-size: 9px; color: rgb(0, 255, 0); font-weight: bold;">148 MS (19-918)</div><div style="position: relative; width: 74px; height: 30px; background-color: rgb(0, 255, 0);"><span style="width: 1px; height: 11.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 9.3px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 3.3px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.35px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.85px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.35px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.3px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.6px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.05px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.95px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.85px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.65px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 1.08474px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.4175px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.65px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.45px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 16.35px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 16.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.9px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.6px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.7px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.55px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 15.75px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.1px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.2px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.55px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.8px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.55px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 1.2px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 15.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 15.6px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.05px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 16.2px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.75px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.1px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 3.6px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 16.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 3.15px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.75px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 7.05px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 7.5px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.4px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 10.65px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.7px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 4.95px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.85px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.2px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.35px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.1px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.1px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 11.55px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 13.65px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 16.8px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.45px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 12.9px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 8.7px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.4px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 14.1px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 0.45px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 2.25px; float: left; background-color: rgb(16, 48, 16);"></span><span style="width: 1px; height: 7.8px; float: left; background-color: rgb(16, 48, 16);"></span></div></div></div></div> 
220      
221  
222 </body></html>
Scene.js
  1     //some constants 
  2     var        X_AXIS = 0; 
  3     var        Y_AXIS = 1; 
  4     var        Z_AXIS = 2; 
  5      
  6 Scene = function ( parameters ) { 
  7      
  8     this.scene; 
  9     this.renderer; 
 10     this.camera; 
 11  
 12     this.controls = false; 
 13     this.orbitControls; 
 14  
 15     this.displayStats = false; 
 16     this.stats; 
 17  
 18     this.ambientLight; 
 19     this.directionalLight; 
 20  
 21     this.axisHeight = 0; 
 22  
 23     this.setParameters( parameters ); 
 24 }; 
 25  
 26 // the scene's parameters from the values JSON object 
 27 // lifted from MrDoob's implementation in three.js 
 28 Scene.prototype = { 
 29          
 30     setParameters: function( values ) { 
 31  
 32         if ( values === undefined ) return; 
 33      
 34         for ( var key in values ) { 
 35      
 36             var newValue = values[ key ]; 
 37      
 38             if ( newValue === undefined ) { 
 39                 console.warn( "NEHE: '" + key + "' parameter is undefined." ); 
 40                 continue; 
 41             } 
 42      
 43             if ( key in this ) { 
 44                 var currentValue = this[ key ]; 
 45      
 46                 if ( currentValue instanceof THREE.Color ) { 
 47                     currentValue.set( newValue ); 
 48                 } else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) { 
 49                     currentValue.copy( newValue ); 
 50                 } else if ( key == 'overdraw' ) { 
 51                     // ensure overdraw is backwards-compatible with legacy boolean type 
 52                     this[ key ] = Number( newValue ); 
 53                 } else { 
 54                     this[ key ] = newValue; 
 55                 } 
 56             } 
 57         } 
 58     }, 
 59  
 60     initialize: function () { 
 61         // Check whether the browser supports WebGL.  
 62         if ( !Detector.webgl ) Detector.addGetWebGLMessage(); 
 63      
 64         // Create the scene, in which all objects are stored (e. g. camera, lights, geometries, ...) 
 65         this.scene = new THREE.Scene(); 
 66      
 67         // Get the size of the inner window (content area) 
 68         var canvasWidth = window.innerWidth; 
 69         var canvasHeight = window.innerHeight; 
 70      
 71         // if the caller supplied the container elm ID try to find it 
 72         var container; 
 73         var containerID; 
 74         if (containerID != null && typeof containerID != 'undefined') 
 75             container = document.getElementById(containerID); 
 76          
 77         // couldn't find it, so create it ourselves 
 78         if (container == null || typeof container == 'undefined') { 
 79             container = document.createElement( 'div' ); 
 80             document.body.appendChild( container ); 
 81         } 
 82         else { 
 83             canvasWidth = container.clientWidth; 
 84             canvasHeight = container.clientHeight; 
 85         } 
 86      
 87         // set up the camera 
 88         this.camera = new THREE.PerspectiveCamera(45, canvasWidth / canvasHeight, 0.1, 1000); 
 89         this.camera.position.set(0, 6, 6); 
 90         this.camera.lookAt(this.scene.position); 
 91         this.scene.add(this.camera); 
 92      
 93         // allocate the THREE.js renderer 
 94         this.renderer = new THREE.WebGLRenderer({antialias:true}); 
 95      
 96         // Set the background color of the renderer to black, with full opacity 
 97         this.renderer.setClearColor(0x000000, 1); 
 98      
 99         // Set the renderers size to the content areas size 
100         this.renderer.setSize(canvasWidth, canvasHeight); 
101      
102         // Get the DIV element from the HTML document by its ID and append the renderer's DOM object 
103         container.appendChild(this.renderer.domElement); 
104          
105         // Ambient light has no direction, it illuminates every object with the same 
106         // intensity. If only ambient light is used, no shading effects will occur. 
107         this.ambientLight = new THREE.AmbientLight(0x404040); 
108         this.scene.add(this.ambientLight); 
109      
110         // Directional light has a source and shines in all directions, like the sun. 
111         // This behaviour creates shading effects. 
112         this.directionalLight = new THREE.PointLight(0xffffff); 
113         this.directionalLight.position.set(250,250,250);  
114         this.scene.add(this.directionalLight); 
115          
116         // request the orbitControls be created and enabled 
117         // add the controls 
118         if (this.controls == true) 
119             this.orbitControls = new THREE.OrbitControls( this.camera, this.renderer.domElement ); 
120          
121         if ( this.axisHeight != 0 ) 
122             this.drawAxes(this.axisHeight); 
123          
124         //------ STATS --------------------     
125         // displays current and past frames per second attained by scene 
126         if (this.displayStats == true) { 
127             this.stats = new Stats(); 
128             this.stats.domElement.style.position = 'absolute'; 
129             this.stats.domElement.style.bottom = '0px'; 
130             this.stats.domElement.style.zIndex = 100; 
131             container.appendChild( this.stats.domElement ); 
132         } 
133     }, 
134  
135     addToScene: function ( obj ) { 
136         this.scene.add(obj); 
137     }, 
138  
139 /** 
140  * Render the scene. Map the 3D world to the 2D screen. 
141  */ 
142     renderScene: function() { 
143          
144         this.renderer.render(this.scene, this.camera); 
145  
146         // the orbit controls, if used, have to be updated as well 
147         if (this.orbitControls != null && typeof this.orbitControls != 'undefined')  
148             this.orbitControls.update(); 
149  
150         if (this.stats != null && typeof this.stats != 'undefined')  
151             this.stats.update(); 
152  
153 }, 
154  
155 // draw some axes 
156     drawAxis: function( axis, axisColor, axisHeight ) { 
157         var        AXIS_RADIUS   =    axisHeight/200.0; 
158         var        AXIS_HEIGHT   =    axisHeight; 
159         var        AXIS_STEP     =    axisHeight/20.0; 
160         var        AXIS_SEGMENTS = 32; 
161         var        AXIS_GRAY     = 0x777777; 
162         var        AXIS_WHITE    = 0xEEEEEE; 
163          
164         //console.log("drawAxis " + axis + " ht: " +  AXIS_HEIGHT + ", " + AXIS_STEP + " color: " + axisColor); 
165      
166         for ( i=0; i<(AXIS_HEIGHT/AXIS_STEP); i++ ) 
167         { 
168             //console.log("loop " +  i); 
169              
170             var pos = -AXIS_HEIGHT / 2 + i * AXIS_STEP; 
171      
172             if ((i & 1) == 0) 
173                 curColor = axisColor; 
174             else if (pos < 0) 
175                 curColor = AXIS_GRAY; 
176             else 
177                 curColor = AXIS_WHITE; 
178              
179             //console.log(i + " pos: " + pos + " color: " + curColor); 
180              
181             var geometry = new THREE.CylinderGeometry( AXIS_RADIUS, AXIS_RADIUS, AXIS_STEP, AXIS_SEGMENTS );  
182             var material = new THREE.MeshLambertMaterial( {color: curColor} );  
183             var cylinder = new THREE.Mesh( geometry, material );  
184              
185             pos += AXIS_STEP/2.0; 
186             if (axis == X_AXIS) 
187             { 
188                 cylinder.position.x = pos; 
189                 cylinder.rotation.z = Math.PI/2; 
190             } 
191             else if (axis == Y_AXIS) 
192             { 
193                 cylinder.rotation.y = Math.PI/2; 
194                 cylinder.position.y = pos; 
195             } 
196             else 
197             {     
198                 cylinder.position.z = pos; 
199                 cylinder.rotation.x = Math.PI/2; 
200             } 
201              
202             this.scene.add( cylinder ); 
203         }; 
204     }, 
205  
206     drawAxes: function( height ) { 
207      
208         this.drawAxis(X_AXIS, 0xff0000, height); 
209         this.drawAxis(Y_AXIS, 0x00ff00, height); 
210         this.drawAxis(Z_AXIS, 0x0000ff, height); 
211     } 
212 }
NEHE.css
  1 /* 
  2  * @author rkwright   /  www.geofx.com 
  3  */ 
  4   
  5  body { 
  6     /* Set the background color of the HTML page to black */ 
  7     background-color: #000000; 
  8  
  9     /* Hide oversized content. This prevents the scroll bars. */ 
 10     overflow: hidden; 
 11  
 12     /* Define the font and the color for the usage, which is an ordinary HTML overlay. */ 
 13     font-family: Monospace; 
 14     color: white; 
 15 }
Live example