我正在做一个展示建筑物的项目。的要求是根据相机与建筑物之间的距离让建筑物逐渐淡出(透明),也必须跟随摄像机的运动。
我考虑使用THREE.Fog()
,但雾似乎只能改变材质的颜色。
上面是一张有白色雾的建筑物的照片。
var bigGeometry = new THREE.Geometry(); bigGeometry.merge(smallGeometry);
将所有的建筑物合并成一个)。ground.material.fog = false;
。所以地面不会与雾相互作用。我的问题是:
alphaMap
。如果是这样的话,每个建筑瓷砖必须映射一个alphaMap和所有这些alphaMap必须与相机的运动互动。这将是一项艰巨的工作。有什么建议吗?
向你问好,亚瑟
发布于 2018-09-25 20:32:57
我就是行动。花了一些时间阅读如何使用Three.js的着色材料。我得到了一些按需要工作的代码。
下面是代码:https://jsfiddle.net/yingcai/4dxnysvq/
其基本思想是:
另一件重要的事情是:因为淡出面罩应该跟随摄像机的移动,所以不要忘记更新制服中的每一帧的控件。
// Create uniforms that contains control position value.
uniforms = {
texture: {
value: new THREE.TextureLoader().load("https://threejs.org/examples/textures/water.jpg")
},
control: {
value: controls.target
}
};
// In the render() method.
// Update the uniforms value every frame.
uniforms.control.value = controls.target;
发布于 2018-09-21 01:51:22
注意:我怀疑可能有比不透明更容易/更漂亮的方法来解决这个问题。特别要注意的是,部分不透明的建筑物会显示出它们后面的其他建筑物.要解决这个问题,请考虑使用渐变或其他场景背景,并选择与之匹配的雾色,而不是使用不透明度。但为了尝试..。
下面是如何根据一个物体的距离来改变它的不透明度。这实际上不需要THREE.Fog
,我不知道您将如何直接使用fog数据。相反,我将使用THREE.NodeMaterial
,它(就three.js r96而言)是相当实验性的。另一种选择是用THREE.ShaderMaterial
编写一个自定义着色器,这也很好。
const material = new THREE.StandardNodeMaterial();
material.transparent = true;
material.color = new THREE.ColorNode( 0xeeeeee );
// Calculate alpha of each fragment roughly as:
// alpha = 1.0 - saturate( distance / cutoff )
//
// Technically this is distance from the origin, for the demo, but
// distance from a custom THREE.Vector3Node would work just as well.
const distance = new THREE.Math2Node(
new THREE.PositionNode( THREE.PositionNode.WORLD ),
new THREE.PositionNode( THREE.PositionNode.WORLD ),
THREE.Math2Node.DOT
);
const normalizedDistance = new THREE.Math1Node(
new THREE.OperatorNode(
distance,
new THREE.FloatNode( 50 * 50 ),
THREE.OperatorNode.DIV
),
THREE.Math1Node.SAT
);
material.alpha = new THREE.OperatorNode(
new THREE.FloatNode( 1.0 ),
normalizedDistance,
THREE.OperatorNode.SUB
);
演示:https://jsfiddle.net/donmccurdy/1L4s9e0c/
截图:
发布于 2022-06-14 20:09:55
几年后,我也遇到了同样的问题,我用.onBeforeCompile函数解决了这个问题,这个函数可能更方便使用。有一个很好的教程这里
代码本身是简单的,可以很容易地更改为其他材料。它只使用fogFactor作为材料中的α值。
这里的物质功能:
alphaFog() {
const material = new THREE.MeshPhysicalMaterial();
material.onBeforeCompile = function (shader) {
const alphaFog =
`
#ifdef USE_FOG
#ifdef FOG_EXP2
float fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );
#else
float fogFactor = smoothstep( fogNear, fogFar, vFogDepth );
#endif
gl_FragColor.a = saturate(1.0 - fogFactor);
#endif
`
shader.fragmentShader = shader.fragmentShader.replace(
'#include <fog_fragment>', alphaFog
);
material.userData.shader = shader;
};
material.transparent = true
return material;
}
然后你就可以像
const cube = new THREE.Mesh(geometry, this.alphaFog());
https://stackoverflow.com/questions/52425575
复制相似问题