<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jaimebboyjt</title>
    <description>The latest articles on DEV Community by Jaimebboyjt (@jaimebboyjt).</description>
    <link>https://dev.to/jaimebboyjt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F415321%2Fa40f08ff-9b0e-4cfa-af2b-cf7223545302.jpg</url>
      <title>DEV Community: Jaimebboyjt</title>
      <link>https://dev.to/jaimebboyjt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jaimebboyjt"/>
    <language>en</language>
    <item>
      <title>¿Como es ser un mantenedor Open Source?</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Wed, 27 Mar 2024 17:55:48 +0000</pubDate>
      <link>https://dev.to/jaimebboyjt/como-es-ser-un-mantenedor-open-source-4624</link>
      <guid>https://dev.to/jaimebboyjt/como-es-ser-un-mantenedor-open-source-4624</guid>
      <description>&lt;p&gt;Si estás leyendo esto, probablemente, tengas curiosidad de convertirte en uno, hacer contribuciones al open source o solo leer de que se trata esto, espero ayudarte un poco con este post.😊&lt;/p&gt;

&lt;h2&gt;
  
  
  Un repaso breve de como me convertí en mantenedor Open Source🧐
&lt;/h2&gt;

&lt;p&gt;Primero que nada soy mantenedor de una librería de Vue para realizar experiencias 3D, Y es aquí donde dos cosas muy importantes se unen las pasiones.&lt;/p&gt;

&lt;p&gt;Me encanta programar y diseñar, descubrí el 3D con JS usando ThreeJs por allá por el 2021. En ese entonces (y como mucho) existía una librería muy buena para realizar estas experiencias sin usar vanilla JS llamada React-Three/Fiber. Pero la verdad nunca me sentí cómodo usando react 🚫.&lt;/p&gt;

&lt;p&gt;No había nada para Vue, (había una solución, pero no era muy buena). Además, me había llamado la atención realizar contribuciones al Open Source, pero simplemente no había encontrado ningún paquete, o simplemente tenía desconfianza de hacer PRs a grandes repos.&lt;/p&gt;

&lt;p&gt;En noviembre del 2023. Aparece Alvaro Saburido y crea TresJs. Lo vi por twitter, me llamo la atención, le escribí y me uní al proyecto, poco a poco empecé a empaparme del código y hacer contribuciones cada vez mayores.&lt;/p&gt;

&lt;p&gt;Entonces (para ese momento los repos estaban en privado, tú no sabes si una librería va a gustar o no) Realizamos él anunció oficial y para sorpresa, la librería gusto mucho, siendo reconocida por grandes personajes del ecosistema de Vue como Evan You, Eduardo, Patak, etc.&lt;/p&gt;

&lt;p&gt;Ya para aproximadamente febrero de 2024 Alvaro consulta por posibles mantenedores, acepte el desafío y acá estamos una librería con más de 1K en github con menos de un año de desarrollo :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo mejor de ser mantenedor👌
&lt;/h2&gt;

&lt;p&gt;Entre lo mejor yo destacaría&lt;/p&gt;

&lt;h3&gt;
  
  
  Aprendizaje 🎓
&lt;/h3&gt;

&lt;p&gt;No solo tiene la oportunidad de desarrollar código a nivel mundial, sino de crecer muchísimo profesionalmente, diariamente me encuentro trabajando con personas de un muy alto nivel. &lt;/p&gt;

&lt;p&gt;Entendiendo como funciona una librería de manera interna, te abre muchas puertas, no solo entras a entender el porqué una librería se comporta de cierta manera, sino que aumenta tu confianza como desarrollador.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comunidad 🤝
&lt;/h3&gt;

&lt;p&gt;La comunidad es definitivamente una de las mejores cosas, hablas con muchas personas, 95% de ellas dispuestas a ayudar, responderte, o guiarte.&lt;/p&gt;

&lt;p&gt;Te permite ayudar/guiar a otros miembros de la comunidad, ya sabes lo que dicen: si quieres mejorar, explícalo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trabajo... trabajo... 👩‍💻
&lt;/h3&gt;

&lt;p&gt;Bueno, esto puede que no suene tan genial, pero es trabajo en tu tiempo libre, lo que implica que si no te sientes bien, tienes un evento importante, simplemente avisas y listo. Nadie va a "no pagarte" por alejarte del proyecto un tiempo.&lt;/p&gt;

&lt;p&gt;Te proporciona un curriculum mejor posicionado que la mayoría. Para cualquier software engineer, incluso si no sabe nada de tu proyecto, puede entender y apreciar el trabajo Open Source.&lt;/p&gt;

&lt;p&gt;Puedes ganar algo extra por donaciones, sinceramente esto no se hace por dinero, si ese es tu goal, te recomiendo emprender o buscar un mejor trabajo. Pero que alguien te dedique una cuota es un gran agradecimiento por las contribuciones realizadas&lt;/p&gt;

&lt;h2&gt;
  
  
  Lo que no es tan bueno 🤨
&lt;/h2&gt;

&lt;p&gt;De partida, ya tu foco principal cambia, y contribuyes al proyecto de forma diferente al bienestar del proyecto (organización de código, limpieza, discusiones, resolución de bugs, mejoras, DX, etc).&lt;/p&gt;

&lt;p&gt;Si quieres que tu proyecto de OSS crezca y sea usado, conseguir contribuidores requiere bastante trabajo de marketing, planificación (incluye charlas, posts, RRSS, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviews 🔍
&lt;/h3&gt;

&lt;p&gt;Gran parte es realizar reviews a los contribuidores, y muy personalmente no me gusta mucho hacer reviews de otros códigos porque siento que es casi como "criticar" (ojo es un tema totalmente personal, sé que no es una crítica destructiva ni nada, pero hay un sentimiento que no termina de gustarme)&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsabilidades, ¿Realmente que se hace? 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Entre las tareas está. Ayudar a la comunidad, por cualquier medio, Discord, Twitter, GitHub, foros, etc.&lt;/li&gt;
&lt;li&gt;Resolver y encontrar bugs&lt;/li&gt;
&lt;li&gt;Reviews de los contribuidores&lt;/li&gt;
&lt;li&gt;Guiar e incentivar a los contribuidores&lt;/li&gt;
&lt;li&gt;Buscar formas de mejorar la DX(developer experience). &lt;/li&gt;
&lt;li&gt;Hacer anuncios de las nuevas versiones (marketing).&lt;/li&gt;
&lt;li&gt;Definir junto al resto del equipo (si es un proyecto un poco más grande) el roadmap.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Algunos tips personales sobre como contribuir al Open Source 📝
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Buscar un proyecto que te guste y que uses a menudo, que esté en constante mantenimiento, y que esté buscando contribuidores&lt;/li&gt;
&lt;li&gt;Buscar en la lista de issues, aquellos con "first good issue" o labels similares. Recuerda que puedes contribuir con traducciones, arreglando gramática, etc. No solo con código.&lt;/li&gt;
&lt;li&gt;Revisa la documentación del proyecto, como realizar commits, o levantar el proyecto.&lt;/li&gt;
&lt;li&gt;Pide ayuda, la gran mayoría de proyectos va a ayudarte y guiarte porque quieren que contribuyas al proyecto.&lt;/li&gt;
&lt;li&gt;Recuerda que tu commit no debe ser perfecto, no te estreses y no olvides que las contribuciones son en tu tiempo libre, por amor, y para aprender.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Ser contribuidor es algo maravilloso y lo recomendaría a cualquiera. Me ha traído muchas alegrías y mucho crecimiento personal, además he hecho amigos y ayudado a mucha gente.&lt;/p&gt;

&lt;p&gt;Nuestro proyecto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tresjs.org/"&gt;https://tresjs.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>TresJs por una web con más 3D</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Wed, 28 Feb 2024 17:57:58 +0000</pubDate>
      <link>https://dev.to/javascriptchile/tresjs-por-una-web-con-mas-3d-39d4</link>
      <guid>https://dev.to/javascriptchile/tresjs-por-una-web-con-mas-3d-39d4</guid>
      <description>&lt;p&gt;Hace algunas semanas publiqué algunos artículos sobre como empezar a desarrollar páginas web en 3D usando &lt;a href="https://threejs.org/"&gt;ThreeJs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Puedes leer el primer capítulo de la serie &lt;a href="https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-1-2k95"&gt;acá&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;También mencioné las distintas capas de abstracción al rededor de WebGL (próximamente WebGPU).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rrh6rtqjde1wxpa0ag9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rrh6rtqjde1wxpa0ag9.png" alt="Image description" width="390" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Normalmente, no recomendaría ir de lleno a la última capa sin antes conocer un poco de lo básico &lt;a href="https://threejs.org/"&gt;ThreeJs&lt;/a&gt;. Pero también entiendo que gestionar todo de manera manual para empezar con un cubo girando consume bastante tiempo.&lt;/p&gt;

&lt;p&gt;Es por eso que existe una capa a nivel de frameworks que facilita MUCHÍSIMO el trabajo, abstrae mucho de los conceptos, elimina boilerplate y te permite usar todas las ventajas de tus frameworks favoritos. Últimamente, he notado que muchos de los nuevos usuarios no tienen experiencia previa con &lt;strong&gt;Threejs&lt;/strong&gt; lo cual no es lo mejor, pero igual funciona (imagina aprender react sin saber javascript).&lt;/p&gt;

&lt;p&gt;También mencioné que soy mantenedor de una de ellas &lt;a href="https://tresjs.org/"&gt;TresJs&lt;/a&gt; que es básicamente la alternativa por default para crear experiencias 3D con VueJs. Con poco más de un año, Tresjs Core ya cuenta con más de 1k de estrellas en GitHub y poco más de 2k en todo su ecosistema.&lt;/p&gt;

&lt;p&gt;# TresJs vs ThreeJs 🥊&lt;/p&gt;

&lt;p&gt;Veamos una comparación de códigos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisdeo3xtr8zmut9wy1ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fisdeo3xtr8zmut9wy1ys.png" alt="Code comparison" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como ven, TresJs es indudablemente mucho más fácil y rápido de escribir, eso es porque nos concentramos mucho en la DX (developer experience).&lt;/p&gt;

&lt;p&gt;Podemos notar que para nuestra "hello world" (nuestro cubo verde girando) solo tenemos que instancia algunos componentes y listo.&lt;/p&gt;

&lt;p&gt;Además, y muy importante &lt;strong&gt;TODO&lt;/strong&gt; lo que puedes hacer con ThreeJs lo puedes hacer con TresJs&lt;/p&gt;

&lt;h2&gt;
  
  
  Gran documentación 📝
&lt;/h2&gt;

&lt;p&gt;La verdad no los molestaré con el paso a paso en este post, porque básicamente sería repetir lo que la documentación oficial ya explica. &lt;a href="https://docs.tresjs.org/guide/your-first-scene.html#adding-a-%F0%9F%8D%A9"&gt;Tu primera escena&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTA&lt;/em&gt;: La documentación también cuenta con la traducción al español y mucho más están en proceso.&lt;/p&gt;

&lt;p&gt;Contamos también con una sección de cookbook (libro de recetas) en donde enseñamos como realizar algunas de las operaciones básicas, como agregar sombra, usar shaders, aplicar texturas, etc. Una sección de &lt;a href="https://lab.tresjs.org/"&gt;Showcase&lt;/a&gt; donde encontrarás ejemplos un poco más elaborados. Y por último un &lt;a href="https://play.tresjs.org/"&gt;playground&lt;/a&gt;, para probar TresJs sin instalar nada en tu PC &lt;/p&gt;

&lt;p&gt;Somos 100% open source, por lo que todo es transparente, puedes entrar a nuestro GitHub, revisar y tomar el código que desees, así como ver, trabajar y proponer nuevas features.&lt;/p&gt;

&lt;p&gt;Por último, contamos con servidor en &lt;a href="https://discord.gg/rSyxCSqAc2"&gt;discord&lt;/a&gt; dedicado para resolver dudas, estar atento a las últimas actualizaciones y compartir con la comunidad 🤝&lt;/p&gt;

&lt;h2&gt;
  
  
  Ecosistema 🌱
&lt;/h2&gt;

&lt;p&gt;Incluso con toda la gran capa de abstracción que nos provee TresJs. Aún podemos extender y rehusar más código. Es por eso que TresJs no es un solo paquete, es un ECOSISTEMA completo, por eso tenemos otras librerías que funcionan para extender funcionalidades específicas a &lt;a href="https://tresjs.org/"&gt;TresJs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cientos.tresjs.org/"&gt;Cientos&lt;/a&gt;: Conjunto de abstracciones superútiles para &lt;strong&gt;TresJs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Tresjs/nuxt"&gt;Nuxt&lt;/a&gt;: Módulo para Nuxt, provee ventajas como autoimport y CSR de manera automatica.  &lt;/p&gt;

&lt;p&gt;DevTool:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Tresjs/post-processing"&gt;Post-processing&lt;/a&gt;: Para agregar post-processing o efectos de post procesado a tus experiencias de manera fácil y sencilla (bajo desarrollo).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tresleches.tresjs.org/"&gt;Leches&lt;/a&gt;: Módulo para realizar tweaks, ajustes y monitorear tu experiencia 3D creado con sintonía para Tresjs.&lt;/p&gt;

&lt;p&gt;Proximamente (Rappier (para agregar fisicas) y ar/xr)&lt;/p&gt;

&lt;h3&gt;
  
  
  Más alternativas 🤔
&lt;/h3&gt;

&lt;p&gt;Por último, mencionar que TresJs es la alternativa que está disponible para VueJs. Pero también existen para otros frameworks de front-end. Por ejemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.pmnd.rs/react-three-fiber/getting-started/introduction"&gt;React-Three&lt;/a&gt;: Alternativa para React, cuenta con el mayor ecosistema de todas&lt;br&gt;
&lt;a href="https://threlte.xyz/"&gt;ThreeVelte&lt;/a&gt;: Alternativa para svelte con muy buena aceptación por parte del público.&lt;br&gt;
&lt;a href="https://angular-threejs.netlify.app/docs/getting-started/introduction/"&gt;AngularThree&lt;/a&gt;: Alternativa para Angular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algunos links que podrían interesarte 🔍
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Inspiración 🌈
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ohzi.io/"&gt;https://ohzi.io/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://backstage.bonjovi.com/"&gt;https://backstage.bonjovi.com/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://lr.doesbook.kr/en/"&gt;https://lr.doesbook.kr/en/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.brettwilliams.net/WebXR"&gt;https://www.brettwilliams.net/WebXR&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursos 📦
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@AlvaroDevLabs"&gt;https://www.youtube.com/@AlvaroDevLabs&lt;/a&gt; &lt;br&gt;
&lt;a href="https://www.youtube.com/@BrunoSimon"&gt;https://www.youtube.com/@BrunoSimon&lt;/a&gt; &lt;br&gt;
&lt;a href="https://www.youtube.com/@WaelYasmina"&gt;https://www.youtube.com/@WaelYasmina&lt;/a&gt; &lt;br&gt;
&lt;a href="https://www.youtube.com/@WawaSensei"&gt;https://www.youtube.com/@WawaSensei&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Saludos y Happy 3D coding 💚&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>3d</category>
      <category>vue</category>
    </item>
    <item>
      <title>Programación 3D con JavaScript - parte 3</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Mon, 25 Dec 2023 18:55:02 +0000</pubDate>
      <link>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-3-56cj</link>
      <guid>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-3-56cj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-2-1jj8"&gt;Segunda parte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Mesh 🔮
&lt;/h1&gt;

&lt;p&gt;Bien, continuaremos donde nos quedamos, en nuestra pantalla negra y añadiremos un Mesh (una malla), Los mesh u objetos 3D se componen de una geometría y un material&lt;/p&gt;

&lt;h3&gt;
  
  
  Geometría 🌐
&lt;/h3&gt;

&lt;p&gt;En pocas palabras es la forma que tomara nuestro objeto, esto lo hace colocando de manera precisa puntos en nuestro espacio 3D (vértices) y rellenando el espacio con una "cara" o face. Para crear nuestro cubo, lo hacemos de la siguiente forma.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const geometry = new THREE.BoxGeometry();&lt;/code&gt;&lt;br&gt;
&lt;em&gt;Las dimensiones por defectos serán de 1,1,1 (uno de ancho, uno de alto y uno de profundidad)&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Materiales 🧱
&lt;/h3&gt;

&lt;p&gt;Puedes pensar en ellos tal cual el mundo real, como una "piel". Algunos pueden ser translúcidos, metálicos, simples colores, sombras, etc. El material lo creamos así&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Una vez nuestra geometría y material creados, creemos nuestro mesh y añadámoslo a nuestra escena.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
console.log("cube", cube);
scene.add(cube);
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos ver en nuestra consola que hemos creado exitosamente nuestro cubo, pero, ¿por qué no se ve?&lt;/p&gt;

&lt;h2&gt;
  
  
  Vectores 📐
&lt;/h2&gt;

&lt;p&gt;Simple lo que sucede es que nuestra cámara, y nuestro mesh están en la posición inicial, el punto 0,0,0. En threeJs la posición inicial es el centro de nuestra escena.&lt;/p&gt;

&lt;p&gt;Podemos mover nuestra cámara para atrás, o nuestro cubo da igual. Movamos la cámara. Justo después de iniciar nuestra cámara añadamos esta línea.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;camera.position.z = 5;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gBh8mjTt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdul8v63ob2vd3vt2535.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gBh8mjTt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rdul8v63ob2vd3vt2535.png" alt="Image description" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pero... ¿Qué significa ese 5? ¿Metros? ¿Centímetros? ¿y porque vemos un cuadrado en lugar de un cubo?&lt;/p&gt;

&lt;p&gt;Al igual que como sucede con los SVG, threeJs manea Unidades y depende de nosotros tratarlas como tal, por lo que estamos diciendo es que mueva la cámara 5 "unidades" de manera positiva en el eje Z. &lt;/p&gt;

&lt;p&gt;Todos los objetos heredados de la clase isObject3D contienen propiedades como position, rotation, scale. Estas propiedades esperan un Vector3, que puedes pensar en ellos como en un array con 3 valores. El orden inicial de los ejes X, Y, Z. y funcionan muy usando el plano cartesiano&lt;/p&gt;

&lt;p&gt;Podríamos mover nuestro Mesh de la siguiente forma. (solo ejemplo)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cube.position.x = -1 // podemos usar el eje x en negativo
cube.position.y = 3+3 // podemos realizar operaciones matematicas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ThreeJs también nos provee del metodo set() que espera un vector3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cube.position.set(-1, 3+3, 0)
// o tambien
const myCubePosition = new THREE.Vector3(-1, 3+3, 0)
cube.position.set(...myCubePosition)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;También existen Vector2 y Vector4 (si no es broma hay 4 dimensiones, pero no te preocupes, no las veremos en este post y no es tan difícil de entender)&lt;/p&gt;

&lt;p&gt;Con respecto a la última pregunta, en realidad es un cubo, solo que  lo estamos visualizando perfectamente alineado, si deseas puedes probar subiendo la cámara una unidad en el eje Y&lt;/p&gt;

&lt;h2&gt;
  
  
  Request animation frame 💥
&lt;/h2&gt;

&lt;p&gt;El último detalle que vamos a ver, es la animación.&lt;/p&gt;

&lt;p&gt;Y para esto hacemos uso de otra API que los navegadores nos proveen, el &lt;a href="https://developer.mozilla.org/es/docs/Web/API/Window/requestAnimationFrame"&gt;Request animation API&lt;/a&gt;. En palabras muy cortas, es una API que se creó específicamente para crear animaciones, se ejecuta cada frame por segundo (FPS) y viene con un montón de beneficios para el rendimiento.&lt;/p&gt;

&lt;p&gt;Básicamente, vamos a renderizar nuestra escena cada FPS y aplicar un leve cambio (girar el cubo) y esto lo hacemos mediante una función recursiva.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function loop() {
  cube.rotation.x += 0.1;
  cube.rotation.y += 0.1;

  requestAnimationFrame(animated);
  renderer.render(scene, camera);
}
loop();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Dato curioso: no hay un estándar para el nombre de esta función, algunos la llaman RAF, otros animated, otros loop e incluso tick&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TwmEvitK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8go0nxypw05jmihs2r8z.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TwmEvitK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8go0nxypw05jmihs2r8z.gif" alt="Image description" width="640" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y así hemos terminado de diseccionar por completo todos los componentes que contienen las escenas 3D con threeJS (y casi cualquier otro motor de gráficos 3D 😮 )&lt;/p&gt;

&lt;p&gt;Puedes ver el ejemplo &lt;a href="https://codepen.io/jaime_torrealba/full/mdQZvjz"&gt;aquí&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Dónde continuar ahora?
&lt;/h3&gt;

&lt;p&gt;Sé lo que estás pensando... tan largo el post, ¿solo para crear un cubo verde girando? Pasos pequeños llegan a grandes resultados, afortunadamente hay muchos recursos online sobre este tema, hay mucha gente creado cursos y videos. &lt;/p&gt;

&lt;p&gt;Todas las increíbles páginas que viste al principio fueron creadas usando como base estos métodos. ThreeJS es tan grande que contiene muchas funciones que aún no están documentadas 🤯. Y constantemente se crean más.&lt;/p&gt;

&lt;p&gt;Este es un área del código altamente creativa y reconfortante, y por experiencia propia puedo decir que la comunidad es muy amigable y dispuesta a ayudar. &lt;/p&gt;

&lt;p&gt;Así que si alguna vez te llamo la atención, crear juegos u objetos 3D o si eres una persona creativa que está buscando un nuevo desafío, esto puede ser para ti.&lt;/p&gt;

&lt;h3&gt;
  
  
  Algunos links de interés:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://threejs.org/"&gt;https://threejs.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://threejs-journey.com/"&gt;https://threejs-journey.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@AlvaroDevLabs"&gt;https://www.youtube.com/@AlvaroDevLabs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lessons.wawasensei.dev/courses/react-three-fiber/lessons/intro"&gt;https://lessons.wawasensei.dev/courses/react-three-fiber/lessons/intro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También dejaré mi twitter (X) por acá, por si tienes alguna consulta estaré más que feliz de ayudar&lt;/p&gt;

&lt;p&gt;Hasta luego y happy 3D Coding 🤓&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Programación 3D con JavaScript - parte 2</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Fri, 15 Dec 2023 14:17:04 +0000</pubDate>
      <link>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-2-1jj8</link>
      <guid>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-2-1jj8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-1-2k95"&gt;Primera parte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configurando nuestro entorno 🤓
&lt;/h2&gt;

&lt;p&gt;Bien, lo primero que vamos a hacer es configurar nuestro entorno de trabajo, no importa que editor uses, necesitaremos un archivo HTML como punto de entrada. Luego darle un &lt;code&gt;margin:0&lt;/code&gt; de estilo al &lt;code&gt;body&lt;/code&gt;. Por último importaremos un script que contendrá nuestro archivo JS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;meta charset="utf-8"&amp;gt;
        &amp;lt;title&amp;gt;My first three.js app&amp;lt;/title&amp;gt;
        &amp;lt;style&amp;gt;
            body { margin: 0; }
        &amp;lt;/style&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;script type="module" src="/main.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sip, eso es todo el HTML y CSS que necesitaremos 😮.&lt;/p&gt;

&lt;p&gt;Bien, ahora depende de donde y como estés trabajando, puedes instalar ThreeJS o por CDN o por npm packages.  &lt;a href="https://threejs.org/docs/index.html#manual/en/introduction/Installation" rel="noopener noreferrer"&gt;Guía de instalacion&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Elementos indispensables de toda escena 3D
&lt;/h2&gt;

&lt;p&gt;Son 5 y veremos uno por uno, la idea es entender bien la función de cada uno, en lugar de solo copiar y pegar (si copias el código de &lt;a href="https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene" rel="noopener noreferrer"&gt;Creating-a-scene&lt;/a&gt; de threejs ya tienes el famoso verde cubo girando, pero así ni una gracia).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scene&lt;/strong&gt; 🖼️: Contenedor de nuestras instancias&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Camera&lt;/strong&gt; 🎥: Actuará como nuestros ojos en la escena&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Renderer&lt;/strong&gt; 🔩: Motor de renderizado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mesh&lt;/strong&gt; 🔮: Objecto 3D, algo que mostrar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request animation frame API&lt;/strong&gt; 💥: Para animar nuestras escenas &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scene 🖼️
&lt;/h3&gt;

&lt;p&gt;El elemento &lt;code&gt;Scene&lt;/code&gt;, va a servir como nuestro contenedor, en él van a vivir todos nuestros elementos, sean luces, cámaras, modelos 3D, etc.&lt;/p&gt;

&lt;p&gt;Para crearlo solo debemos importarlo de ThreeJs e instanciarlo de la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import * as THREE from 'three';

const scene = new THREE.Scene();
console.log('scene', scene)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; acá estamos importando todo como THREE, para mayor flexibilidad. Esto no tiene muy buen rendimiento pero es cómodo. Si quisiéramos pudiéramos importar &lt;code&gt;Scene&lt;/code&gt; como:&lt;br&gt;
 &lt;code&gt;import { Scene } from 'three'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si prestamos atención a nuestro log veremos algo como:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbw61fs9r1bwdfmvntl15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbw61fs9r1bwdfmvntl15.png" alt="Log example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algo muy útil acerca de ThreeJs es que la gran mayoría de objetos heredan de la clase &lt;a href="https://threejs.org/docs/index.html?q=obje#api/en/core/Object3D" rel="noopener noreferrer"&gt;Object3D&lt;/a&gt;. Esto significa que muchas propiedades, serán compartidas en otras instancias.&lt;/p&gt;

&lt;p&gt;Por ejemplo, una buena práctica es asignarles nombres a nuestro objeto y luego es fácil recorrer toda la escena en busca de él.&lt;/p&gt;

&lt;p&gt;Algo particular para prestar atención es nuestra propiedad &lt;code&gt;children&lt;/code&gt; 👶, allí veremos todos los objetos 3D que forman parte de nuestra escena.&lt;/p&gt;
&lt;h3&gt;
  
  
  Camera 🎥
&lt;/h3&gt;

&lt;p&gt;Existen varios tipos de cámaras y para verlas todas en profundidad necesitaríamos un post completo 🙅‍♂️. Por ahora empezaremos usando la &lt;code&gt;PerspectiveCamera&lt;/code&gt; Es la más fácil de entender por qué simula el ojo humano (los objetos más alejados se ven más pequeños).&lt;/p&gt;

&lt;p&gt;Para la &lt;a href="https://threejs.org/docs/index.html?q=perspe#api/en/cameras/PerspectiveCamera" rel="noopener noreferrer"&gt;PerspectiveCamera&lt;/a&gt; necesitaremos proporcionar unos parámetros, la gran mayoría serán por ahora estándar, pero veamos que son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;fov&lt;/strong&gt;: field of view, campo de visión. Me parece que con una imagen se expresa mejor este parámetro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.securityinfowatch.com%2Ffiles%2Fbase%2Fcygnus%2Fsiw%2Fimage%2F2019%2F05%2F960w%2FOlsen_1_Camera_FOV.5ce321b430946.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.securityinfowatch.com%2Ffiles%2Fbase%2Fcygnus%2Fsiw%2Fimage%2F2019%2F05%2F960w%2FOlsen_1_Camera_FOV.5ce321b430946.jpg" alt="Field of view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;aspect-ratio&lt;/strong&gt;: en nuestro caso tomaremos el aspect-ratio de nuestro viewport, que no es más que dividir nuestro window.innerWidth / window.innerHeight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;near&lt;/strong&gt;: Que tan cerca de nosotros la cámara renderizará&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;far&lt;/strong&gt;: Que tan lejos nuestra la cámara renderizará&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// trabajar con un objecto sizes resulta muy comodo
const sizes = {
  width: window.innerWidth,
  height: window.innerHeight
};

const camera = new THREE.PerspectiveCamera(
  45,
  sizes.width / sizes.height,
  1,
  1000
);
console.log('camera', camera)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmchmqde2rlz3dauc5syf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmchmqde2rlz3dauc5syf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Algo&lt;/em&gt; importante a tener en cuenta es que "si la cámara no lo renderiza, no consume recursos"&lt;/p&gt;

&lt;p&gt;Ahora y como último detalle, recordemos añadir nuestra cámara a nuestra escena con la función scene.add():&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
scene.add(camera);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Renderer 🔩
&lt;/h3&gt;

&lt;p&gt;Nuestro renderer es el puente entre la WebGL API y ThreeJS, básicamente es el motor que da vida a nuestros increíbles gráficos.&lt;/p&gt;

&lt;p&gt;ThreeJs provee varios renderers, nosotros en esta ocasión usaremos el &lt;code&gt;WebGLRenderer&lt;/code&gt;, lo instanciamos de la siguiente forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const renderer = new THREE.WebGLRenderer();
renderer.setSize(sizes.width, sizes.height);
document.body.appendChild(renderer.domElement);
renderer.setClearColor("#111");
renderer.render(scene, camera);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entonces veamos paso a paso:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instanciamos nuestro &lt;code&gt;WebGLRenderer&lt;/code&gt; desde threeJs&lt;/li&gt;
&lt;li&gt;Indicamos el tamaño que tendrá nuestra escena&lt;/li&gt;
&lt;li&gt;Acá podemos proporcionarle un elemento HTMLcanvas personalizado o cuando no hemos creado uno manualmente(como es nuestro caso) ThreeJs creará uno automáticamente y vivirá dentro de &lt;code&gt;renderer.domElement&lt;/code&gt; Entonces lo que hacemos es colocarlo en nuestro body.&lt;/li&gt;
&lt;li&gt;Como detalle opcional (y muchas veces útil), colocaremos el fondo de la escena, un negro menos intenso&lt;/li&gt;
&lt;li&gt;Y el último paso es llamar a la función &lt;code&gt;render&lt;/code&gt; que recibe como parámetros la escena y la cámara anteriormente creados&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si todo ha salido de manera correcta, veremos que nuestra pantalla está negra, esto es una buena señal, significa que tenemos una escena con threeJs corriendo exitosamente :).&lt;/p&gt;

&lt;p&gt;Obviamente, no tiene nada que mostrar aún, pero cambiaremos esto y otros detalles en nuestro siguiente post &lt;/p&gt;

&lt;p&gt;Happy 3D coding 😊&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-3-56cj"&gt;Tercera parte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>3d</category>
      <category>threejs</category>
    </item>
    <item>
      <title>Programación 3D con JavaScript - parte 1</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Thu, 07 Dec 2023 17:42:37 +0000</pubDate>
      <link>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-1-2k95</link>
      <guid>https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-1-2k95</guid>
      <description>&lt;p&gt;¿Alguna vez te has preguntado como se crean sitios web como los que encuentras en &lt;a href="https://www.awwwards.com/" rel="noopener noreferrer"&gt;awwwards&lt;/a&gt; &lt;a href="https://www.cssdesignawards.com/" rel="noopener noreferrer"&gt;cssdesignawards&lt;/a&gt; u &lt;a href="https://orpetron.com/" rel="noopener noreferrer"&gt;orpetron&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;¿Estará esto hecho con JavaScript? &lt;a href="https://bruno-simon.com/" rel="noopener noreferrer"&gt;bruno-simon&lt;/a&gt;, &lt;a href="https://lr.doesbook.kr/en/" rel="noopener noreferrer"&gt;doesbook&lt;/a&gt; o &lt;a href="https://www.brettwilliams.net/WebXR" rel="noopener noreferrer"&gt;brettwilliams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;¿Sabías que podemos programar (enviar secuencias de instrucciones) directamente a nuestra GPU, con JavaScript?&lt;/p&gt;

&lt;p&gt;En esta serie de post vamos a entender los elementos que componen estas maravillosas escenas, como y de que están hechas, y terminaremos con el equivalente al "hello word" &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4sfko2o8fpdpf6hnnsp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4sfko2o8fpdpf6hnnsp.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo sé, lo sé un cubo verde girando, no se ve particularmente útil... Pero después de construir este cubo tan básico, te darás cuenta de que la programación 3D no es ingeniería nuclear de la nasa (no tengo idea siquiera si eso existe, pero no será tan difícil). &lt;a href="https://codepen.io/jaime_torrealba/details/mdQZvjz" rel="noopener noreferrer"&gt;Ver codigo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Un poco de historia 📃
&lt;/h2&gt;

&lt;p&gt;Antes de saltar al código primero entendamos un poco que es lo que hace todo esto posible.&lt;/p&gt;

&lt;p&gt;WebGL API aparece alrededor del 2007 como una solución a los múltiples plug-ins y la falta de estándares, para crear experiencias 2D y 3D en los navegadores de manera nativa usando OpenGL como base. &lt;/p&gt;

&lt;p&gt;OpenGL es una API usada en diferentes plataformas, mantenida por el grupo Khronos y compite con otras API como Direct3D de Microsoft (importante destacar que OpenGL no es la única opción disponible)&lt;/p&gt;

&lt;p&gt;WebGL se introduce en los navegadores con la capacidad de usar los Shaders. Los Shaders que son básicamente dos: Fragment-shaders y Vertex-Shaders (No vamos a entrar en este tópico ahora). Estos son escritos en un lenguaje llamado GLSL y básicamente nos permiten programar en nuestra GPU. GLSL no es JavaScript, se parece más a C; Es multiplataforma y lo podemos usar en nuestros navegadores.&lt;/p&gt;

&lt;p&gt;Ahora programar en WebGL directo, aunque posible, resulta increíblemente laborioso, ya que debemos especificar todo de manera muy manual, por ejemplo luces, sombras, coordenadas en el espacio...&lt;/p&gt;

&lt;h2&gt;
  
  
  ThreeJs
&lt;/h2&gt;

&lt;p&gt;Es aquí donde aparece &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;threejs&lt;/a&gt; para salvarnos, realizando abstracciones sumamente útiles, y se establece como librería estándar para la creación de experiencias 3D en el ecosistema de JS.&lt;/p&gt;

&lt;p&gt;ThreeJs aparece por el 2010, es open source y es un repositorio sumamente activo, en su página principal pueden ver muchos más ejemplos creativos, cuenta con una documentación muy buena en varios idiomas y muchísimos ejemplos, además también podemos crear experiencias de realidad virtual y realidad aumentada, con él. &lt;/p&gt;

&lt;p&gt;Existe mucho contenido y recursos alrededor, uno de los más famosos es el curso &lt;a href="https://threejs-journey.com/" rel="noopener noreferrer"&gt;Threejs-journey&lt;/a&gt; Recomendado para todos los que quieran adentrarse más en este mundo de los creative-developers🎨. El único detalle es que la mayor parte de todos los contenidos está en inglés.&lt;/p&gt;

&lt;p&gt;Yo mismo tengo un curso en español 🎓, lo puedes encontrar acá: &lt;a href="https://ed.team/cursos/threejs" rel="noopener noreferrer"&gt;Curso&lt;/a&gt;. Donde explico las bases. (post-data: no gano ningún dinero extra si compran el curso).&lt;/p&gt;

&lt;h3&gt;
  
  
  React-Three-fiber, TresJs, AngularThree, threlte
&lt;/h3&gt;

&lt;p&gt;Se ha popularizado una capa superior en torno a ThreeJS que facilita todavía más el desarrollo de estas experiencias, eliminando el código duplicado y trayendo todo el poder de tus frameworks favoritos. React-Three-Fiber fue la primera y declara los componentes de ThreeJs de forma declarativa y permite separa fácilmente las instancias por componentes. El resto de librerías sigue la misma filosofía&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9ktwlxkub29pyrr2ri3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9ktwlxkub29pyrr2ri3.png" alt="Layers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yo mismo soy mantenedor de &lt;a href="https://tresjs.org/" rel="noopener noreferrer"&gt;TresJs&lt;/a&gt; que es la opción por defecto para &lt;strong&gt;VueJs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ahora, aunque recomiendo mucho usar estas librerías, para experiencias más complejas, al final todas ellas usan ThreeJs como base, lo que significa que altamente es recomendable, conocer como funciona ThreeJs antes de entrar a trabajar con cualquiera de ellas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué viene para el futuro🔮?
&lt;/h3&gt;

&lt;p&gt;Como mencione anteriormente, WebGL ya tiene bastante tiempo rondando, y a pesar de todo viene con algunos problemas que son virtualmente imposibles de solucionar sin breaking changes. Por eso, en mayo del 2022 fue liberado al público un trabajo de años, la nueva &lt;strong&gt;WebGPU&lt;/strong&gt; API. Que promete mejores rendimientos, mejor manejo de la memoria, mejor manejo de errores, y un sin fin de beneficios. Por ahora, "dic/2023" solo está disponible para Chrome.&lt;/p&gt;

&lt;p&gt;La buena noticia: No tendremos que adaptar casi nada de nuestro código o aprender un lenguaje nuevo 🥳, ThreeJs ya está trabajando en una migración responsable, y aunque la definición de los shaders cambia un poco, ThreeJs está trabajando, en fallbacks para manejar estos casos.&lt;/p&gt;

&lt;p&gt;Uff, suficiente con la teoría 😓... En los siguientes post empezaremos con el código ¡Yes! 🤓, y los elementos básicos de todas las escenas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/javascriptchile/programacion-3d-con-javascript-parte-2-1jj8"&gt;Segunda parte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>threejs</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Vue + threeJs, importando modelos</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Mon, 13 Feb 2023 14:59:06 +0000</pubDate>
      <link>https://dev.to/jaimebboyjt/vue-threejs-importando-modelos-48ko</link>
      <guid>https://dev.to/jaimebboyjt/vue-threejs-importando-modelos-48ko</guid>
      <description>&lt;p&gt;Hola, Este es el tercer post de Vuejs+ threeJS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si no has visto el &lt;a href="https://dev.to/jaimebboyjt/vuejs-threejs-primera-parte-template-10ph"&gt;primer post&lt;/a&gt; donde creamos un template te lo recomiendo, usaremos ese template como base para este post &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta vez añadiremos un modelo 3D.&lt;/p&gt;

&lt;p&gt;Puedes descargar modelos 3D desde alguno de estos sitios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://sketchfab.com/" rel="noopener noreferrer"&gt;https://sketchfab.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://poly.pizza/" rel="noopener noreferrer"&gt;https://poly.pizza/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cgtrader.com/" rel="noopener noreferrer"&gt;https://www.cgtrader.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Como consideración importante, el peso del modelo es importante recuerda que el usuario lo va a tener q descargar desde su navegador, por lo que siempre modelos low Poly son recomendados, o optimizados para web&lt;/p&gt;

&lt;p&gt;Yo elegiré este modelo &lt;a href="https://poly.pizza/m/iltq5bVNaV" rel="noopener noreferrer"&gt;link&lt;/a&gt; y el resultado final es este:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/vue-threejs-model-part-1-xjnxqk?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fstatic%2Fimg%2Fplay-codesandbox.svg" alt="Edit Vue+threejs model part 1" width="165" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Formatos:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Existe una amplia variedad de formatos, incluso puedes crear uno nuevo.Entre los más comunes nos encontramos con:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OBJ&lt;/li&gt;
&lt;li&gt;GLTF&lt;/li&gt;
&lt;li&gt;glb (mi favorito personal)&lt;/li&gt;
&lt;li&gt;3DS (uno de los favoritos del maestro Bruno Simon)&lt;/li&gt;
&lt;li&gt;FBX&lt;/li&gt;
&lt;li&gt;Draco&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ThreeJs viene con &lt;strong&gt;loaders&lt;/strong&gt; para algunos de ellos, aunque no vienen importados en el “three” y tenemos que acceder al node_modules directamente para usarlos (esto se corregirá en futuras versiones de ThreeJs).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A codear&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Importamos y probamos el loader&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lo primero será descargar un modelo, yo para este ejemplo descargar un modelo low poli de &lt;a href="https://poly.pizza/m/iltq5bVNaV" rel="noopener noreferrer"&gt;https://poly.pizza/m/iltq5bVNaV&lt;/a&gt;. en formato glb que además tiene una animación (la usaremos en un futuro post)&lt;/p&gt;

&lt;p&gt;Ya conociendo el formato, podemos crear un composable, para rehusar lógica. Crearemos un nuevo archivo composables/useGltf&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GLTFLoader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three/examples/jsm/loaders/GLTFLoader&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// desconozco el motivo porque los loaders se encuentran dentro de examples&lt;/span&gt;
&lt;span class="c1"&gt;// en caso que tu modelo sea otro formato aca examples/jsm/loaders/ puedes revisar los loaders disponibles&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useGltfModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// para testear la función coloquemos en el onMouted&lt;/span&gt;
&lt;span class="c1"&gt;// además añadamos async al ciclo de vida&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego importamos la función en nuestro App.vue y certificamos que tengamos un log en la consola&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// añadimos el async al mounted&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;useGltfModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora subamos nuestro modelo, a nuestros assets, (si estás usando vite, te recomiendo subirlo dentro de la carpeta public, la importación es más fácil) usemos la función &lt;strong&gt;loadAsync&lt;/strong&gt;&lt;br&gt;
 que recibirá la ruta a nuestro modelo (el path). Además transformemos nuestra función en una promesa&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useGltfModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MODEL_PATH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y si todo ha ido bien podemos hacer un console.log en el mounted&lt;/p&gt;

&lt;p&gt;Lo que yo recomiendo es crear un container de modelos, inicializarlos fuera y así tenerlos accesibles en nuestro App.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;rat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;modelContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;useGltfModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelContainer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Añadir el modelo&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Normalmente los modelos que son exportados en otros software más robustos como blender exportan un objeto que contiene varias propiedades como scene, scenes, animations etc. Para añadirlo a la escena normalmente necesitamos el .scene&lt;/p&gt;

&lt;p&gt;Para añadir el modelo una forma es pasarle la escena directamente a la función y hacer el scene.add(_model.scene). Mientras hacemos este pequeño cambio añadamos otros parámetro que sea el path así nuestro useGltfModel quedará reutilizable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useGltfModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GLTFLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con todo correcto debiésemos poder ver nuestro modelo completamente negro, si has llegado hasta aca sin remover el cubo del template podrás fijarte.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e24klgru738b1q485o4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3e24klgru738b1q485o4.png" alt="Modelo todo negro" width="286" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo que sucede es que los modelos trabajan con PRB (Phisical Based Rendering) y usan materiales como MeshStandardMaterial que reaccionan a la luz. Necesitamos agregar luz a nuestra escena para poder apreciar nuestro modelo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Añadiendo luz&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Para tener más control creemos un archivo separado, lights.js y colocaremos nuestras luces allí.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Al igual que las sombras las luces y sus tipos pueden impactar en tu rendimiento úsalas sabiamente (explicaremos más en un capítulo de performance tips)&lt;/p&gt;

&lt;p&gt;Al igual que como en muchos objetos que nos proporciona threeJs existen muchos tipos de luces, dedicaremos un post entero a explicar como funcionan, por ahora vamos a añadir una simple directionalLight, que básicamente simula un sol y siempre apunta al centro de la escena.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DirectionalLight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initDirectionalLight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;directionalLight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DirectionalLight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xc0c0c0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;//Params (color, intensidad)&lt;/span&gt;
  &lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;directionalLight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;directionalLight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usémosla en nuestro App.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initDirectionalLight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./lights&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;light&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initDirectionalLight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ya vemos que nuestro modelo reacciona pero…. solo se ve desde arriba…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhobksgb58ga3a855mcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhobksgb58ga3a855mcd.png" alt="Modelo con luz" width="382" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;y para solucionarlo podemos hacer dos cosas.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Añadir rotación a la luz en nuestra función tick&lt;/li&gt;
&lt;li&gt;Añadir OrbicControls&lt;/li&gt;
&lt;li&gt;Bajar de position y nuestro modelo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dedicaremos otro post al tema de los controls para definirlo en profundidad pero en realidad es bastante sencillo&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Animando la luz&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Esta parte puede ser un poco compleja de entender al principio, y también añadiré un post para explicarlo con más profundidad. Pero básicamente le indicaremos a nuestra luz que gire sobre su eje.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Clock&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="c1"&gt;// dentro del mounted y antes de nuestra funcion tick&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// creamos un reloj que nos devolvera un tiempo &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsedTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElapsedTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// obtenemos la diferencia de tiempo que ha transcurrido entre el clock y el tick&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lightAngle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;elapsedTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// con el elapsedTime podemos crear un angulo,&lt;/span&gt;
        &lt;span class="c1"&gt;// luego con las funciones de coseno y seno se convertiran en un circulo&lt;/span&gt;
    &lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lightAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;light&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lightAngle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ¡Listoya! tenemos nuestra luz girando sobre su propio eje y mostrando nuestro modelo&lt;/p&gt;

&lt;p&gt;yo para efectos de mi modelo voy a ajustarlo un poco modelContainer.rat.scene.position.y = -1 pero puede que tu no lo necesites. (si lo deseas puedes eliminar el cube llegados a este punto)&lt;/p&gt;

&lt;p&gt;y con esto estaríamos listos.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusión&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hemos visto nuevos conceptos como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Light&lt;/li&gt;
&lt;li&gt;ElapsedTime&lt;/li&gt;
&lt;li&gt;Cómo cargar un modelo de manera asíncrona.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo esto nos servirá más adelante para nuestros futuros proyectos, threeJs es muy amplio pero a la vez tiene documentación muy buena.&lt;/p&gt;

</description>
      <category>gcp</category>
      <category>cli</category>
      <category>googlecloud</category>
      <category>bug</category>
    </item>
    <item>
      <title>Parallax mouse effect (Vue + Three.js)</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Mon, 30 Jan 2023 15:26:48 +0000</pubDate>
      <link>https://dev.to/jaimebboyjt/parallax-mouse-effect-4i62</link>
      <guid>https://dev.to/jaimebboyjt/parallax-mouse-effect-4i62</guid>
      <description>&lt;p&gt;Hola, Este es el segundo post de Vuejs+ threeJS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si no has visto el primer post donde creamos un template te lo recomiendo, usaremos el template creado como base para este post&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://dev.to/jaimebboyjt/vuejs-threejs-primera-parte-template-10ph"&gt;Link creacion del template&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esta vez añadiremos de manera sencilla un simple efecto parallax controlado por el mouse que se verá así:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/vue-threejs-template-parallax-effect-mz6slx?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rJFNpIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://codesandbox.io/static/img/play-codesandbox.svg" alt="Edit Vue+threejs-template parallax effect" width="201" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En realidad es bien sencillo, vamos a añadir el movimiento a la cámara.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Como el efecto es fácil de implementar, seguiremos trabajando en el app.vue pero siéntete libre de crear otro composable, cambiar nombres etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Capturando el movimiento del mouse&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;La primera parte es muy sencillo ya que vueUse nos da un composable que podemos usar, es el useMouse&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWindowSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMouse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vueuse/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos colocar un log dentro del nuestro watchEffect para asegurarnos que esté funcionando&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y_6AYlqM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.codepen.io/4698468/mouseDataImage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y_6AYlqM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.codepen.io/4698468/mouseDataImage.png" alt="" width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora si actualizamos nuestra cámara con estos valores, va a ser un caos, por lo que necesitamos convertirlos, para esto creamos dos variables nuevas usando el computed&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWindowSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMouse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cameraX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cameraY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dividiremos el valor del mouse por el valor de la pantalla, el eje X entre el width y el eje Y entre el height (valores que ya tenemos capturados del tutorial anterior&lt;/p&gt;

&lt;p&gt;Ahora si te fijas bien en la cameraY es diferente de cameraX, estamos imprimiendo un valor negativo, esto lo hacemos para invertir el valor que viene por defecto del evento mouse movement (recordemos que lo que deseamos es que si el mouse va para abajo nuestra cámara se vaya para abajo y la vista suba)&lt;/p&gt;

&lt;p&gt;Y además tenemos un - 0.5, los valores normales del mouse van a hacer de entre 0 y 1. Pero nosotros necesitamos que sean de entre -0.5 a 0.5 y sin mucha ingeniería, restamos el valor 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Actualizando la &lt;strong&gt;cámara&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Si vienes de la primera lección, tenemos nuestra función tick() donde colocaremos nuestro efecto.&lt;/p&gt;

&lt;p&gt;Lo siguiente es super sencillo, recordemos que la cámara es un object3D y por lo tanto tiene ciertas propiedades comunes, una de ellas es la posición.&lt;/p&gt;

&lt;p&gt;podemos acceder a ellas solo debemos colocar que propiedad queremos modificar y que eje (recordemos x,y,z)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cameraX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cameraY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora si deseas ampliar el limite puedes tomar y multiplicar el valor de camera.value y encontrar el que mejor se ajuste a tu escena&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;¡Listo!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Así de simple tenemos un bonito efecto que queda muy bien en muchas combinaciones. Esto también se hace muy simple cuando tenemos un template robusto&lt;/p&gt;

&lt;p&gt;Por último invitarte separar esta lógica y crear un nuevo composable 🙂&lt;/p&gt;

</description>
    </item>
    <item>
      <title>VueJs + ThreeJs Primera parte. Template</title>
      <dc:creator>Jaimebboyjt</dc:creator>
      <pubDate>Wed, 25 Jan 2023 19:49:13 +0000</pubDate>
      <link>https://dev.to/jaimebboyjt/vuejs-threejs-primera-parte-template-10ph</link>
      <guid>https://dev.to/jaimebboyjt/vuejs-threejs-primera-parte-template-10ph</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Esta será la primera de una serie de post sobre algunas técnicas para usar vueJs + threeJs. Aunque hay algunas librerías que nos facilitan el trabajo conocer las bases nos ayuda a tener conocimientos más sólidos&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://threejs.org/docs/"&gt;https://threejs.org/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vuejs.org/guide/quick-start.html#creating-a-vue-application"&gt;https://vuejs.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vueuse.org/"&gt;https://vueuse.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://greensock.com/"&gt;https://greensock.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://threejs-journey.xyz/"&gt;https://threejs-journey.xyz/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esta serie de post crearemos algunas cosas interesantes como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Como hacer un FPS (first person shooter camera)&lt;/li&gt;
&lt;li&gt;Parallax effect sobre una escena con threeJs que sigue al mouse&lt;/li&gt;
&lt;li&gt;Shadders&lt;/li&gt;
&lt;li&gt;usar 3D models&lt;/li&gt;
&lt;li&gt;y algunas cosillas más…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usaremos algunos conceptos avanzados por lo que es recomendable un conocimiento básico de cómo funciona VueJs y js. Pero no es necesario conocimiento previo con ThreeJs&lt;/p&gt;

&lt;p&gt;Crearemos un template que usaremos como base para las siguientes ediciones, como este:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/vue-threejs-template-cf3vcw?fontsize=14&amp;amp;hidenavigation=1&amp;amp;theme=dark&amp;amp;view=preview"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1rJFNpIB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://codesandbox.io/static/img/play-codesandbox.svg" alt="Edit Vue+threejs-template" width="201" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Lo primero será crear un nuevo proyecto con Vue e instalar las dependencias&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;your&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;vueuse&lt;/span&gt;&lt;span class="sr"&gt;/core thre&lt;/span&gt;&lt;span class="err"&gt;e
&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;dev&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para efectos de este tutorial eliminaremos todos los archivos y nos quedaremos solo con nuestros archivos App.vue y main.js dentro de /src&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuestra escena
&lt;/h2&gt;

&lt;p&gt;Para iniciar nuestra primera escena 3D necesitamos comprender y configurar algunos componentes así que vamos por partes, lo primero que necesitaremos será un canvas, (algunos autores lo crean directamente desde JS) yo prefiero crearlo en nuestro template.&lt;/p&gt;

&lt;p&gt;Le asignaremos un ref para tener acceso dentro del lifecycle onMouted&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;canvas&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "vue";

const canvas = ref(null);

onMounted(() =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="si"&gt;}&lt;/span&gt;);
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora necesitamos varias cosas, como la &lt;strong&gt;escena&lt;/strong&gt;, la &lt;strong&gt;cámara&lt;/strong&gt;, una función &lt;strong&gt;render&lt;/strong&gt;, un &lt;strong&gt;Mesh&lt;/strong&gt; (objeto que mostrar) y algunas pequeñas configuraciones, empecemos por la escena.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;// NOTA: Aunque muchos autores usan una notación * as THREE&lt;/span&gt;
&lt;span class="c1"&gt;// Yo personalmente prefiero importar sólo lo que necesito por temas de rendimiento&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y así de simple creamos nuestra escena (nada muy emocionante aún) pero vamos a ir poco a poco añadiendo todo lo que necesitamos a ella&lt;/p&gt;

&lt;h2&gt;
  
  
  Renderer
&lt;/h2&gt;

&lt;p&gt;Sigamos con el render, que no es más que una función de ThreeJs que realizará el renderizado de nuestra escena usando la WebGL API&lt;/p&gt;

&lt;p&gt;Crearemos un archivo renderer.js donde exportamos dos funciones un initRenderer y un updateRenderer, por ahora creemos el initRenderer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// renderer.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebGLRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebGLRenderer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;

        &lt;span class="na"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le indicamos donde renderizar (nuestro canvas), aunque podemos tener múltiples configuraciones, tales como color de la escena, manejo de sombras , etc. Nos quedaremos con lo básico, ahora usemos initRenderer en nuestro App.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;script setup&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aún no podemos ver nada pero vamos avanzando.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Nota&lt;/em&gt;*: Puede parecer extraño declarar una variable let renderer null al principio, no te preocupes esto se hace porque próximamente nuestro updateRender se dispara antes de que el obj renderer pueda ejecutarse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cámara
&lt;/h2&gt;

&lt;p&gt;Para poder visualizar algo, necesitamos una cámara, hay muchos tipos de cámaras disponibles en esta maravillosa librería de ThreeJs, elegiremos PerspectiveCamera&lt;/p&gt;

&lt;p&gt;Para esto también vamos a crear dos funciones initCamera y updateCamera empecemos por el init en un archivo separado camera.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//camera.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PerspectiveCamera&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PerspectiveCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// la position de la cámara por defecto es x:0, y:0 z:0&lt;/span&gt;
&lt;span class="c1"&gt;// recordemos que trabajamos con 3 dimensiones, el orden por defecto es XYZ&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para poder visualizar nuestra escena vamos a renderizarla con la función render() que recibe dos parámetros, la escena y la cámara (y añadirla a nuestra escena)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//&amp;lt;script setup&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./camera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y si todo ha salido de manera correcta deberíamos visualizar algo como:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TG855QPt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.codepen.io/4698468/Primera_scena.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TG855QPt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://assets.codepen.io/4698468/Primera_scena.png" alt="" width="786" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lo sé, lo sé. No es lo más emocionante del mundo pero pasos cortos.*&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tenemos dos detalles a corregir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El tamaño de la escena no corresponde a toda la pantalla&lt;/li&gt;
&lt;li&gt;Además el tamaño de la escena es fijo y no se actualiza (acá vamos a usar la reactividad de Vue para ayudarnos)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Update functions
&lt;/h3&gt;

&lt;p&gt;Crearemos dos funciones updateRenderer y updateCamera en sus correspondientes archivos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//renderer.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// configura nuestra escena con el tamaño enviado&lt;/span&gt;

&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setPixelRatio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;devicePixelRatio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// configura nuestra escena con el pixel Ratio del dispositivo&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;//camera.js&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateCamera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aspect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// configura nuestra escena con el aspectRatio enviado&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateProjectionMatrix&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// actualiza la projection de la cámara&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Necesitamos algunos parámetros extras para usar nuestras update functions, usaremos la reactividad de VueJs para que escuche los cambios y automáticamente llame a nuestra update function. Usemos un watchEffect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;script setup&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watchEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./camera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;También necesitamos hacer un llamado inicial de las funciones update en el onMounted.&lt;/p&gt;

&lt;p&gt;Usemos vueUse para obtener los tamaños reactivos de la pantalla&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWindowSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como extra añadamos unos estilos en el css global que nos van a ayudar&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="py"&gt;touch-action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y nuestro App quedaría de esta forma&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;script setup&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watchEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWindowSize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vueuse/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateCamera&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./camera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWindowSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Es ok si perdemos visibilidad de la escena a este punto, esto es porque el updateRenderer y updateCamera se ejecutan antes del mounted&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Function tick
&lt;/h3&gt;

&lt;p&gt;La función tick() (el maestro Bruno Simon la llama de esta forma), es una función versátil, que nos permitirá animar los objetos que se encuentren dentro de nuestra escena, le dará vida a nuestra app, además como usa el  requestAnimationFrame API tiene buen rendimiento&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;//App..vue dentro del mounted&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//render&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// moveremos nuestro renderer dentro de tick()&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// cada frame ejecutara un tick()&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// inicializamos tick()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ya casi…
&lt;/h3&gt;

&lt;p&gt;uff hasta ahora hay bastante código y solo una escena totalmente negra (color por default)&lt;/p&gt;

&lt;p&gt;Pero con todo configurado, ahora si intentamos hacer resize a la pantalla, veremos que nuestra escena se actualiza de manera automática, al igual que nuestra cámara.&lt;/p&gt;

&lt;p&gt;Hasta ahora nuestro script va de esta forma&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watchEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWindowSize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vueuse/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateRenderer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./renderer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateCamera&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./camera&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useWindowSize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;camera&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//render&lt;/span&gt;
        &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mesh
&lt;/h3&gt;

&lt;p&gt;Aunque para los Mesh hay infinidades de combinaciones: materiales, geometrías, texturas y propiedades, que poco a poco indagaremos más en ellas, por el momento crearemos la forma más simple posible un cubo, yo recomendaría tratar de dejar lo más despejado el App.vue y crear un archivo aparte algo como cube.js (que luego reemplazamos por otros modelos o sencillamente lo eliminaremos)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// cube.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BoxGeometry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MeshBasicMaterial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Mesh&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;three&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;geometry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BoxGeometry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// la BoxGeometry necesita los parámetros de width, height y depth&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;material&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MeshBasicMaterial&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0x00ff00&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// el MeshBasicMaterial es el material más básico, no necesita luz&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Mesh&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;geometry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para crear un mesh, necesitamos una geometría y un material.&lt;/p&gt;

&lt;p&gt;Hay muchas geometrías e incluso podemos crear las nuestras propias, y también hay muchos materiales cada uno con diferentes propiedades, algunos reflejan sombra, otros tienen refracción de luz. Muchos de estos temas los estaremos viendo más adelante.&lt;/p&gt;

&lt;p&gt;Por ahora importamos y añadamos a nuestra escena&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// App.vue&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCube&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./cube&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCube&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;onMouted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y te darás cuenta que…. nada se renderiza 😟. ¿Por qué sucede esto?&lt;/p&gt;

&lt;p&gt;Realmente si se esta renderizando pero no lo podemos ver, (podemos checarlo haciendo un console.log(scene) y revisando si tiene un children, y lo que sucede es muy simple.&lt;/p&gt;

&lt;p&gt;Nuestra cámara está en la posición (0,0,0) al igual que nuestro cubo. es la posición por defecto y no la hemos cambiado. (recordemos que el orden es X,Y,Z)&lt;/p&gt;

&lt;p&gt;La cámara así como nuestro Mesh son lo que denominamos 3d Object y comparten propiedades como, scale, rotation y posición. Todas en tres dimensiones.&lt;/p&gt;

&lt;p&gt;Para solucionarlo solo movamos la cámara un poco para atrás, nos vamos a nuestro camera.js y justo antes del return añadimos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// si te preguntas 5 qué? la mejor forma de verlo son 5 unidades, una buena práctica&lt;/span&gt;

&lt;span class="c1"&gt;// es definir si son 5 metros, 5 centímetros depende de tu scena&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahí está! un cuadrado en el medio de nuestra escena, verde, inmóvil y que parece en 2D 😟&lt;/p&gt;

&lt;p&gt;Ah! pero no es en 2D, lo que sucede es que nuestra cámara está exactamente alineada, de frente a él&lt;/p&gt;

&lt;p&gt;Agreguemos una pequeña animación, verán que es muy fácil&lt;/p&gt;

&lt;p&gt;Para esto en nuestra función tick() vamos a añadir un estas dos líneas de código&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="nx"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;

&lt;span class="nx"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y listo.&lt;/p&gt;

&lt;p&gt;uff fue bastante trabajo no? varias cosas que configurar, nuevos conceptos pero al final tenemos un template robusto que podemos usar como base para infinita variedad de proyectos&lt;/p&gt;

&lt;p&gt;Así se ve nuestro código hasta el momento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;canvas&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watchEffect&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "vue";
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "three";
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useWindowSize&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "@vueuse/core";
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateRenderer&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "./renderer";
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCamera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updateCamera&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "./camera";
import &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCube&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; from "./cube";

const canvas = ref(null);
const scene = new Scene();
let renderer = null;
let camera = null;

const cube = createCube();
camera = initCamera();

const &lt;span class="si"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt; = useWindowSize();
const aspectRatio = computed(() =&amp;gt; width.value / height.value);

scene.add(camera);
scene.add(cube);

watchEffect(() =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;);

onMounted(() =&amp;gt; &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateRenderer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;aspectRatio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//render&lt;/span&gt;
        &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;//animation&lt;/span&gt;
        &lt;span class="nx"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;cube&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;);

&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
* &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

canvas &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;touch&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Hasta ahora puede parecer que tengamos solo un cubo verde dando vueltas, pero la verdad tenemos un template que usaremos más adelante sirve como base para ya no preocuparnos de pequeños detalles.&lt;/p&gt;

&lt;p&gt;Que hemos aprendido:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Crear una escena básica y renderizarla&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Crear un Mesh, añadirlo a la escena y agregarle animación&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cómo usar la reactividad de VueJs, para añadir reactividad a la escena&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
  </channel>
</rss>
