着色器
本指南将帮助你开始在 TresJS 中使用着色器。
我们将构建一个带有 blob 的简单场景。然后,我们将对 blob 进行动画处理,使其柔和地扭曲。
WARNING
需要了解着色器工作原理的基本知识
设置场景(可选)
我们导入所需的所有模块,为了方便,我们可以使用 cientos 中的轨道控件,点击此处查看方法。
现在,我们将相机放在 [11,11,11]
位置。
最后,为了帮助我们确定位置,我们添加一个简单的平面,绕 X 轴旋转,单位为 [10, 10]
。
<script setup lang="ts">
import { OrbitControls } from '@tresjs/cientos'
import { TresCanvas } from '@tresjs/core'
</script>
<template>
<TresCanvas
clear-color="#111"
window-size
>
<OrbitControls />
<TresPerspectiveCamera :position="[11, 11, 11]" />
<TresMesh :rotation="[-Math.PI / 2, 0, 0]">
<TresPlaneGeometry :args="[10, 10]" />
<TresMeshBasicMaterial color="#444" />
</TresMesh>
</TresCanvas>
</template>
ShaderMaterial
如你所知,ThreeJs 中的每个实例都可以在 TresJs 中使用,ShaderMaterial
也是如此,我们只需要添加 Tres
前缀即可使用它。
对于我们的 blob ,我们可以使用简单的 SphereGeometry
,添加一些 widthSegments
和 heightSegments
来创建平滑效果,并将 blob 放在 Y 轴正方向的 4 个单位处
<TresMesh :position="[0, 4, 0]">
<TresSphereGeometry :args="[2, 32, 32]" />
<TresShaderMaterial />
</TresMesh>
ShaderMaterial
接受特殊属性,如 uniforms
vertexShader
和 fragmentShader
,因此我们可以在脚本部分创建它,并与我们的实例进行绑定。
对于此示例,我们的 uniforms 如下所示:
import { Vector2 } from 'three'
// ...
const uniforms = {
uTime: { value: 0 },
uAmplitude: { value: new Vector2(0.1, 0.1) },
uFrequency: { value: new Vector2(20, 5) },
}
// ..
我们的片段着色器如下所示:
// ...
const fragmentShader = `
precision mediump float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(1.0, vUv.y, 0.5, 1.0);
}
`
// ..
最后是我们的顶点着色器:
const vertexShader = `
uniform vec2 uAmplitude;
uniform vec2 uFrequency;
uniform float uTime;
varying vec2 vUv;
void main() {
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
modelPosition.y += sin(modelPosition.x * uFrequency.x - uTime) * uAmplitude.x;
modelPosition.x += cos(modelPosition.y * uFrequency.y - uTime) * uAmplitude.y;
vec4 viewPosition = viewMatrix * modelPosition;
gl_Position = projectionMatrix * viewPosition;
vUv = uv;
}
`
// ..
为 blob 添加动画
类似于我们在 基本动画 示例中学习到的,我们首先使用 模板引用 引用 blob
<script setup lang="ts">
import { OrbitControls } from '@tresjs/cientos'
import { TresCanvas } from '@tresjs/core'
import { shallowRef } from 'vue'
const blobRef = shallowRef(null)
// ...
</script>
<template>
<TresCanvas
clear-color="#111"
window-size
>
<OrbitControls />
<TresPerspectiveCamera :position="[11, 11, 11]" />
<TresMesh
ref="blobRef"
:position="[0, 4, 0]"
>
<TresSphereGeometry :args="[2, 32, 32]" />
<TresShaderMaterial />
</TresMesh>
</TresCanvas>
</template>
获得引用后,我们可以使用 onLoop
回调为 uTime
添加动画。
import { TresCanvas, useRenderLoop } from '@tresjs/core'
// ...
const { onLoop } = useRenderLoop()
onLoop(({ elapsed }) => {
if (blobRef.value) {
blobRef.value.material.uniforms.uTime.value = elapsed
}
})
// ...
就这样,我们的基本着色器顺利运行。
使用 GLSL vite 插件(可选)
此步骤完全是可选的,并且超出了 TresJs 团队的范围
将着色器定义为内联形式并不总是最好的主意,但是如果你正在使用 vite,你可以通过使用 vite-plugin-glsl 将你的 GLSL
文件放在另一个文件中(查看链接以获取官方文档)。
你可以拥有类似于这样的结构:
├── src/
│ ├── myTresJsComponent.vue
│ ├── shaders/
│ ├── vertexShader.glsl
│ ├── fragmentShader.glsl