three.js利用着色器实现波浪效果
·
效果演示
着色器旗帜
1、实现步骤
1.1创建项目
// 创建一个空项目
import * as THREE from 'three'
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//1、创建场景
const scene = new THREE.Scene()
//2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
) // 参数分别代表,相机角度、屏幕宽高比、近端点,远端点
//设置相机位置
camera.position.set(0, 0, 10)
scene.add(camera)
//添加环境光和平行光
const ambientLight = new THREE.AmbientLight(0xffffff, 1)
const dirLight = new THREE.DirectionalLight(0xffffff, 1)
dirLight.castShadow = true
scene.add(ambientLight)
scene.add(dirLight)
//初始化渲染器
const renderer = new THREE.WebGLRenderer()
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
renderer.physicallyCorrectLights = true
//将webGL渲染的canvas添加到app中
document.getElementById('app').appendChild(renderer.domElement)
//创建控制器
const controls = new OrbitControls(camera, renderer.domElement)
//设置控制器阻尼,让滑动更有真实感
controls.enableDamping = true
//创建坐标轴
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
//设置时钟
const clock = new THREE.Clock()
render()
//渲染函数
function render() {
const time = clock.getElapsedTime()
controls.update()
renderer.render(scene, camera)
//下一帧渲染完毕再次执行,保证每一帧都渲染
requestAnimationFrame(render)
}
1.2创建顶点着色器和片元着色器
新建文件夹shader/raw/vertexShader.glsl和shader/raw/fragmentShader.glsl分别存储顶点着色器和片元着色器
// shader/raw/vertexShader.glsl
precision lowp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform float uTime;//拿到传过来的uTime
varying vec2 vUv;
varying float vElevation;
void main() {
vUv = uv;
vec4 modelPosition = modelMatrix * vec4(position,1.0);
//波浪
modelPosition.z = sin((modelPosition.x + uTime) * 10.0) * 0.05;
modelPosition.z += sin((modelPosition.y + uTime)* 10.0) * 0.05;
vElevation = modelPosition.z;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
// shader/raw/fragmentShader.gls
precision highp float;
varying vec2 vUv;
varying float vElevation;
uniform sampler2D uTexture;
void main(){
// gl_FragColor = vec4(vUv,0.0,1.0);
// float height = vElevation + 0.05 * 10.0;
// gl_FragColor = vec4(1.0 * height,0.0,0.0,1.0);
//根据uv,取出对应的颜色
vec4 textureColor = texture2D(uTexture,vUv);
float height = vElevation + 0.05 * 20.0;
textureColor.rgb *= height;
gl_FragColor = textureColor;
}
1.3导入着色器和纹理
//导入顶点着色器
import basicVertexShader from '@/shader/raw/vertexShader.glsl?raw'
//导入片元着色器
import basicFragmentShader from '@/shader/raw/fragmentShader.glsl?raw'
//导入纹理
const textureLoader = new THREE.TextureLoader()
const imgTexture = textureLoader.load('/static/imgs/ca.jpeg')
1.4创建物体和材质
//创建平面
const floorGeometry = new THREE.PlaneGeometry(1, 1, 64, 64)
// const floorMaterial = new THREE.MeshBasicMaterial({ color: '#00ff00' })
//创建着色器材质
const floorMaterial = new THREE.RawShaderMaterial({
//让着色器材质跟随相机等转,顶点着色器
vertexShader: basicVertexShader,
//片源着色器
fragmentShader: basicFragmentShader,
// wireframe: true,
side: THREE.DoubleSide,
//给顶点着色器传的值uniforms
uniforms: {
uTime: {
value: 0,
},
uTexture: {
value: imgTexture,
},
},
})
const floorMesh = new THREE.Mesh(floorGeometry, floorMaterial)
scene.add(floorMesh)
1.5让物体动起来
//渲染函数
function render() {
const time = clock.getElapsedTime()
floorMaterial.uniforms.uTime.value = time //给片元着色器传的
controls.update()
renderer.render(scene, camera)
//下一帧渲染完毕再次执行,保证每一帧都渲染
requestAnimationFrame(render)
}
2、全部代码
import * as THREE from 'three'
//目标:学习着色器变量
//导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
//导入顶点着色器
import basicVertexShader from '@/shader/raw/vertexShader.glsl?raw'
//导入片元着色器
import basicFragmentShader from '@/shader/raw/fragmentShader.glsl?raw'
//1、创建场景
const scene = new THREE.Scene()
//2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
) // 参数分别代表,相机角度、屏幕宽高比、近端点,远端点
//设置相机位置
camera.position.set(0, 0, 10)
scene.add(camera)
//导入纹理
const textureLoader = new THREE.TextureLoader()
const imgTexture = textureLoader.load('/static/imgs/ca.jpeg')
//创建平面
const floorGeometry = new THREE.PlaneGeometry(1, 1, 64, 64)
// const floorMaterial = new THREE.MeshBasicMaterial({ color: '#00ff00' })
//创建着色器材质
const floorMaterial = new THREE.RawShaderMaterial({
//让着色器材质跟随相机等转,顶点着色器
vertexShader: basicVertexShader,
//片源着色器
fragmentShader: basicFragmentShader,
// wireframe: true,
side: THREE.DoubleSide,
//给顶点着色器传的值uniforms
uniforms: {
uTime: {
value: 0,
},
uTexture: {
value: imgTexture,
},
},
})
const floorMesh = new THREE.Mesh(floorGeometry, floorMaterial)
scene.add(floorMesh)
//添加环境光和平行光
const ambientLight = new THREE.AmbientLight(0xffffff, 1)
const dirLight = new THREE.DirectionalLight(0xffffff, 1)
dirLight.castShadow = true
scene.add(ambientLight)
scene.add(dirLight)
//初始化渲染器
const renderer = new THREE.WebGLRenderer()
//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
renderer.physicallyCorrectLights = true
//将webGL渲染的canvas添加到app中
document.getElementById('app').appendChild(renderer.domElement)
//创建控制器
const controls = new OrbitControls(camera, renderer.domElement)
//设置控制器阻尼,让滑动更有真实感
controls.enableDamping = true
//创建坐标轴
const axesHelper = new THREE.AxesHelper(5)
scene.add(axesHelper)
//设置时钟
const clock = new THREE.Clock()
render()
//渲染函数
function render() {
const time = clock.getElapsedTime()
floorMaterial.uniforms.uTime.value = time
controls.update()
renderer.render(scene, camera)
//下一帧渲染完毕再次执行,保证每一帧都渲染
requestAnimationFrame(render)
}
更多推荐
已为社区贡献3条内容
所有评论(0)