A-Frame中文教程

材质(material)

材质组件为实体提供外观。我们可以定义颜色、不透明度或纹理等属性。这通常和提供外形的 几何体组件一起工作。

我们可以注册自定义材质来扩展材质组件,以提供广泛的视觉效果。

目录

例子

使用默认标准材质定义红色材质:

<a-entity geometry="primitive: box" material="color: red"></a-entity>

下面是使用不同材质的示例:

<a-entity geometry="primitive: box" material="shader: flat; color: red"></a-entity>

下面是使用自定义材质的示例:

<a-entity geometry="primitive: plane"
material="shader: ocean; color: blue; wave-height: 10"></a-entity>

属性

材质组件具有一些基本特性。根据应用的材质类型,可以使用更多特性。

属性 描述 默认值
depthTest 渲染材质时是否启用深度测试。 true
flatShading 是否使用 THREE.FlatShading而非 THREE.StandardShading. false
opacity 透明度。如果 transparent属性没有被设置为 true,那么材质将保持为不透明而 opacity将只影响颜色。 1.0
transparent 材料是否透明。透明实体在非透明实体之后呈现。 false
shader 使用哪种材料。默认为 standard material. 可以被设置为 flat material或者一个注册过的自定义材质。 standard
side 要渲染网格的哪些边。可以是 front, back, or double. front
visible 材料是否可见。光线投射器将忽略不可见的材质。 true
offset 要使用的纹理偏移。 {x: 0, y: 0}
repeat 使用纹理重复。 {x: 1, y: 1}
npot 使用非二次方(NPOT)纹理的设置。 false

事件(Events)

事件名称 描述
materialtextureloaded 纹理加载到材质上。
materialvideoloadeddata 视频数据已加载并将播放。
materialvideoended 对于视频纹理,在视频结束时发射(可能无法使用 循环)。

内置材质(Built-in Materials)

A-Frame提供了一些内置材质。

standard

The standard材质是默认材质。它使用基于物理的 THREE.MeshStandardMaterial.

属性

这些特性在基础材料特性之上可用。

属性 描述 默认值
ambientOcclusionMap 环境光遮挡贴图。用于向网格添加阴影。可以是 &lt;img&gt;内联URL。 None
ambientOcclusionMapIntensity 环境光遮挡贴图的强度,介于0和1之间的数字。 1
ambientOcclusionTextureRepeat 环境光遮挡纹理在X和Y方向重复多少次。 1 1
ambientOcclusionTextureOffset 环境光遮挡纹理在x,y方向的偏移。 0 0
color 基础漫反射颜色。 #fff
displacementMap 位移图。用于扭曲网格。可以是&lt;img&gt;内联URL。 None
displacementScale 位移图效果强度。 1
displacementBias 位移图的零点。 0.5
displacementTextureRepeat 置换纹理在X和Y方向重复多少次。 1 1
displacementTextureOffset 置换纹理在x,y方向的偏移。 0 0
height 定义视频纹理时的视频高度(以像素为单位)。 360
envMap 反射的环境立方体贴图纹理。可以选择或以逗号分隔的URL列表。 None
fog 材料是否受 fog所影响。 true
metalness 材料的金属感,从 01 0.5
normalMap 法线贴图。用于添加复杂细节的视觉效果。可以是&lt;img&gt;内联URL。 None
normalScale 法线贴图在X和Y方向上的效果比例。 1 1
normalTextureRepeat 法线纹理在X和Y方向重复多少次。 1 1
normalTextureOffset 法线纹理在x,y方向的偏移。 0 0
repeat 纹理(定义为src)在X和Y方向重复的次数。 1 1
roughness 材质粗糙度,从 01。较粗糙的材料比光滑的材料将反射光散射到更多的方向。 0.5
sphericalEnvMap 反射的环境球形纹理。可以是&lt;img&gt;或内联URL。 None
width 定义视频纹理时的视频宽度(以像素为单位)。 640
wireframe 是否仅渲染几何体框线。 false
wireframeLinewidth 以像素为单位的几何体框线宽度。 2
src 图像或视频纹理贴图。可以是 <img>or <video>,或者一个内联URL。 None

基于物理的着色(Physically-Based Shading)

基于物理的着色是一种着色处理模型,其目的是使材质在灯光条件下具有真实的行为。外观是入射光与材料特性相互作用的结果。

为了达到真实感,漫反射 color, metalness, roughness必须精确控制材料的性质,通常是基于真实的材料研究。有些人已经为不同种类的材料编制了真实感数值图表,我们可以以此为出发点。

例如,对于树皮材料,作为估计,我们可以设置:

<a-entity geometry="primitive: cylinder"
material="src: treebark.png; color: #696969; roughness: 1; metalness: 0">
</a-entity>

畸变图(Distortion Maps)

有三个属性可以给几何体添加高级视觉效果:

环境贴图(Environment Maps)

The envMapsphericalEnvMap属性定义材质所反映的环境。环境反射的清晰度取决于 metalness, 和 roughness属性。

The sphericalEnvMap属性采用单个球形映射纹理。可以分配给 <a-sky>

与纹理不同的是 envMap属性获取一个立方体映射,将六个图像组合在一起形成一个立方体。立方体贴图包围网格并被用作一个纹理。

比如:

<a-scene>
<a-assets>
<a-cubemap id="sky">
<img src="right.png">
<img src="left.png">
<img src="top.png">
<img src="bottom.png">
<img src="front.png">
<img src="back.png">
</a-cubemap>
</a-assets>

<a-entity geometry="primitive: box" material="envMap: #sky; roughness: 0"></a-entity>
</a-scene>

flat

flat使用 THREE.MeshBasicMaterial。平面材质不受场景照明条件的影响。这对图像或视频等东西很有用。设置 shaderflat:

<a-entity geometry="primitive: plane" material="shader: flat; src: #cat-image"></a-entity>

属性

属性 描述 默认值
color 基础漫反射颜色。 #fff
fog 材质是否受 fog所影响。 true
height 定义视频纹理时的视频高度(像素)。 360
repeat 纹理(定义为src)在X和Y方向重复的次数。 1 1
src 图像或视频纹理贴图。可以是 &lt;img&gt;&lt;video&gt;或内联URL。 None
width 定义视频纹理时的视频宽度(像素)。 640
wireframe 是否仅渲染几何体线框。 false
wireframeLinewidth 以像素为单位的几何体框线宽度。 2

贴图(Textures)

若要使用内置材质之一设置纹理,请指定 src属性。 src可以是资产管理系统中的一个 <img>或者 <video>元素的选择器:

<a-scene>
<a-assets>
<img id="my-texture" src="texture.png">
</a-assets>

<a-entity geometry="primitive: box" material="src: #my-texture"></a-entity>
</a-scene>

src也可以是内联URL。请注意,我们没有通过此方法获取浏览器缓存或预加载。

<a-scene>
<a-entity geometry="primitive: box" material="src: url(texture.png)"></a-entity>
</a-scene>

大多数其他属性可以与纹理一起工作。例如 color属性将充当基色,并将每个像素与纹理相乘。设置为 #fff以保持纹理的原始颜色。

A-Frame会缓存纹理而避免把冗余纹理推送到GPU。

视频贴图(Video Textures)

视频纹理后是否循环或自动播放取决于用于创建纹理的视频元素。如果我们只是传递一个URL而不是创建和传递一个视频元素,那么默认情况下纹理将循环并自动播放。否则,请在资产管理系统中创建一个视频元素,并为 id属性(例如, #my-video)传递一个选择器(selector):

<a-scene>
<a-assets>
<!-- No loop. -->
<video id="my-video" src="video.mp4" autoplay="true">
</a-assets>

<a-entity geometry="primitive: box" material="src: #my-video"></a-entity>
</a-scene>

控制视频纹理

要控制视频播放,例如暂停或查找,可以使用video元素来 控制媒体播放。 比如:

var videoEl = document.querySelector('#my-video');
videoEl.currentTime = 122; // Seek to 122 seconds.
videoEl.pause();

如果要传递内联URL,则此操作不起作用。在这种情况下,A-Frame会在内部创建一个视频元素。要获得视频元素的handle,我们应该在 <a-assets>中定义一个。

画布贴图(Canvas Textures)

我们可以用&lt;canvas&gt;作为纹理源。当画布更改时,纹理将自动刷新自身。

<script>
AFRAME.registerComponent('draw-canvas', {
schema: {default: ''},

init: function () {
this.canvas = document.getElementById(this.data);
this.ctx = this.canvas.getContext('2d');

// Draw on canvas...
}
});
</script>

<a-assets>
<canvas id="my-canvas" crossorigin="anonymous"></canvas>
</a-assets>

<a-entity geometry="primitive: plane" material="src: #my-canvas"
draw-canvas="my-canvas"></a-entity>

重复纹理

我们可能希望平铺纹理,而不是让它们拉伸。repeat属性可以用来指示重复纹理。

<a-entity geometry="primitive: plane; width: 100"
material="src: carpet.png; repeat: 100 20"></a-entity>

透明问题

透明度和alpha通道在三维图形中是很棘手的。如果您遇到的问题是,前景中的透明材质不能正确组合到背景中的材质上,那么这些问题可能是由于OpenGL合成器(WebGL是其API)的底层设计造成的

在理想的场景中,A-Frame中的透明性应该没有问题,而不管开发人员将实体放在3D空间的何处,也不管他们在标记中定义元素的顺序如何。可实际情况是我们经常会遇到前景实体遮挡背景实体的场景。这会造成混乱和不必要的视觉缺陷。

若要规避此问题,一种方法是尝试更改HTML中实体的顺序。

注册自定义材料

我们可以使用 AFRAME.registerShader来注册自定义材质的表现和效果。

registerShader

与组件一样,自定义材质具有模式(schema)和生命周期处理程序(lifecycle handler)。

属性 描述
schema 定义着色器所需使用的properties、uniforms、attributes来扩展材质组件。
init 在着色器初始化期间调用一次生命周期处理程序。用于创建材质。
update 在着色器初始化期间和数据更新时调用一次生命周期处理程序。用于更新材质或着色器(shader)。

Schema

我们可以像定义组件属性一样定义材质属性。数据将作为我们用来创建材料的数据:

AFRAME.registerShader('custom', {
schema: {
emissive: {default: '#000'},
wireframe: {default: false}
}
});

要将数据值作为uniforms传递到着色器中,在定义中包含is:'uniform'

AFRAME.registerShader('my-custom', {
schema: {
color: {type:'color', is:'uniform', default:'red'},
opacity: {type:'number', is:'uniform', default:1.0}
},
...