是否可以让 Fog 与 material 的不透明度交互?
Is it possible to let Fog interact with the material's opacity?
我正在做一个显示建筑物的项目。 要求是让建筑物根据摄像机和建筑物之间的距离逐渐淡出(透明)。另外,这个效果必须跟随摄像机的移动。
我考虑使用THREE.Fog()
,但雾似乎只能改变material的颜色。
上图是白雾缭绕的建筑图
- 建筑在瓦片中,每个瓦片都是一个单一的几何体(我将所有建筑物合并为一个)使用
var bigGeometry = new THREE.Geometry();
bigGeometry.merge(smallGeometry);
- purple/blue颜色的东西是地面,
ground.material.fog = false;
。所以地面不会与雾相互作用。
我的问题是:
- 是否可以让雾与建筑物 material 的不透明度而不是颜色相互作用? (越白越透明)
- 或者我应该使用着色器根据到相机的距离来控制 material 的不透明度吗?但是我不知道该怎么做。
- 我也考虑过添加
alphaMap
。如果是这样,每个建筑瓷砖都必须映射一个 alphaMap,并且所有这些 alphaMap 都必须与相机的移动进行交互。这将是大量的工作。
有什么建议吗?
此致,
亚瑟
NOTE: I suspect there are probably easier/prettier ways to solve this than opacity. In particular, note that partially-opaque buildings will show other buildings behind them. To address that, consider using a gradient or some other scene background, and choosing a fog color to match that, rather than using opacity. But for the sake of trying it...
以下是如何根据对象的距离改变对象的不透明度。这实际上并不需要 THREE.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/
截图:
我是OP。在花了一些时间阅读如何使用 Three.js 的着色器后 material。我得到了一些可以正常工作的代码。
代码如下:https://jsfiddle.net/yingcai/4dxnysvq/
基本思路是:
- 创建包含 controls.target(Vector3 位置)的制服。
- 将顶点位置属性传递给顶点着色器中的变化。所以
片段着色器可以访问它。
- 获取每个顶点位置与controls.target之间的距离。根据距离计算 alpha 值。
- 为顶点颜色分配 alpha 值。
另一个重要的事情是:因为淡出遮罩应该跟随相机移动,所以不要忘记每帧更新制服中的控件。
// 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;
我正在做一个显示建筑物的项目。 要求是让建筑物根据摄像机和建筑物之间的距离逐渐淡出(透明)。另外,这个效果必须跟随摄像机的移动。
我考虑使用THREE.Fog()
,但雾似乎只能改变material的颜色。
- 建筑在瓦片中,每个瓦片都是一个单一的几何体(我将所有建筑物合并为一个)使用
var bigGeometry = new THREE.Geometry(); bigGeometry.merge(smallGeometry);
- purple/blue颜色的东西是地面,
ground.material.fog = false;
。所以地面不会与雾相互作用。
我的问题是:
- 是否可以让雾与建筑物 material 的不透明度而不是颜色相互作用? (越白越透明)
- 或者我应该使用着色器根据到相机的距离来控制 material 的不透明度吗?但是我不知道该怎么做。
- 我也考虑过添加
alphaMap
。如果是这样,每个建筑瓷砖都必须映射一个 alphaMap,并且所有这些 alphaMap 都必须与相机的移动进行交互。这将是大量的工作。
有什么建议吗?
此致, 亚瑟
NOTE: I suspect there are probably easier/prettier ways to solve this than opacity. In particular, note that partially-opaque buildings will show other buildings behind them. To address that, consider using a gradient or some other scene background, and choosing a fog color to match that, rather than using opacity. But for the sake of trying it...
以下是如何根据对象的距离改变对象的不透明度。这实际上并不需要 THREE.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/
截图:
我是OP。在花了一些时间阅读如何使用 Three.js 的着色器后 material。我得到了一些可以正常工作的代码。
代码如下:https://jsfiddle.net/yingcai/4dxnysvq/
基本思路是:
- 创建包含 controls.target(Vector3 位置)的制服。
- 将顶点位置属性传递给顶点着色器中的变化。所以 片段着色器可以访问它。
- 获取每个顶点位置与controls.target之间的距离。根据距离计算 alpha 值。
- 为顶点颜色分配 alpha 值。
另一个重要的事情是:因为淡出遮罩应该跟随相机移动,所以不要忘记每帧更新制服中的控件。
// 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;