小德

超级版主
  • 主题:17
  • 回复:42
  • 金钱:142
  • 积分:301
I made a low-poly model for our game, finished it around midnight and was looking for feedback from my friends. Taking pictures from every possible angle or even recording a short turntable animation were too much work for me as I had already been very tired. So I created a WebGL model viewer in three.js. This took me about an hour and propably much longer than the images would have but was so much more fun and exciting. Also my tiredness suddenly disappeared while working on the model viewer.
It turned out pretty well and that is why I want to share this small tutorial on how to build a WebGL 3Dmodel viewer with three.js. Before you start, you have to gather some things which you’ll be working with:
  • Your model in OBJ format. If you do not know how to export your model, please take a look at the manual of Blender, Maya, Modo or whatever software you are using.
  • You texture in PNG or JPG format, of course as a square power-of-two texture.
  • The latest build of the three.js library, mine is r61.
  • TrackballControls.js for cool camera control.
  • OBJLoader.js for loading the model and Detector.js, which detects if your browser can handle WebGL.
Put the files in a folder and reference them in a simple HTML page as in the code snippet below. I also recommend you to set some styles for the background, so your character does not have to sit in an empty white void. I like empty dark voids, so I set the background to black.
[color=rgb(98, 98, 98) !important]WebGL 3d model viewer using three.js – HTML









[color=rgb(98, 98, 98) !important]XHTML



1

[color=rgb(151, 151, 151) !important]2

3

[color=rgb(151, 151, 151) !important]4

5

[color=rgb(151, 151, 151) !important]6

7

[color=rgb(151, 151, 151) !important]8

9

[color=rgb(151, 151, 151) !important]10

11

[color=rgb(151, 151, 151) !important]12

13

[color=rgb(151, 151, 151) !important]14

15

[color=rgb(151, 151, 151) !important]16

17

[color=rgb(151, 151, 151) !important]18


[color=rgb(255, 255, 255) !important][color=rgb(102, 102, 102) !important]<!DOCTYPE html>
[color=rgb(248, 248, 242) !important]<html>
[color=rgb(248, 248, 242) !important]<head>
  <meta charset="utf-8">
  <title>WebGL 3D model viewer using three.js</title>
[color=rgb(248, 248, 242) !important]  <script src="viewer/three.js"></script>
[color=rgb(248, 248, 242) !important]  <script src="viewer/TrackballControls.js"></script>
[color=rgb(248, 248, 242) !important]  <script src="viewer/OBJLoader.js"></script>
[color=rgb(248, 248, 242) !important]  <script src="viewer/Detector.js"></script>
[color=rgb(248, 248, 242) !important]</head>
[color=rgb(248, 248, 242) !important]<body>

[color=rgb(248, 248, 242) !important]  <script>
    // This is where our model viewer code goes.
  </script>

[color=rgb(248, 248, 242) !important]</body>
[color=rgb(248, 248, 242) !important]</html>



The code is pretty self-explanatory, so instead of explaining the different parts I have created comments. It may be easier to read if you paste it into an editor with syntax highlighting.
[color=rgb(98, 98, 98) !important]WebGL 3D model viewer using three.js – JS









[color=rgb(98, 98, 98) !important]JavaScript



1

[color=rgb(151, 151, 151) !important]2

3

[color=rgb(151, 151, 151) !important]4

5

[color=rgb(151, 151, 151) !important]6

7

[color=rgb(151, 151, 151) !important]8

9

[color=rgb(151, 151, 151) !important]10

11

[color=rgb(151, 151, 151) !important]12

13

[color=rgb(151, 151, 151) !important]14

15

[color=rgb(151, 151, 151) !important]16

17

[color=rgb(151, 151, 151) !important]18

19

[color=rgb(151, 151, 151) !important]20

21

[color=rgb(151, 151, 151) !important]22

23

[color=rgb(151, 151, 151) !important]24

25

[color=rgb(151, 151, 151) !important]26

27

[color=rgb(151, 151, 151) !important]28

29

[color=rgb(151, 151, 151) !important]30

31

[color=rgb(151, 151, 151) !important]32

33

[color=rgb(151, 151, 151) !important]34

35

[color=rgb(151, 151, 151) !important]36

37

[color=rgb(151, 151, 151) !important]38

39

[color=rgb(151, 151, 151) !important]40

41

[color=rgb(151, 151, 151) !important]42

43

[color=rgb(151, 151, 151) !important]44

45

[color=rgb(151, 151, 151) !important]46

47

[color=rgb(151, 151, 151) !important]48

49

[color=rgb(151, 151, 151) !important]50

51

[color=rgb(151, 151, 151) !important]52

53

[color=rgb(151, 151, 151) !important]54

55

[color=rgb(151, 151, 151) !important]56

57

[color=rgb(151, 151, 151) !important]58

59

[color=rgb(151, 151, 151) !important]60

61

[color=rgb(151, 151, 151) !important]62

63

[color=rgb(151, 151, 151) !important]64

65

[color=rgb(151, 151, 151) !important]66

67

[color=rgb(151, 151, 151) !important]68

69

[color=rgb(151, 151, 151) !important]70

71

[color=rgb(151, 151, 151) !important]72

73

[color=rgb(151, 151, 151) !important]74

75

[color=rgb(151, 151, 151) !important]76

77

[color=rgb(151, 151, 151) !important]78

79

[color=rgb(151, 151, 151) !important]80

81

[color=rgb(151, 151, 151) !important]82

83

[color=rgb(151, 151, 151) !important]84

85

[color=rgb(151, 151, 151) !important]86

87

[color=rgb(151, 151, 151) !important]88

89

[color=rgb(151, 151, 151) !important]90

91

[color=rgb(151, 151, 151) !important]92

93

[color=rgb(151, 151, 151) !important]94

95

[color=rgb(151, 151, 151) !important]96

97

[color=rgb(151, 151, 151) !important]98

99

[color=rgb(151, 151, 151) !important]100

101

[color=rgb(151, 151, 151) !important]102

103

[color=rgb(151, 151, 151) !important]104

105

[color=rgb(151, 151, 151) !important]106


[color=rgb(255, 255, 255) !important]var container;
var camera, scene, renderer;
var mouseX = 0, mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

init();
animate();

[color=rgb(117, 113, 94) !important]/*** Initialize ***/
function init() {
  // This <div> will host the canvas for our scene.
  container = document.createElement( 'div' );
  document.body.appendChild( container );

  // You can adjust the cameras distance and set the FOV to something
  // different than 45°. The last two values set the clippling plane.
  camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
  camera.position.z = 100;

  // These variables set the camera behaviour and sensitivity.
  controls = new THREE.TrackballControls( camera );
  controls.rotateSpeed = 5.0;
  controls.zoomSpeed = 5;
  controls.panSpeed = 2;
  controls.noZoom = false;
  controls.noPan = false;
  controls.staticMoving = true;
  controls.dynamicDampingFactor = 0.3;

  // This is the scene we will add all objects to.
  scene = new THREE.Scene();

  // You can set the color of the ambient light to any value.
  // I have chose a completely white light because I want to paint
  // all the shading into my texture. You propably want something darker.
  var ambient = new THREE.AmbientLight( 0xffffff );
  scene.add( ambient );

  // Uncomment these lines to create a simple directional light.
  // var directionalLight = new THREE.DirectionalLight( 0xffeedd );
  // directionalLight.position.set( 0, 0, 1 ).normalize();
  // scene.add( directionalLight );

  /*** Texture Loading ***/
  var manager = new THREE.LoadingManager();
  manager.onProgress = function ( item, loaded, total ) {
    console.log( item, loaded, total );
  };
  var texture = new THREE.Texture();
  var loader = new THREE.ImageLoader( manager );

  // You can set the texture properties in this function.
  // The string has to be the path to your texture file.
  loader.load( 'female_croupier_2013-03-26.png', function ( image ) {
    texture.image = image;
    texture.needsUpdate = true;
    // I wanted a nearest neighbour filtering for my low-poly character,
    // so that every pixel is crips and sharp. You can delete this lines
    // if have a larger texture and want a smooth linear filter.
    texture.magFilter = THREE.NearestFilter;
    texture.minFilter = THREE.NearestMipMapLinearFilter;
  } );

  /*** OBJ Loading ***/
  var loader = new THREE.OBJLoader( manager );

  // As soon as the OBJ has been loaded this function looks for a mesh
  // inside the data and applies the texture to it.
  loader.load( 'female_croupier_2013-03-26.obj', function ( event ) {
    var object = event;
    object.traverse( function ( child ) {
      if ( child instanceof THREE.Mesh ) {
        child.material.map = texture;
      }
    } );

    // My initial model was too small, so I scaled it upwards.
    object.scale = new THREE.Vector3( 25, 25, 25 );

    // You can change the position of the object, so that it is not
    // centered in the view and leaves some space for overlay text.
    object.position.y -= 2.5;
    scene.add( object );
  });

  // We set the renderer to the size of the window and
  // append a canvas to our HTML page.
  renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );
[color=rgb(248, 248, 242) !important]}

[color=rgb(117, 113, 94) !important]/*** The Loop ***/
function animate() {
  // This function calls itself on every frame. You can for example change
  // the objects rotation on every call to create a turntable animation.
  requestAnimationFrame( animate );

  // On every frame we need to calculate the new camera position
  // and have it look exactly at the center of our scene.
  controls.update();
  camera.lookAt(scene.position);
  renderer.render(scene, camera);
[color=rgb(248, 248, 242) !important]}



Et voilà! Your in-browser model viewer is done and you can show off your great models to your friends. I recommend the Getting Started with Three.js article and thethree.js documentation if you want to dive deeper into WebGL.
Kind regards,
Manuel