Record Class SurfaceOutputs

java.lang.Object
java.lang.Record
limn.render3d.shader.SurfaceOutputs

public record SurfaceOutputs(Expr baseColor, Expr metallic, Expr roughness, Expr emissive, Expr normal, Expr diffuseResponse) extends Record
What a material's surface function contributes to the engine's lighting core: the metallic-roughness inputs. The backend owns the BRDF and consumes these: baseColor (vec4, linear rgb + alpha), metallic and roughness (floats), emissive (vec3, linear) and normal, the shading normal in world space. AO joins in a later phase.

normal may be null, meaning "shade with the interpolated geometric normal". A tangent-space map becomes a world normal through the framework helper normalMapToWorld(tangentNormal, scale), which builds a per-pixel frame from the screen-space derivatives of the world position and the UVs, so no mesh tangent attribute is required and the vertex stage is untouched. That is not only convenient: nothing in this toolkit produces tangents (neither the primitives nor the glTF loader), so a surface that demanded them would shade most meshes from a zero-length frame.

The diffuse response

diffuseResponse is the one output evaluated inside the light loop, once per light rather than once per fragment. It replaces the max(dot(N, L), 0) that scales the diffuse lobe, and it may read two framework locals the other expressions cannot see:
  • L: a vec3, the unit vector from the surface toward the light, in world space, with the light's type and attenuation already resolved;
  • NdotL: a float, the value this expression is replacing, so a surface that wants to blend with the standard term does not have to rebuild it.

Null means the standard term, and null is not merely the default: it is a different generated line. With no response the backend emits the factored form it always emitted, (kd * albedo / PI + specular) * radiance * NdotL; with one it has to distribute the NdotL across the two lobes so the diffuse half can escape it. Those two are equal in real arithmetic and not in IEEE, so a surface that supplied NdotL back verbatim would still shift the last bits of every lit pixel. Keeping the null path byte-identical is what lets a material adopt this without re-pinning a single existing image.

Why the diffuse lobe only. Specular is a mirror about the normal and stays on NdotL: a response is a statement about how light is scattered by the surface, not about where it reflects. Wrap lighting, toon ramps, a cloth or hair term, and the six-way directional response a volumetric billboard wants are all the diffuse half; none of them wants the highlight moved.

To turn L into the same tangent frame normalMapToWorld shades in, use the framework helper worldToTangent(v).

  • Constructor Summary

    Constructors
    Constructor
    Description
    SurfaceOutputs(Expr baseColor, Expr metallic, Expr roughness, Expr emissive, Expr normal)
    A surface shaded by the standard N·L diffuse response.
    SurfaceOutputs(Expr baseColor, Expr metallic, Expr roughness, Expr emissive, Expr normal, Expr diffuseResponse)
    Holds the surface's loops to Expr.Loop.MAX_ITERATIONS turns a pixel, its diffuse response's counted once for each of the eight lights a pass shades with, and refuses a loop's state read outside its loop and any other name starting ir_, which are the generator's.
  • Method Summary

    Modifier and Type
    Method
    Description
    Returns the value of the baseColor record component.
    Returns the value of the diffuseResponse record component.
    Returns the value of the emissive record component.
    final boolean
    Indicates whether some other object is "equal to" this one.
    final int
    Returns a hash code value for this object.
    Returns the value of the metallic record component.
    Returns the value of the normal record component.
    of(Expr baseColor, Expr metallic, Expr roughness, Expr emissive)
    A surface shaded by its geometric normal.
    Returns the value of the roughness record component.
    final String
    Returns a string representation of this record class.
    withDiffuseResponse(Expr diffuseResponse)
    A copy whose diffuse lobe is scaled by diffuseResponse instead of by max(dot(N, L), 0).
    withNormal(Expr normal)
    A copy whose surface normal comes from normal, in tangent space.

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Constructor Details

    • SurfaceOutputs

      public SurfaceOutputs(Expr baseColor, Expr metallic, Expr roughness, Expr emissive, Expr normal, Expr diffuseResponse)
      Holds the surface's loops to Expr.Loop.MAX_ITERATIONS turns a pixel, its diffuse response's counted once for each of the eight lights a pass shades with, and refuses a loop's state read outside its loop and any other name starting ir_, which are the generator's.
      Throws:
      IllegalArgumentException - if the surface's loops take more turns a pixel than that, or it reads a name starting ir_ where no loop binds it
    • SurfaceOutputs

      public SurfaceOutputs(Expr baseColor, Expr metallic, Expr roughness, Expr emissive, Expr normal)
      A surface shaded by the standard N·L diffuse response.
  • Method Details

    • of

      public static SurfaceOutputs of(Expr baseColor, Expr metallic, Expr roughness, Expr emissive)
      A surface shaded by its geometric normal.
    • withNormal

      public SurfaceOutputs withNormal(Expr normal)
      A copy whose surface normal comes from normal, in tangent space.
    • withDiffuseResponse

      public SurfaceOutputs withDiffuseResponse(Expr diffuseResponse)
      A copy whose diffuse lobe is scaled by diffuseResponse instead of by max(dot(N, L), 0). The expression is evaluated once per light and may reference the framework locals L and NdotL.
    • toString

      public final String toString()
      Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components.
      Specified by:
      toString in class Record
      Returns:
      a string representation of this object
    • hashCode

      public final int hashCode()
      Returns a hash code value for this object. The value is derived from the hash code of each of the record components.
      Specified by:
      hashCode in class Record
      Returns:
      a hash code value for this object
    • equals

      public final boolean equals(Object o)
      Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. All components in this record class are compared with Objects::equals(Object,Object).
      Specified by:
      equals in class Record
      Parameters:
      o - the object with which to compare
      Returns:
      true if this object is the same as the o argument; false otherwise.
    • baseColor

      public Expr baseColor()
      Returns the value of the baseColor record component.
      Returns:
      the value of the baseColor record component
    • metallic

      public Expr metallic()
      Returns the value of the metallic record component.
      Returns:
      the value of the metallic record component
    • roughness

      public Expr roughness()
      Returns the value of the roughness record component.
      Returns:
      the value of the roughness record component
    • emissive

      public Expr emissive()
      Returns the value of the emissive record component.
      Returns:
      the value of the emissive record component
    • normal

      public Expr normal()
      Returns the value of the normal record component.
      Returns:
      the value of the normal record component
    • diffuseResponse

      public Expr diffuseResponse()
      Returns the value of the diffuseResponse record component.
      Returns:
      the value of the diffuseResponse record component