threejs ShaderMaterial 使用 vertexAlphas

146 阅读1分钟

定义Material

class ColorMaterial extends ShaderMaterial {

  constructor(params: { u_mvpMatrix: Matrix4, u_color: Vector4 }) {
    super();

    this.vertexShader = VERTEX_SHADER_SOURCE;
    this.fragmentShader = FRAGMENT_SHADER_SOURCE;
    this.vertexColors = true; // 要使用顶点着色器定义顶点颜色
    this.uniforms = {
      u_mvpMatrix: {
        value: params.u_mvpMatrix
      },
      u_color: {
        value: params.u_color
      }
    }
  }
}

在定义ShaderMaterial 的时候要指定 vertexColors = true; 这样threejs 会在顶点着色器中定义一个 vec3 color/ vec4 color 属性,具体定义成vec3, 还是vec4 就由你定义的值有关;通过下面讲解

定义BufferGeometry

  const cube = createCubeVertices(2)

  const faceColors: number[][] = [
    [1, 0, 0, 1],
    [0, 1, 0, 1],
    [1, 1, 0, 1],
    [0, 0, 1, 1],
    [1, 0, 1, 1],
    [0, 1, 1, 1],
  ]
  var colorVerts: number[] = [];
  for (var f = 0; f < 6; ++f) {
    for (var v = 0; v < 4; ++v) {
      colorVerts = colorVerts.concat(faceColors[f]);
    }
  }

  const buffer = new BufferGeometry();
  const positions = new Float32BufferAttribute(cube.position.array, 3)
  const colors = new Float32BufferAttribute(colorVerts, 4);

  buffer.setAttribute('position', positions);
  buffer.setAttribute('color', colors);
  buffer.setIndex([...cube.indices.array]);

在上面我们在BufferGeometry 中定义的color 属性是一个 vec4 变量,在合建程序对象的时候,threejs 会先生成 一个程序对象的配置参数

vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
                        

判断当前材质有没有定义 vertexColors,然后才根据属性的数量来决定vertexAlphas 的值。 这个值将决定着色器模块的内容。 下面是在生成着色器前的宏定义

parameters.vertexAlphas ? '#define USE_COLOR_ALPHA' : '',

可以看到 vertexAlphas 如果存在 就会增加一个宏定义,这个宏定义又直接影响了着色器中color 属性的类型;下面是定义着色器的代码

'#if defined( USE_COLOR_ALPHA )',

'	attribute vec4 color;',

'#elif defined( USE_COLOR )',

'	attribute vec3 color;',

'#endif',

综上可知,

  1. 在ShaderMaterial 中设置vertexColors = true
  2. 在定义BufferGeometry 的时候 将color值定义为一个vec4 的量

这样 着色器中就能使用alpha 值了。