使用实例化,我无法更改单个子几何体的 transparency/opacity
With Instancing, I am not able to change the transparency/opacity of the individual child geometries
我有一个由 1000 个球体实例组成的简单模型。我正在尝试使用实例化来减少绘制调用的次数。但是,我无法更改单个子几何图形的 transparency/opacity。
我已经尝试过以下方法:
我可以使用
改变每个球体的透明度
material.fragmentShader = "varying vec3 vColor;void main() { gl_FragColor = vec4( vColor, 0.2 );}";
但是,这会将每个球体的不透明度更改为 0.2。
html 文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>A-Frame Instancing component</title>
<meta name="description" content="A-Frame Instancing component">
<script>
/*
var WebVRConfig = {
FORCE_ENABLE_VR: true,
BUFFER_SCALE: 1.0
};
*/
</script>
<script src="https://cdn.rawgit.com/aframevr/aframe/v0.4.0/dist/aframe-master.min.js"></script>
<script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v3.2.0/dist/aframe-extras.min.js"></script>
<script type="text/javascript" src="build/aframe-instancing.js"></script>
</head>
<body>
<a-scene stats>
<a-assets>
<img id="sky" src="https://cdn.rawgit.com/aframevr/aframe/master/examples/primitives/models/peach-gradient.jpg">
</a-assets>
<a-entity instancing="count:100"></a-entity>
<a-sky src="#sky"></a-sky>
<a-entity light="type:directional;color:#FFFFFF" position="-1 1 1"></a-entity>
</a-scene>
</body>
</html>
实现实例化的函数:
AFRAME.registerComponent('instancing', {
schema: {
count: {type: 'int', default: 10000}
},
var geometry = new THREE.InstancedBufferGeometry();
geometry.copy(new THREE.SphereBufferGeometry(5.0));
var translateArray = new Float32Array(count*3);
var vectorArray = new Float32Array(count*3);
var colorArray = new Float32Array(count*3);
geometry.addAttribute('translate', new THREE.InstancedBufferAttribute(translateArray, 3, 1));
geometry.addAttribute('vector', new THREE.InstancedBufferAttribute(vectorArray, 3, 1));
geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1));
var material = new THREE.ShaderMaterial({
uniforms: {
time: {value: 0}
},
vertexShader: [
'attribute vec3 translate;',
'attribute vec3 vector;',
'attribute vec3 color;',
'uniform float time;',
'varying vec3 vColor;',
'const float g = 9.8 * 1.5;',
'void main() {',
' vec3 offset;',
' offset.xz = vector.xz * time;',
' offset.y = vector.y * time - 0.5 * g * time * time;',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position + translate + offset, 1.0 );',
' vColor = color;',
'}'
].join('\n'),
fragmentShader: [
'varying vec3 vColor;',
'void main() {',
' gl_FragColor = vec4( vColor, 1 );',
'}'
].join('\n')
});
var mesh = new THREE.Mesh(geometry, material);
this.model = mesh;
el.setObject3D('mesh', mesh);
el.emit('model-loaded', {format:'mesh', model: mesh});
//try to change opacity here
material.fragmentShader = "varying vec3 vColor;void main() { gl_FragColor = vec4( vColor, 0.2 );}";
material.transparent = true;
//use the new opacity
var mesh1 = new THREE.Mesh(geometry1, material);
this.mesh = mesh1;
el.setObject3D('mesh', mesh1);
el.emit('model-loaded', {format:'mesh', model: mesh1});
}
});
}
]);
谁能告诉我,如何只改变一个球体的不透明度?提前致谢!
此外,假设我正在尝试复制多个盒子。
其中之一如下:
<a-box position="19.0 1.5 23.0"
width="32.0"
height="1.0"
depth="40.0"
color="#969696"
shader="flat"
flat-shading="true">
</a-box>
我将在 translateArray 和 vectorArray 中填写什么值?
非常感谢!
您的颜色只是 RGB
值,而不是 RGBA
。更新您的 color
属性以支持 4 个值,并将关联的 vec3
引用更改为使用 vec4
。向量中的最后一个值将是您的 alpha
(透明度)值。
看来您已经知道如何将 vertex shader
中的值发送到 fragment shader
,所以我不会在那里详细介绍。但是在你的fragment shader
中,你可以直接使用颜色,因为gl_FragColor
期望设置为vec4
。
进一步说明:
当您创建 InstancedBufferAttribute
时,您会为每个实例创建一个属性 。因此,您的 color
属性目前仅包含每个实例的 RGB
值。
硬编码 1
或 0.2
在 w
位置(即 gl_FragColor = vec4( vColor, 1 );
),您将它普遍应用于所有实例。因此,您需要在每个实例的基础上定义 alpha
值,最简单的方法是通过您已经创建和实例化的 color
属性。
//geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1)
geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 4, 1)
上面的代码为您应该为每个球体提供的 alpha 值留出空间。您的 colorArray
将包含 [ R, G, B, A, R, G, B, A, ... ]
.
等数据
然后,在你的着色器中...
// vertex shader
// ...
attribute vec4 color;
varying vec4 vColor;
// ...
void main(){
// ...
vColor = color;
// ...
}
// fragment shader
// ...
varying vec4 vColor;
// ...
void main(){
// ...
gl_FragColor = vColor;
}
现在,您为每个球体实例提供的 alpha 值将仅用于该实例。例如,如果您希望索引 1 处的球体是唯一透明的球体,您的 colorArray
缓冲区应如下所示:
colorArray = [
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 0.5,
1.0, 1.0, 1.0, 1.0,
// ...
];`
重要警告
此实现不会对实例进行深度排序,因此混合将取决于渲染顺序。您可以在以下问题中阅读更多相关信息:
我有一个由 1000 个球体实例组成的简单模型。我正在尝试使用实例化来减少绘制调用的次数。但是,我无法更改单个子几何图形的 transparency/opacity。
我已经尝试过以下方法:
我可以使用
改变每个球体的透明度material.fragmentShader = "varying vec3 vColor;void main() { gl_FragColor = vec4( vColor, 0.2 );}";
但是,这会将每个球体的不透明度更改为 0.2。
html 文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>A-Frame Instancing component</title>
<meta name="description" content="A-Frame Instancing component">
<script>
/*
var WebVRConfig = {
FORCE_ENABLE_VR: true,
BUFFER_SCALE: 1.0
};
*/
</script>
<script src="https://cdn.rawgit.com/aframevr/aframe/v0.4.0/dist/aframe-master.min.js"></script>
<script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v3.2.0/dist/aframe-extras.min.js"></script>
<script type="text/javascript" src="build/aframe-instancing.js"></script>
</head>
<body>
<a-scene stats>
<a-assets>
<img id="sky" src="https://cdn.rawgit.com/aframevr/aframe/master/examples/primitives/models/peach-gradient.jpg">
</a-assets>
<a-entity instancing="count:100"></a-entity>
<a-sky src="#sky"></a-sky>
<a-entity light="type:directional;color:#FFFFFF" position="-1 1 1"></a-entity>
</a-scene>
</body>
</html>
实现实例化的函数:
AFRAME.registerComponent('instancing', {
schema: {
count: {type: 'int', default: 10000}
},
var geometry = new THREE.InstancedBufferGeometry();
geometry.copy(new THREE.SphereBufferGeometry(5.0));
var translateArray = new Float32Array(count*3);
var vectorArray = new Float32Array(count*3);
var colorArray = new Float32Array(count*3);
geometry.addAttribute('translate', new THREE.InstancedBufferAttribute(translateArray, 3, 1));
geometry.addAttribute('vector', new THREE.InstancedBufferAttribute(vectorArray, 3, 1));
geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1));
var material = new THREE.ShaderMaterial({
uniforms: {
time: {value: 0}
},
vertexShader: [
'attribute vec3 translate;',
'attribute vec3 vector;',
'attribute vec3 color;',
'uniform float time;',
'varying vec3 vColor;',
'const float g = 9.8 * 1.5;',
'void main() {',
' vec3 offset;',
' offset.xz = vector.xz * time;',
' offset.y = vector.y * time - 0.5 * g * time * time;',
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position + translate + offset, 1.0 );',
' vColor = color;',
'}'
].join('\n'),
fragmentShader: [
'varying vec3 vColor;',
'void main() {',
' gl_FragColor = vec4( vColor, 1 );',
'}'
].join('\n')
});
var mesh = new THREE.Mesh(geometry, material);
this.model = mesh;
el.setObject3D('mesh', mesh);
el.emit('model-loaded', {format:'mesh', model: mesh});
//try to change opacity here
material.fragmentShader = "varying vec3 vColor;void main() { gl_FragColor = vec4( vColor, 0.2 );}";
material.transparent = true;
//use the new opacity
var mesh1 = new THREE.Mesh(geometry1, material);
this.mesh = mesh1;
el.setObject3D('mesh', mesh1);
el.emit('model-loaded', {format:'mesh', model: mesh1});
}
});
}
]);
谁能告诉我,如何只改变一个球体的不透明度?提前致谢!
此外,假设我正在尝试复制多个盒子。 其中之一如下:
<a-box position="19.0 1.5 23.0"
width="32.0"
height="1.0"
depth="40.0"
color="#969696"
shader="flat"
flat-shading="true">
</a-box>
我将在 translateArray 和 vectorArray 中填写什么值? 非常感谢!
您的颜色只是 RGB
值,而不是 RGBA
。更新您的 color
属性以支持 4 个值,并将关联的 vec3
引用更改为使用 vec4
。向量中的最后一个值将是您的 alpha
(透明度)值。
看来您已经知道如何将 vertex shader
中的值发送到 fragment shader
,所以我不会在那里详细介绍。但是在你的fragment shader
中,你可以直接使用颜色,因为gl_FragColor
期望设置为vec4
。
进一步说明:
当您创建 InstancedBufferAttribute
时,您会为每个实例创建一个属性 。因此,您的 color
属性目前仅包含每个实例的 RGB
值。
硬编码 1
或 0.2
在 w
位置(即 gl_FragColor = vec4( vColor, 1 );
),您将它普遍应用于所有实例。因此,您需要在每个实例的基础上定义 alpha
值,最简单的方法是通过您已经创建和实例化的 color
属性。
//geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1)
geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 4, 1)
上面的代码为您应该为每个球体提供的 alpha 值留出空间。您的 colorArray
将包含 [ R, G, B, A, R, G, B, A, ... ]
.
然后,在你的着色器中...
// vertex shader
// ...
attribute vec4 color;
varying vec4 vColor;
// ...
void main(){
// ...
vColor = color;
// ...
}
// fragment shader
// ...
varying vec4 vColor;
// ...
void main(){
// ...
gl_FragColor = vColor;
}
现在,您为每个球体实例提供的 alpha 值将仅用于该实例。例如,如果您希望索引 1 处的球体是唯一透明的球体,您的 colorArray
缓冲区应如下所示:
colorArray = [
1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 0.5,
1.0, 1.0, 1.0, 1.0,
// ...
];`
重要警告
此实现不会对实例进行深度排序,因此混合将取决于渲染顺序。您可以在以下问题中阅读更多相关信息: