我试图创建这种链接http://blog.edankwan.com/post/my-first-christmas-experiment底部页面上的雪花效果。其他所有工作都很好,但是无法使运动模糊效果正常工作。有任何想法吗?
用于实现运动模糊效果的纹理精灵
代码如下:
(function(global) {
var img = 'https://i.imgur.com/hlmsgWA.png'
var renderer, scene, camera
var w = 800, h = 320
var uniforms
var geometry
var texture, material
var gui
var conf = {
amount: 200,
speed: 0.5,
time: 0
}
var obj = {
init: function() {
renderer = new THREE.WebGLRenderer({
antialias: true
})
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(w, h)
camera = new THREE.Camera
scene = new THREE.Scene()
geometry = new THREE.BufferGeometry()
var positions = []
for(var i = 0, l = conf.amount; i < l; i++) {
positions[i * 3] = Math.random() * 800 - 400
positions[i * 3 + 1] = i
positions[i * 3 + 2] = Math.random() * 800
}
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3))
var vs = document.getElementById('vertexShader').textContent
var fs = document.getElementById('fragmentShader').textContent
uniforms = {
u_amount: {
type: 'f',
value: conf.amount
},
u_speed: {
type: 'f',
value: conf.speed
},
u_time: {
type: 'f',
value: conf.time
},
u_resolution: {
type: 'vec2',
value: new THREE.Vector2(w, h)
},
u_texture : {
value: new THREE.TextureLoader().load(img)
}
}
material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vs,
fragmentShader: fs,
transparent: true
})
var points = new THREE.Points(geometry, material)
scene.add(points)
document.body.appendChild(renderer.domElement)
this.render()
this.createGui()
},
createGui: function() {
gui = new dat.GUI()
gui.add(conf, 'speed', -1, 1)
},
render: function() {
requestAnimationFrame(this.render.bind(this))
uniforms.u_time.value += conf.speed * 0.003
renderer.render(scene, camera)
}
}
obj.init()
})(window)
<script id="vertexShader" type="x-shader/x-vertex">
precision highp float;
vec3 getPosOffset(float ratio, float thershold) {
return vec3(
cos((ratio * 80.0 + 10.0) * thershold) * 20.0 * thershold,
(sin((ratio * 90.0 + 30.0) * thershold) + 1.0) * 5.0 * thershold + mix(500.0, -500.0, ratio / thershold),
sin((ratio * 70.0 + 20.0) * thershold) * 20.0 * thershold
);
}
uniform vec2 u_resolution;
uniform float u_amount;
uniform float u_speed;
uniform float u_time;
varying float v_alpha;
varying float v_rotation;
varying float v_index;
void main() {
float indexRatio = position.y / u_amount;
float thershold = 0.7 + indexRatio * 0.3;
float ratio = mod(u_time - indexRatio * 3.0, thershold);
float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);
vec3 offsetPos = getPosOffset(ratio, thershold);
vec3 prevOffsetPos = getPosOffset(prevRatio, thershold);
vec3 pos = position;
pos += offsetPos;
float perspective = (2000.0 - pos.z) / 2000.0;
pos.x *= perspective;
pos.y *= perspective;
float delta = length(offsetPos.xy - prevOffsetPos.xy);
float maxDelta = 2.7;
v_index = floor(pow(clamp(delta, 0.0, maxDelta) / maxDelta, 5.0) * 15.99);
v_rotation = atan((offsetPos.x - prevOffsetPos.x) / (offsetPos.y - prevOffsetPos.y));
pos.x *= 2.0 / u_resolution.x;
pos.y *= 2.0 / u_resolution.y;
pos.z = 0.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = 24.0 * perspective;
v_alpha = perspective;
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D u_texture;
varying float v_rotation;
varying float v_index;
varying float v_alpha;
void main() {
vec2 coord = gl_PointCoord.xy;
coord = vec2(
clamp(cos(v_rotation) * (coord.x - 0.5) + sin(v_rotation) * (coord.y - 0.5) + 0.5, 0.0, 1.0),
clamp(cos(v_rotation) * (coord.y - 0.5) - sin(v_rotation) * (coord.x - 0.5) + 0.5, 0.0, 1.0)
);
float index = floor(v_index + 0.5);
coord.y = - coord.y + 4.0;
coord.x += (index - floor(index / 4.0) * 4.0);
coord.y -= floor(index / 4.0);
coord *= 0.25;
vec4 color = texture2D(u_texture, coord);
color.a *= v_alpha;
gl_FragColor = color;
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.js"></script>
http://blog.edankwan.com/post/my-first-christmas-experiment。
答案 0 :(得分:3)
在摘要代码中,您在更新循环和顶点着色器中对变量speed
的处理不同。
uniforms.u_time.value += conf.speed * 0.003
float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);
如果您在着色器代码中将u_speed
更改为u_speed * 0.003
(或者最好将该乘法移动到javascript中的定义),您将获得理想的结果。
调试此类事情的最快方法-将值传递给输出颜色,并检查其是否符合您的期望。
=================
如果某人想要制作 非平坦曲率的尾巴 ,则可以存储每个粒子路径的最后N个点。然后,您可以在CPU上完全计算尾迹网格几何并将其流式传输到GPU。
另一种方式:您可以将所有路径上传到单个“统一缓冲区对象”,并找到要用pointId
和uv
的尾网格顶点提取的正确点。