emitMaterialFragment function

String emitMaterialFragment(
  1. MaterialProgram program
)

The .frag source for program, which should already be specialised.

describeMaterial answers the other half — what the engine may bind to it.

Implementation

String emitMaterialFragment(MaterialProgram program) {
  final out = StringBuffer()
    ..writeln('#version 460 core')
    ..writeln()
    ..writeln('// Generated from a material written in the material language')
    ..writeln('// — gfx-84n. The source is the thing to edit; this file is')
    ..writeln('// what the shader build compiles and what the three GPU')
    ..writeln('// backends translate. The software backend evaluates the same')
    ..writeln('// tree instead of reading this.')
    // It gathers no lights, so it keeps no light list: see
    // `LightingModel.usesLightList`.
    ..writeln('#define F3D_NO_LIGHT_LIST')
    ..writeln('#include <lib/surface.glsl>')
    ..writeln();

  // Both prototypes have to be satisfied whether or not anything calls them,
  // which is what `unlit.frag` says about its own pair. A material in this
  // language never accumulates lights — it returns the light the surface
  // emits — so these are the same honest stubs.
  out
    ..writeln('// Never called: a material in this language returns the light')
    ..writeln('// its surface emits rather than gathering any. The prototypes')
    ..writeln('// in surface.glsl still have to be satisfied.')
    ..writeln('vec3 ShadeLight(Surface s, LightSample light) {')
    ..writeln('  return s.albedo;')
    ..writeln('}')
    ..writeln()
    ..writeln('float LightVisibility(Surface s, LightSample light, int i) {')
    ..writeln('  return 1.0;')
    ..writeln('}')
    ..writeln()
    ..writeln('void main() {')
    ..writeln('  Surface s = ReadSurface();');

  for (final statement in program.body) {
    switch (statement) {
      case MaterialLet(:final name, :final value):
        out.writeln('  ${value.type.name} $name = ${_glsl(value)};');
      case MaterialReturn(:final value):
        out
          ..writeln('  vec4 result = ${_glsl(value)};')
          ..writeln('  WriteSurface(result.rgb, result.a);');
    }
  }

  out.writeln('}');
  return out.toString();
}