具有 threejs 材质的着色器在帧中不起作用



我正在尝试通过自定义着色器为在组件中创建的实体添加波浪,但添加着色器后场景立即消失。如果我删除着色器,实体将显示为静态实体。

控制台不会抛出任何错误,所以我不确定出了什么问题

这是一个代码笔:代码笔

如果删除材料属性,将显示实体。

<script>
AFRAME.registerComponent('waves', {
init: function() {
var texture = new THREE.TextureLoader().load( "https://cinemont.com/tutorials/zelda/water.png" );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(5, 5);
this.geometry = new THREE.PlaneBufferGeometry( 4000, 2000, 128, 64 ); 
this.material = new THREE.MeshPhongMaterial({
map:texture,
color: 0xffffff,
opacity: 1,
blending: THREE.NoBlending,
side: THREE.DoubleSide,
transparent: false,
depthTest: false,
wireframe: false 
});
var plane = new THREE.Mesh(this.geometry, this.material);
plane.position.set(0, -400, -300);
plane.rotation.set(Math.PI / 2, 0, 0);
var el = this.el;
el.setObject3D('mesh', plane);
}
});
</script>
<script>
AFRAME.registerShader('makewaves', {
schema: {
color: {type: 'color', is: 'uniform', default: '#0051da'},
timeMsec: {type: 'time', is: 'uniform'}
},
vertexShader: `
#define SCALE 10.0
varying vec2 vUv;
uniform float timeMsec;  
float calculateSurface(float x, float z) {
float uTime = timeMsec / 1000.0;
float y = 0.0;
y += (sin(x * 1.0 / SCALE + uTime * 1.0) + sin(x * 2.3 / SCALE + uTime * 1.5) + sin(x * 3.3 / SCALE + uTime * 0.4)) / 3.0;
y += (sin(z * 0.2 / SCALE + uTime * 1.8) + sin(z * 1.8 / SCALE + uTime * 1.8) + sin(z * 2.8 / SCALE + uTime * 0.8)) / 3.0;
return y;
}
void main() {
float uTime = timeMsec / 1000.0;
vUv = uv;
vec3 pos = position;    
float strength = 1.0;
pos.y += strength * calculateSurface(pos.x, pos.z);
pos.y -= strength * calculateSurface(0.0, 0.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}  
`,
fragmentShader: `
varying vec2 vUv;
uniform sampler2D uMap;
uniform vec3 color;
uniform float timeMsec; 
void main() {
float uTime = timeMsec / 1000.0;     
vec2 uv = vUv * 10.0 + vec2(uTime * -0.05);
uv.y += 0.01 * (sin(uv.x * 3.5 + uTime * 0.35) + sin(uv.x * 4.8 + uTime * 1.05) + sin(uv.x * 7.3 + uTime * 0.45)) / 3.0;
uv.x += 0.12 * (sin(uv.y * 4.0 + uTime * 0.5) + sin(uv.y * 6.8 + uTime * 0.75) + sin(uv.y * 11.3 + uTime * 0.2)) / 3.0;
uv.y += 0.12 * (sin(uv.x * 4.2 + uTime * 0.64) + sin(uv.x * 6.3 + uTime * 1.65) + sin(uv.x * 8.2 + uTime * 0.45)) / 3.0;
vec4 tex1 = texture2D(uMap, uv * 1.0);
vec4 tex2 = texture2D(uMap, uv * 1.0 + vec2(0.2));
vec3 blue = color;
gl_FragColor = vec4(blue + vec3(tex1.a * 0.9 - tex2.a * 0.02), 1.0);
}`
});
</script>
<a-scene>
<a-camera postion="0 1.2 0"></a-camera>     
<a-entity material="shader:makewaves;" 
waves></a-entity>
<a-entity light="type: directional; color: #ffffff; intensity: 2.8; castShadow:true;" position="0 2 -10"></a-entity>
<a-light type="point" color="blue" position="0 5 0"></a-light>
<a-light type="directional" color="blue" intensity="1.8" position="0 5 0"></a-light> 
</a-scene>

这里的问题是应用材质中的着色器不提供贴图均匀/纹理值。

另一方面,您尝试创建两次材质:

1( 首先使用a-framematerial组件创建材料
2( 然后在waves组件内创建一个新几何体 + 一个新材料(具有不正确的 THREE 材料类型(。 您需要让a-frame处理大部分工作,或者完全在 THREE.js 中创建网格(几何体 + 材质(。

阿frame 这里
没有那么多要补充的。着色器不会为纹理公开任何统一,因此在registerShader内部需要将其添加到架构中:

AFRAME.registerShader('makewaves', {
schema: {
......,
uMap: {
type: 'map',
is: 'uniform'
}
}, .....

并像这样使用着色器:

<a-plane postion="1 1.2 2" width="5" height="5" rotation="-90 0 90" material="shader:makewaves; 
uMap: https://cinemont.com/tutorials/zelda/water.png;"></a-plane>

然后a-frame将使用顶点着色器和片段着色器创建一个新的着色器。 这里的例子。


此外,根据@ngoKevin的 anwser,向默认平面添加更多段将允许更多顶点随着"波浪"运动移动。
segments-height="20" segments-width="20"

在这里摆弄。


要使用自定义着色器,您需要使用 THREE。着色器材质:

THREE.ShaderMaterial({
fragmentShader: this.fragmentShader, // custom fragment shader
vertexShader: this.vertexShader, // custom vertex shader
......

这是一种旨在与自定义着色器一起使用的 THREE 材质。

在这里查看。

您还需要在a-planesegments-height="20" segments-width="20"以为其提供要替换的顶点。默认平面仅在拐角处有顶点,因此不会得到波浪。

https://codepen.io/anon/pen/MPoBKz?editors=1000

最新更新