runAt method
Vector4
runAt(
- int vertexIndex,
- int instanceIndex,
- Float32List a,
- ShaderBindings bindings,
- Float32List out,
The same as CpuVertexShader.run, plus the vertex's and the instance's
own indices.
run must still work — a caller that has no indices, or a rasteriser that has not been taught to pass them, falls back to it — so an implementation answers both and shares whatever it can.
Implementation
@override
Vector4 runAt(
int vertexIndex,
int instanceIndex,
Float32List a,
ShaderBindings bindings,
Float32List out,
) {
final CpuVertexShaderByIndex engine = skinned
? _skinned
: instanced
? _instanced
: lightmapped
? _lightmapped
: _plain;
final clip = engine.runAt(vertexIndex, instanceIndex, a, bindings, out);
final model = bindings.mat4('FrameInfo', 'model');
final mvp = bindings.mat4('FrameInfo', 'mvp');
final world = Vector3(
out[CpuMeshLayout.varyingWorld],
out[CpuMeshLayout.varyingWorld + 1],
out[CpuMeshLayout.varyingWorld + 2],
);
final normal = Vector3(
out[CpuMeshLayout.varyingNormal],
out[CpuMeshLayout.varyingNormal + 1],
out[CpuMeshLayout.varyingNormal + 2],
);
final toMesh = Matrix4.copy(model)..invert();
final position = toMesh.transformed3(world.clone());
final normalRotation = bindings
.mat4('FrameInfo', 'normal_matrix')
.getRotation();
final objectNormal = (normalRotation..invert()).transformed(normal.clone());
final origin = model.getTranslation();
final uniforms = <String, List<double>>{
for (final parameter in program.parameters)
if (parameter.uniform)
parameter.name: ?bindings.read(parameter.block!, parameter.name),
};
final written = evaluateMaterialVertex(
program,
MaterialSurfaceValues(
inputs: <String, List<double>>{
'position': <double>[position.x, position.y, position.z],
'objectNormal': <double>[
objectNormal.x,
objectNormal.y,
objectNormal.z,
],
'world': <double>[world.x, world.y, world.z],
'normal': <double>[normal.x, normal.y, normal.z],
'uv': <double>[
a[CpuMeshLayout.texcoord],
a[CpuMeshLayout.texcoord + 1],
],
'color': lightmapped
? const <double>[1.0, 1.0, 1.0, 1.0]
: <double>[
a[CpuMeshLayout.color],
a[CpuMeshLayout.color + 1],
a[CpuMeshLayout.color + 2],
a[CpuMeshLayout.color + 3],
],
'instance': instanced
? <double>[
for (var i = 0; i < 4; i++)
out[CpuMeshLayout.varyingInstance + i],
]
: const <double>[0.0, 0.0, 0.0, 0.0],
'origin': <double>[origin.x, origin.y, origin.z],
},
uniforms: uniforms,
sample: (_, _, _) =>
throw StateError('a vertex block samples no texture'),
),
);
if (written['normal'] case final n?) {
out
..[CpuMeshLayout.varyingNormal] = n[0]
..[CpuMeshLayout.varyingNormal + 1] = n[1]
..[CpuMeshLayout.varyingNormal + 2] = n[2];
}
if (written['position'] case final p?) {
final local = Vector4(p[0], p[1], p[2], 1.0);
final Vector4 moved = model * local;
out
..[CpuMeshLayout.varyingWorld] = moved.x
..[CpuMeshLayout.varyingWorld + 1] = moved.y
..[CpuMeshLayout.varyingWorld + 2] = moved.z;
return mvp * local;
}
if (written['world'] case final w?) {
out
..[CpuMeshLayout.varyingWorld] = w[0]
..[CpuMeshLayout.varyingWorld + 1] = w[1]
..[CpuMeshLayout.varyingWorld + 2] = w[2];
final viewProjection = bindings.mat4(
'MaterialVertexInfo',
'view_projection',
);
return viewProjection * Vector4(w[0], w[1], w[2], 1.0);
}
return clip;
}