Blog post hero image

TresJS 1 Year Anniversary

Alvaro Saburido
Alvaro Saburido @alvarosabu

A year ago, I was learning how to use React Three Fiber, a custom renderer with the power of creating 3D scenes declarately with React components and it blowed my mind ๐Ÿคฏ.

Then, I did what I do best, complain in twitter ๐Ÿ˜… ๐Ÿ˜‚:

Tweet complaining about the lack of a 3D framework on VueJS

Yep, that was the panorama for VueJS developers like me back then. There were some initiatives like TroisJS, a manual wrapper of ThreeJS for VueJS that became unmantained and Lunchbox, who were the firsts to try to create a renderer. But, it was not enough for me, inspired by Pmndrs work and Thretle for Svelte I decided to create a renderer for VueJS, and thatโ€™s how TresJS was born.

First commits of TresJS

I started with a simple idea, provide the vue community with a ecosystem that would allow you to create 3D scenes declaratively with VueJS components and that was easy to mantain and extend.

For us it was important to solve the biggest problems of previous solutions:

  • Keep it up to date with ThreeJS which constantly updates
  • A good DX, we wanted to make it easy to use and learn
  • Performant, even with reactivity.
  • Extendable, we wanted to make it easy to create new components and extend the core library with community-driven packages.

Although v1 was a decent solution ๐Ÿ˜„ and we managed to achieve some of the goals, it has some limitations that would only be solved by using Vueโ€™s Custom Renderer API.

Roadmap to v2

via GIPHY

Getting started with the Custom Renderer API was not easy, itโ€™s a very powerful API but itโ€™s not completly documented and itโ€™s not easy to find examples. We had to learn how to use it by reading the source code of VueJS and how the framework uses it internally to render the DOM @vue/runtime-dom.

Thats when Verekia author of WebGameDev and one of our earliest supporters, put me in contact with Cody Bennet and Paul Henschel (0xca0a) who are not more no less than the creators of React Three Fiber. They were very kind and helped me a lot with the fundations of the project and Cody did a small PoC replicating the React Three Fiber custom renderer but with the VueJS API.

Voilร ! We had a working prototype of a custom renderer for VueJS, thanks to that example, I was able to understand how the API works and how to develop it further to assemble the scene graph based on nodes using insert, patchProp and createElement methods.

// core/renderer.ts
import * as THREE from 'three'

import { createRenderer } from 'vue'
import { extend } from './catalogue'
import { nodeOps } from './nodeOps'

export const { render } = createRenderer(nodeOps)

// Creates the catalogue of components based on THREE namespace
extend(THREE)

export default { extend }

where the nodeOps are the methods that the renderer uses to create the scene graph and patch the props of the nodes.

// core/nodeOps.ts
export const nodeOps: RendererOptions<TresObject, TresObject> = {
  createElement(tag, _isSVG, _anchor, props) {
    // Matches tags with the catalogue of THREE constructors with arguments and returns the instance
  },
  insert(child, parent) {
    // Adds the instance to the scene graph
  },
  remove(node) {
    // Removes the instance from the scene graph and dispose it from memory
  },
  patchProp(node, prop, _prevValue, nextValue) {
    // Handles props
  },
}

With a <TresCanvas /> component, we were able to provide a context for the custom renderer, a catalogue of instances from Three namespace, a state and a scene graph that would be shared across the ecosystem using provide and inject API.

// TresCanvas.vue

const createInternalComponent = (context: TresContext) =>
  defineComponent({
    setup() {
      const ctx = getCurrentInstance()?.appContext
      if (ctx) ctx.app = instance as App
      provide('useTres', context)
      provide('extend', extend)
      return () => h(Fragment, null, slots?.default ? slots.default() : [])
    },
  })

const mountCustomRenderer = (context: TresContext) => {
  const InternalComponent = createInternalComponent(context)
  render(h(InternalComponent), scene.value as unknown as TresObject)
}

onMounted(() => {
  const existingCanvas = canvas as Ref<HTMLCanvasElement>

  context.value = useTresContextProvider({
    scene: scene.value,
    canvas: existingCanvas,
    windowSize: props.windowSize,
    disableRender,
    rendererOptions: props,
  })
  mountCustomRenderer(context.value)
})

Core Team assembly

Soon after, Jaime Torralba and Tino joined the core-team. Jaime took the lead of the abstractions and helpers on the cientos package, providing the ecosystem with really cool demos, and Tino contributed heavily on the stability of the core, creating a context provider for the state and everything related to pointer events and raycasting.

andretchen0 joined the team later after collaborating heavily extending cientos with new components and helpers that literally blowed our minds off ๐Ÿคฏ.

Way more people has contributed to the project without being on the core team and we are really grateful for that. Contributors

They are the heart of the project and without them, TresJS would not be what it is today ๐Ÿ’š.

Open Source at VueJS London

Until this point, TresJS was a private repository. We were not sure if the project was going to be successful or not, but we were sure that we wanted to make it open source. So we decided to make it public live on stage at VueJS Live London.

Funny enough, Github gave us a really hard time with authentication to make it public, you know, the magic of live stage. ๐Ÿ˜…

Status Quo

A year after, we have a stable ecosystem that allow you to create 3D scenes declaratively with VueJS. We have a lot of cool demos and people using TresJS already in production for webistes and, games ๐Ÿ•น๏ธ.

  • More than 1000 ๐ŸŒŸ on Github across the ecosystem, being the core the most starred repository (818),
  • Around 550 PR merged, and > 1700 commits in total.
  • 30,800 downloads ๐Ÿคฏ (around 1.4k monthly) see npm-stats

Total npm downloads of TresJS ecosystem

Future

Now, itโ€™s time to look forward to the future. And we couldnโ€™t be more excited about it. 2024 is going to be a big year for TresJS, we have a lot of cool stuff coming up:

Post-processing ๐Ÿ“ฆ is reaching alpha soon.

Post-processing demo

We are working on a post-processing package @tresjs/post-processing that will introduce the concept of passes and effects to extend the common rendering workflow with fullscreen image manipulation tools your scenes declaratively. Itโ€™s based on postprocessing and itโ€™s going to be a game changer for the ecosystem.

<script setup>
import { EffectComposer, DepthOfField, Bloom } from '@tresjs/post-processing'
</script>

<template>
  <TresCanvas>
    <EffectComposer>
      <DepthOfField />
      <Bloom />
    </EffectComposer>
  </TresCanvas>
</template>

You can follow up the progress in the official repo. We are looking for contributors to help us with the development and testing ๐Ÿ˜Š.

TresLeches ๐Ÿฐ GUI for Vue controls

Something that is also close to alpha is TresLeches, a GUI for Vue controls. Fine-tuning ๐ŸŽ›๏ธ and monitoring your scenes like never before

#008080
๐Ÿฐ
0 FPS

Official repo and docs. We are also looking for contributors to help us with the development.

๐Ÿ‘€ Physics and XR

Two major features that we are looking forward to implement in the ecosystem are physics and XR. We are still in the early stages of the development, but we are really excited about it since the community has been asking for it for a long time.

The physics package will be based on Rapier physics engine and the XR package will be based on three.js and webxr.

If you want to participate in the development of these packages, you can join us in the Discord server.

Support the project

If you like the project and want to support it, you can do it in many ways:

  • If you are a company or an individual using TresJS in your projects, please consider becoming a Sponsor. Your sponsorship will help us to maintain the project and develop new features.

  • Contribute to the project. If you are a developer, you can contribute to the project by creating new components, fixing bugs, or improving the documentation. You can also help us by testing the packages and reporting bugs.

  • Spread the word. If you are not a developer, you can help us by spreading the word about the project. You can share the project on social media, write a blog post about it, or tell your friends about it.

Thank you and for another year of 3D on Vue with TresJS ๐ŸŽ‰ ๐ŸŽ‰