bind method

  1. @override
void bind(
  1. RenderPass pass,
  2. TransientWriter transientsBuffer,
  3. Matrix4 modelTransform,
  4. Matrix4 cameraTransform,
  5. Vector3 cameraPosition, {
  6. Shader? shaderOverride,
})
override

Binds vertex/index buffers and per-frame uniforms onto pass in preparation for a draw call.

Implementations write the model and camera transforms (and any subclass-specific values, like the joints texture for skinned geometry) into the supplied transient buffer and bind the resulting uniform views.

shaderOverride is the vertex shader the pipeline actually runs when it differs from this geometry's default vertexShader (a custom material's generated vertex variant). The per-frame uniforms (FrameInfo, the joints texture) must be bound against that shader's slots, since a variant can place its uniform blocks at different binding points.

Implementation

@override
void bind(
  gpu.RenderPass pass,
  TransientWriter transientsBuffer,
  vm.Matrix4 modelTransform,
  vm.Matrix4 cameraTransform,
  vm.Vector3 cameraPosition, {
  gpu.Shader? shaderOverride,
}) {
  if (_jointsTexture == null) {
    throw Exception('Joints texture must be set for skinned geometry.');
  }

  // Bind against the shader the pipeline runs (a material's skinned vertex
  // variant when supplied), since its uniform slots can differ.
  final boundShader = shaderOverride ?? vertexShader;

  pass.bindTexture(
    boundShader.getUniformSlot('joints_texture'),
    _jointsTexture!,
    sampler: gpu.SamplerOptions(
      minFilter: gpu.MinMagFilter.nearest,
      magFilter: gpu.MinMagFilter.nearest,
      mipFilter: gpu.MipFilter.nearest,
      widthAddressMode: gpu.SamplerAddressMode.clampToEdge,
      heightAddressMode: gpu.SamplerAddressMode.clampToEdge,
    ),
  );

  bindGeometryBuffers(pass);

  // Skinned vertex UBO. The model transform is identity on purpose:
  // the joint matrices from Skin.getJointsTexture are already full
  // global transforms (including the scene-root flip), so the shader
  // applies them directly. Passing the mesh node's own transform here
  // would double-apply it (and glTF requires a skinned mesh node's
  // transform to be ignored). `modelTransform` is unused for skinned
  // geometry as a result.
  final identityTransform = vm.Matrix4.identity();
  final frameInfoSlot = boundShader.getUniformSlot('FrameInfo');
  final frameInfoFloats = Float32List.fromList([
    identityTransform.storage[0],
    identityTransform.storage[1],
    identityTransform.storage[2],
    identityTransform.storage[3],
    identityTransform.storage[4],
    identityTransform.storage[5],
    identityTransform.storage[6],
    identityTransform.storage[7],
    identityTransform.storage[8],
    identityTransform.storage[9],
    identityTransform.storage[10],
    identityTransform.storage[11],
    identityTransform.storage[12],
    identityTransform.storage[13],
    identityTransform.storage[14],
    identityTransform.storage[15],
    cameraTransform.storage[0],
    cameraTransform.storage[1],
    cameraTransform.storage[2],
    cameraTransform.storage[3],
    cameraTransform.storage[4],
    cameraTransform.storage[5],
    cameraTransform.storage[6],
    cameraTransform.storage[7],
    cameraTransform.storage[8],
    cameraTransform.storage[9],
    cameraTransform.storage[10],
    cameraTransform.storage[11],
    cameraTransform.storage[12],
    cameraTransform.storage[13],
    cameraTransform.storage[14],
    cameraTransform.storage[15],
    cameraPosition.x,
    cameraPosition.y,
    cameraPosition.z,
    _jointsTexture != null ? 1 : 0,
    _jointsTexture != null ? _jointsTextureWidth.toDouble() : 1.0,
  ]);
  final frameInfoView = transientsBuffer.emplace(
    frameInfoFloats.buffer.asByteData(),
  );
  pass.bindUniform(frameInfoSlot, frameInfoView);
}