quinta-feira, 8 de janeiro de 2015

Exportando do Blender para o Web GL usando Collada e three.js (Parte 3)


Essa é a terceira parte do tutorial onde eu ensino como criar no visualizador básico Web GL. Nós vamos usar o Blender para criar os modelos em 3D. E a codificação Web GL em si será feita com o three.js.

Na primeira parte falamos sobre o os programas necessários e os scripts. Na segunda parte foi tudo o que precisavamos para carregar o modelo via Collada e as configurações para o cenário. Caso necessite rever as postagens anteriores desse tutorial, segue os links abaixo.

Criando a SkyDome

Podemos criar um fundo de cor única com a seguinte linha de código.

renderer.setClearColorHex(0x262626, 1)
Se você quiser mudar a cor pesquise por uma HTML online. O Colorizer.org e o Color Hexa são sites que vão ajudar você a converter cores do RGB para cores Hexadecimais. O trio hexa dessa cor deve ser 262626 por isso certifique-se que você mantenha os dois primeiros dígitos. Porém um fundo de cor única é muito chato não?! Por isso decidi criar uma gradiente usando os recursos do three.js vamos precisar de um fragment shader, um vertex shader e um pouco mais de código. Observe a maior parte do código para gradiente usado foi retirado de exemplos do three.js. Visite o threejs.org se desejar mais informações a respeito.

Vamos começar com o Vertez Shader...

Cole o código do Fragment Shader logo após o Vertex Shader.

<script type="x-shader/x-vertex" id="vertexShader">

   varying vec3 vWorldPosition;

   void main() {

    vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
    vWorldPosition = worldPosition.xyz;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

   }

  </script>
A SkyDome devemos criar excluindo todos os calculos de sombreamento exceto as relativas localizações (vertex shader) e de cores simples (fragment shader), sem fontes de luz e outros recursos.

Criando a SkyDome em si

Uma boa inclinação preta para acizentada deve aparecer agora. Se quiser alterar as cores, cole o código hexadecimal no lugar dos atuais em topColor e bottomColor. Cores mais contrastantes deixa o degradê mais exposto.

Script completo

Aqui está o script completo para acompanharmos.

 <!doctype html>
<html lang="en">
<head>
  <title>Test von Web GL</title>
  <meta charset="utf-8">
</head>
<body style="margin: 0;">

  <script src="js/three.min.js"></script>
  <script src="js/OrbitControls.js"></script>
<script src="js/ColladaLoader.js"></script>


 <script type="x-shader/x-vertex" id="vertexShader">

   varying vec3 vWorldPosition;

   void main() {

    vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
    vWorldPosition = worldPosition.xyz;

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

   }

  </script>

  <script type="x-shader/x-fragment" id="fragmentShader">

   uniform vec3 topColor;
   uniform vec3 bottomColor;
   uniform float offset;
   uniform float exponent;

   varying vec3 vWorldPosition;

   void main() {

    float h = normalize( vWorldPosition + offset ).y;
    gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( h, exponent ), 0.0 ) ), 1.0 );

   }

  </script>
  <script>

   
    var scene, camera, renderer;

    init();
    animate();

  
    function init() {

     
      scene = new THREE.Scene();
      var WIDTH = window.innerWidth,
          HEIGHT = window.innerHeight;

    
      renderer = new THREE.WebGLRenderer({antialias:true});
      renderer.setSize(WIDTH, HEIGHT);
      document.body.appendChild(renderer.domElement);


      camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 10000);
      camera.position.set(50,150,100);
      scene.add(camera);

      window.addEventListener('resize', function() {
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;
        renderer.setSize(WIDTH, HEIGHT);
        camera.aspect = WIDTH / HEIGHT;
        camera.updateProjectionMatrix();
      });

  

    var vertexShader = document.getElementById( 'vertexShader' ).textContent;
    var fragmentShader = document.getElementById( 'fragmentShader' ).textContent;
    var uniforms = {
     topColor:   { type: "c", value: new THREE.Color(0x000000) },
     bottomColor: { type: "c", value: new THREE.Color( 0x262626 ) },
     offset:   { type: "f", value: 100 },
     exponent:  { type: "f", value: 0.7 }
    }
   

    

    var skyGeo = new THREE.SphereGeometry( 2000, 32, 15 );
    var skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );

    var sky = new THREE.Mesh( skyGeo, skyMat );
    scene.add( sky );


    
      var light = new THREE.PointLight(0xfffff3, 0.8);
      light.position.set(-100,200,100);
      scene.add(light);

var sphereSize = 1; 
var pointLightHelper = new THREE.PointLightHelper( light, sphereSize ); 
scene.add( pointLightHelper );


      var light2 = new THREE.PointLight(0xd7f0ff, 0.2);
      light2.position.set(200,200,100);
      scene.add(light2);

var sphereSize = 1; 
var pointLightHelper2 = new THREE.PointLightHelper( light2, sphereSize ); 
scene.add( pointLightHelper2 );


var light3 = new THREE.PointLight(0xFFFFFF, 0.5);
      light3.position.set(150,200,-100);
      scene.add(light3);

var sphereSize = 1; 
var pointLightHelper3 = new THREE.PointLightHelper( light3, sphereSize ); 
scene.add( pointLightHelper3 );

  var loader = new THREE.ColladaLoader();

 
  loader.options.convertUpAxis = true;

 
  loader.load( 'models/dummy1.dae', function ( collada ) {
 //dummy1.dae
   
    var dae = collada.scene;
 
 
    var skin = collada.skins[ 0 ];
 
  
dae.position.set(0,0,0);//x,z,y- if you think in blender dimensions ;)
dae.scale.set(1.5,1.5,1.5);

scene.add(dae);






var axes = new THREE.AxisHelper(50);
 axes.position = dae.position;
 scene.add(axes);
 
 var gridXZ = new THREE.GridHelper(100, 10);
 gridXZ.setColors( new THREE.Color(0x8f8f8f), new THREE.Color(0x8f8f8f) );
 gridXZ.position.set(0,0,0 );
 scene.add(gridXZ);
 
 
      });

      
      controls = new THREE.OrbitControls(camera, renderer.domElement);

    }


  
    function animate() {

      
      requestAnimationFrame(animate);
      
 
      renderer.render(scene, camera);
      controls.update();

    }

  </script>
 
</body>
</html>

Limitando o zoom

Por padrão o zoom é infinito. O problema é que depois de uma certa distância vamos perder o nosso modelo de vista.

Para resolver essa questão, acesse o script OrbitControls.js e localize o código abaixo. Os desenvolvedores do three.js oferecem um script bem documentado, isso facilita bastante para mudar os valores no código. Você pode alterar o zoom e a rotação. No meu caso bastou alterar o this.minDistance e o this.maxDistance.

Com algumas tentativas e erros consegui o resultado certo.

// This option actually enables dollying in and out; left as "zoom" for
// backwards compatibility
this.noZoom = false;
this.zoomSpeed = 1.0;
// Limits to how far you can dolly in and out
this.minDistance = 0;
this.maxDistance = Infinity;
Eu deixei algo assim:

 
// This option actually enables dollying in and out; left as "zoom" for
// backwards compatibility
this.noZoom = false;
this.zoomSpeed = 1.0;
// Limits to how far you can dolly in and out
this.minDistance = 20;
this.maxDistance = 300;


Publicando os arquivos no servidor

Então tudo que fizemos até aqui é um desenvolvimento offline. O próximo passo será publicar os seus arquivos no servidor web. Eu estou usando o fillezilla para publicar meus arquivos.

Existem servidores internacionais bastante baratos no mercado. Já vi servidores que custam $ 2,99 por mês mas devemos ficar atentos pois os serviços de hospedagens baratos não suportam muitos recursos e tecnologias e se precisar que um script funcione eles cobram a parte. E também não tem um suporte adequado.

O servidor que estou usando é Locaweb, como sou fornecedora do serviço pago um valor relativamente alto para oferecer aos meus clientes o serviço de hospedagem.

Levando em consideração que tenho um número de clientes que mantém meu servidor auto sustentável posso cobrar um valor muito baixo e oferecer todos recursos, segurança e suporte. Caso interessar é só entrar em contato. :)



Você pode publicar seus arquivos abrindo o Filezilla e conectando no seu web server. Tudo que você são os dados ftp, usuário e senha, em alguns caso a porta. Todas essas informações são fornecidas pelo seu provedor de hospedagem.


Eu criei uma subpasta chamada "_3D" e copiei todo o conteúdo da minha pasta de desenvolvimento incluindo a pasta models e js e colei na dentro da minha pasta "_3D". Se todo esse procedimento for feito corretamente e seu provedor de hospedagem oferecer suporte para a renderização 3D vai funcionar perfeitamente.

Clique aqui para ver o resultado final. 

Boa parte do conteúdo desse tutorial foi traduzida do site Quaint.

Qualquer dúvida estou a disposição. Deixem um comentário e irei responder o mais breve possível.

Abraço!!

Jey


Nenhum comentário:

Postar um comentário