Skip to content

Commit

Permalink
Failed attempt at adding WebGPU renderer support
Browse files Browse the repository at this point in the history
  • Loading branch information
callumacrae committed May 22, 2023
1 parent 46ec2e9 commit a475a3f
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 22 deletions.
23 changes: 23 additions & 0 deletions playground/src/pages/WebGPURenderer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script setup lang="ts">
import WebGPURenderer from 'three/examples/jsm/renderers/webgpu/WebGPURenderer';
import { extend, TresCanvas } from '@tresjs/core'
import { TeapotGeometry } from 'three/examples/jsm/geometries/TeapotGeometry.js';
import { MeshBasicNodeMaterial } from 'three/examples/jsm/nodes/Nodes';
// import TheSphere from './TheSphere.vue'
// import { OrbitControls } from '@tresjs/cientos'
const renderer = (canvas: any) => new WebGPURenderer();
extend({ TeapotGeometry, MeshBasicNodeMaterial });
</script>

<template>
<TresCanvas ref="context" :custom-renderer="renderer">
<TresPerspectiveCamera :position="[0, 200, 800]" :look-at="[0, 0, 0]" :fov="45" />
<TresMesh :position="[0, 4, 0]">
<TresTeapotGeometry :args="[50, 18]" />
<TresMeshBasicNodeMaterial />
</TresMesh>
<TresAmbientLight :intensity="1" />
</TresCanvas>
</template>
5 changes: 5 additions & 0 deletions playground/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ const routes = [
name: 'Shapes',
component: () => import('./pages/shapes.vue'),
},
{
path: '/webgpu-renderer',
name: 'WebGPURenderer',
component: () => import('./pages/WebGPURenderer.vue'),
},
]
export const router = createRouter({
history: createWebHistory(),
Expand Down
3 changes: 3 additions & 0 deletions src/components/TresCanvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TresScene } from './TresScene'
import { defineComponent, h } from 'vue'
import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
import type { Renderer } from 'three'
import { CameraType, useTresProvider } from '../composables'
import { RendererPresetsType } from '../composables/useRenderer/const'
import { Component } from 'vue'
Expand All @@ -21,6 +22,7 @@ export interface TresCanvasProps {
preset?: RendererPresetsType
disableRender?: boolean
camera?: CameraType
customRenderer?: (canvas: any) => Renderer
}
/**
* Vue component for rendering a Tres component.
Expand All @@ -44,6 +46,7 @@ export const TresCanvas = defineComponent<TresCanvasProps>({
'preset',
'disableRender',
'camera',
'customRenderer',
] as unknown as undefined,
setup(props, { slots, expose }) {
const tres = useTresProvider()
Expand Down
8 changes: 5 additions & 3 deletions src/components/TresScene.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { App, defineComponent, h, onMounted, onUnmounted, ref, watch, watchEffect, VNode } from 'vue'
import * as THREE from 'three'
import { ColorSpace, ShadowMapType, ToneMapping } from 'three'
import { ColorSpace, Scene, ShadowMapType, ToneMapping } from 'three'
import type { Renderer } from 'three'
import { useEventListener } from '@vueuse/core'
import { isString } from '@alvarosabu/utils'
import { createTres } from '../core/renderer'
Expand Down Expand Up @@ -34,6 +34,7 @@ export interface TresSceneProps {
preset?: RendererPresetsType
disableRender?: boolean
camera?: CameraType
customRenderer?: (canvas: any) => Renderer
}
/**
* Vue component for rendering a Tres component.
Expand All @@ -59,6 +60,7 @@ export const TresScene = defineComponent<TresSceneProps>({
'preset',
'disableRender',
'camera',
'customRenderer',
] as unknown as undefined,
setup(props, { slots, expose }) {
if (props.physicallyCorrectLights === true) {
Expand All @@ -67,7 +69,7 @@ export const TresScene = defineComponent<TresSceneProps>({

const container = ref<HTMLElement>()
const canvas = ref<HTMLElement>()
const scene = new THREE.Scene()
const scene = new Scene()
const { setState } = useTres()

setState('scene', scene)
Expand Down
56 changes: 37 additions & 19 deletions src/composables/useRenderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
Clock,
ColorSpace,
} from 'three'
import type { ToneMapping } from 'three'
import type { ToneMapping, Renderer } from 'three'
import { useRenderLoop } from '../useRenderLoop'
import { useTres } from '../useTres'
import { normalizeColor } from '../../utils/normalize'
Expand Down Expand Up @@ -112,6 +112,14 @@ export interface UseRendererOptions extends WebGLRendererParameters {
clearColor?: MaybeRefOrGetter<TresColor>
windowSize?: MaybeRefOrGetter<boolean | string>
preset?: RendererPresetsType

/**
* The renderer to use, if you don't want to use WebGLRenderer or if you want
* to provide your own instance.
*
* @default undefined
*/
customRenderer?: (canvas: any) => Renderer
}

/**
Expand All @@ -121,7 +129,7 @@ export interface UseRendererOptions extends WebGLRendererParameters {
* @param {UseRendererOptions} [options]
*/
export function useRenderer(options: UseRendererOptions) {
const renderer = shallowRef<WebGLRenderer>()
const renderer = shallowRef<Renderer>()
const isReady = ref(false)
// Defaults
const {
Expand All @@ -145,6 +153,7 @@ export function useRenderer(options: UseRendererOptions) {
clearColor,
windowSize = false,
preset = undefined,
customRenderer = undefined,
} = toRefs(options)

const { state, setState } = useTres()
Expand All @@ -169,11 +178,13 @@ You could set windowSize=true to force the canvas to be the size of the window.`
}

renderer.value.setSize(width.value, height.value)
renderer.value.setPixelRatio(Math.min(pixelRatio.value, 2))
if ('setPixelRatio' in renderer.value && typeof renderer.value.setPixelRatio === 'function') {
renderer.value.setPixelRatio(Math.min(pixelRatio.value, 2))
}
}

const updateRendererOptions = () => {
if (!renderer.value) {
if (!renderer.value || !(renderer.value instanceof WebGLRenderer)) {
return
}

Expand Down Expand Up @@ -206,20 +217,25 @@ You could set windowSize=true to force the canvas to be the size of the window.`
return
}

renderer.value = new WebGLRenderer({
canvas: _canvas,
alpha: toValue(alpha),
antialias: toValue(antialias),
context: toValue(context),
depth: toValue(depth),
failIfMajorPerformanceCaveat: toValue(failIfMajorPerformanceCaveat),
logarithmicDepthBuffer: toValue(logarithmicDepthBuffer),
powerPreference: toValue(powerPreference),
precision: toValue(precision),
stencil: toValue(stencil),
preserveDrawingBuffer: toValue(preserveDrawingBuffer),
premultipliedAlpha: toValue(premultipliedAlpha),
})
const customRendererValue = toValue(customRenderer)
if (customRendererValue) {
renderer.value = customRendererValue(_canvas)
} else {
renderer.value = new WebGLRenderer({
canvas: _canvas,
alpha: toValue(alpha),
antialias: toValue(antialias),
context: toValue(context),
depth: toValue(depth),
failIfMajorPerformanceCaveat: toValue(failIfMajorPerformanceCaveat),
logarithmicDepthBuffer: toValue(logarithmicDepthBuffer),
powerPreference: toValue(powerPreference),
precision: toValue(precision),
stencil: toValue(stencil),
preserveDrawingBuffer: toValue(preserveDrawingBuffer),
premultipliedAlpha: toValue(premultipliedAlpha),
})
}

setState('renderer', renderer.value)
setState('clock', new Clock())
Expand All @@ -236,7 +252,9 @@ You could set windowSize=true to force the canvas to be the size of the window.`
return
}

renderer.value.dispose()
if ('dispose' in renderer.value && typeof renderer.value.dispose === 'function') {
renderer.value.dispose()
}
renderer.value = undefined

isReady.value = false
Expand Down

0 comments on commit a475a3f

Please # to comment.