# 效果

几何数据 提供了渲染的原材料,材质 决定了渲染的方式,但在讨论材质之前,我们要讨论一下其基于的效果 Effect

效果可以认为是一个材质模板,通过光照模式lightMode宏定义definition来对模板的各个功能进行开关。

# 内置效果

详见 内置效果资源

# 定制一个效果

function createSimpleEffect (scene: XRFrame.Scene) {
  return scene.createEffect({
    name: 'simple',
    properties: [
      {
        key: 'u_baseColorFactor',
        type: xrFrameSystem.EUniformType.FLOAT4,
        default: [1, 1, 1, 1]
      }
    ],
    images: [
      {
        key: 'u_baseColorMap',
        default: 'white',
        macro: 'WX_USE_BASECOLORMAP'
      }
    ],
    // 透明物体需要大于`2500`!
    defaultRenderQueue: 2000,
    passes: [
      {
        renderStates: {
          cullOn: true,
          blendOn: false,
          depthWrite: true,
          cullFace: xrFrameSystem.ECullMode.BACK,
        },
        lightMode: 'ForwardBase',
        useMaterialRenderStates: true,
        shaders: [0, 1]
      }
    ],
    shaders: [`#version 100

    attribute vec3 a_position;
    attribute highp vec2 a_texCoord;

    uniform mat4 u_view;
    uniform mat4 u_projection;
    uniform mat4 u_world;
  
    varying highp vec2 v_uv;
    
    void main()
    {
      v_uv = a_texCoord;
      gl_Position = u_projection * u_view * u_world * vec4(a_position, 1.);
    }`,
      `#version 100
    precision mediump float;

    uniform highp vec4 u_baseColorFactor;
    #ifdef WX_USE_BASECOLORMAP
      uniform sampler2D u_baseColorMap;
    #endif

    varying highp vec2 v_uv;

    void main()
    {
  #ifdef WX_USE_BASECOLORMAP
      vec4 baseColor = texture2D(u_baseColorMap, v_Uv) * u_baseColorFactor;
  #else
      vec4 baseColor = u_baseColorFactor;
  #endif

      gl_FragData[0] = baseColor;
    }  
      `],
  });
}

在效果的参数中,首先是其名字name,然后是其能允许的属性propertiesimages

# 定义属性

属性对应后续生成材质的uniforms的定义。每个property都需要一个键key、类型type和对应于类型的默认值,而每个image则不需要type、默认值也是已经注册到了资源系统的纹理的资源id

这里特别要注意在那个marco参数,它定义了当用户修改设置(通过材质的接口)了这个属性后,将会开启的宏,这个宏会直接应用到着色器中。

注意,所有的外部设置的宏都必须以WX_开头 为了让整个渲染正常运作,框架内置了一些属性和宏,可见文章末尾的附录。

# 渲染队列

defaultRenderQueue定义的渲染队列,决定了渲染顺序,将在下一章材质中详细论述。

透明物体需要大于2500

# 配置Pass

Pass对应的是使用了基于这个效果的材质的网格的一次渲染,这个和相机组件相关,使用哪个pass渲染取决于相机当次绘制指定的lightMode

lightMode是光照模式,目前建议只能使用一个模式ForwardBase。当存在多个pass都使用了同一个光照模式时,将会按顺序将网格渲染多次。

renderStates顾名思义即渲染状态,渲染状态直接对应底层图形API都会提供的一系列概念,比如混合blend、深度depthTest等,比如示例里就定义了blendOn: false,即表明要关掉混合

更多的渲染状态可见API文档IRenderStates,这里不赘述,这里主要要说明一个规则,即useMaterialRenderStates这个参数的作用。

xr-frame框架的设计中,渲染状态是由效果决定默认值,材质决定最终值的,而useMaterialRenderStates则就是用于决定材质是否能够覆盖效果默认值的,如果为false,则总是使用效果提供的默认值,如果为true,则由下面会讲到材质的渲染状态的规则来决定。

在配置完这些之后,就是要定制shaders了。这是一个有两个数字的数组,分别指定了顶点着色器片段着色器在顶层参数中的shaders的索引。

# 编写着色器

效果配置的顶层参数中最后一项是shaders,这是一个字符串数组,每个元素都是一个完整的着色器。着色器使用标准的glsl1语法,这个不属于教程范畴不再赘述。

我们提供了一些内置可用的着色器的函数,在文章末尾会给出。

# 注册到资源系统

将效果注册到资源系统可用:

xrFrameSystem.registerEffect('custom', createSimpleEffect);

注册后在schema中类型指定为effect的数据,便可以使用custom这个资源id引用到创建的资源了。