bind method

  1. @override
void bind(
  1. RenderPass pass,
  2. TransientWriter transientsBuffer,
  3. Lighting lighting
)
override

Binds this material's render-pass state, uniforms, and textures.

The base implementation enables back-face culling with counter-clockwise winding (matching the glTF convention). Subclasses must call super.bind and then bind any per-material uniforms and textures expected by their fragment shader. lighting carries the IBL EnvironmentMap (and its intensity) plus the analytic lights and shadow resources that materials shade against.

Implementation

@override
void bind(
  gpu.RenderPass pass,
  TransientWriter transientsBuffer,
  Lighting lighting,
) {
  pass.setCullMode(renderCullMode);
  pass.setWindingOrder(gpu.WindingOrder.counterClockwise);

  if (shadingModel == FmatShadingModel.lit) {
    final env = environment ?? lighting.environmentMap;
    final fragInfo = Float32List(EngineLightingUniforms.fragInfoFloatCount);
    EngineLightingUniforms.packInto(fragInfo, lighting, env);
    // radiance_blend.zw [162]/[163]: this item's punctual-light slice
    // (count, offset) into the per-frame light-index buffer.
    fragInfo[162] = lightListCount.toDouble();
    fragInfo[163] = lightListOffset.toDouble();
    pass.bindUniform(
      fragmentShader.getUniformSlot('FragInfo'),
      transientsBuffer.emplace(ByteData.sublistView(fragInfo)),
    );
    EngineLightingUniforms.bindEngineTextures(
      pass,
      fragmentShader,
      lighting,
      env,
    );
    if (_sceneInputs.isNotEmpty) {
      EngineLightingUniforms.bindSceneInputTextures(
        pass,
        fragmentShader,
        lighting,
        _sceneInputs,
      );
    }
    // Lit `.fmat` shaders include the lighting framework (and thus fog.glsl),
    // so they carry the FogInfo block. Unlit `.fmat` shaders do not; fog on
    // those is a TODO(fog): give the unlit `.fmat` template the fog block.
    EngineLightingUniforms.bindFog(
      pass,
      fragmentShader,
      transientsBuffer,
      lighting,
    );
  }

  parameters.bind(pass, fragmentShader, transientsBuffer);
  // Bind the fragment keep-alive block (name matches kFragmentKeepAliveBlock
  // in the emitter) to zero. The generated fragment references every
  // declared parameter resource through it (the MaterialParams block and
  // any unreferenced samplers) so none can be optimized out; the emitter
  // declares it whenever the material has any parameter.
  if (parameters.hasAnyParameters) {
    pass.bindUniform(
      fragmentShader.getUniformSlot('FragmentKeepAlive'),
      transientsBuffer.emplace(_zeroKeepAlive),
    );
  }
}