AcademySoftwareFoundation / MaterialX

MaterialX is an open standard for the exchange of rich material and look-development content across applications and renderers.
http://www.materialx.org/
Apache License 2.0
1.87k stars 352 forks source link

Proposal: Add in native "unlit" shader #839

Closed kwokcb closed 2 years ago

kwokcb commented 2 years ago

Proposed new surface shader variant which does no compute any illumination. This allows for any upstream pattern graph to be connected and used as a material. Some applications include support for "modeling" and "NPR" materials.

Description: The new node's interface would look like this. The possible nodegroup is "npbr" (non-pbr).

nodedef name="ND_surface_std" node="surface" nodegroup="npbr" doc="Construct a surface shader from emission and transmission values." version="1.0">
  <input name="emission" type="float" value="1.0" doc="Surface emission amount." />
  <input name="emission_color" type="color3" value="0,0,0" doc="Surface emission color." />
  <input name="transmission" type="float" value="0.0" doc="Surface transmission amount." />
  <input name="transmission_color" type="color3" value="0,0,0" doc="Surface transmission color." />
  <input name="opacity" type="float" value="1.0" doc="Surface cutout opacity." />
  <output name="out" type="surfaceshader" />
</nodedef>

where transmission can be used to perform blending with background elements as opposed to opacity which is just for cut-outs. The inverse of transmission is used for blending (this is similar to what is done for Standard Surface currently). A surface that is 100% transparent will not emit any color (not emit or reflect any light if it was a lit surface).

This is a variant on the existing surface shader,.

  <nodedef name="ND_surface" node="surface" nodegroup="pbr" doc="A constructor node for the surfaceshader type.">
    <input name="bsdf" type="BSDF" value="" doc="Distribution function for surface scattering." />
    <input name="edf" type="EDF" value="" doc="Distribution function for surface emission." />
    <input name="opacity" type="float" value="1.0" doc="Surface cutout opacity" />
    <output name="out" type="surfaceshader" />
  </nodedef>

Properties:

Support:

Examples:

francis-wangfr commented 2 years ago

Thank you @kwokcb, this feature is important and valuable for surfaces that doesn't accept lighting and stylized effect. I appreciate this improvement if we could get it ready in the short future.

kwokcb commented 2 years ago

A question came up as to whether the emission will affect other surfaces in the scene. It was noted that there is a already a uniform edf which has these properties by @dbsmythe. The control for this is left up to the renderer via "light or shader linking" and no new attribute is currently proposed.

kwokcb commented 2 years ago

I did a quick check since KHR PBR is up from @proog128.

Looking over KHR_materials_unlit one interesting thing was routing of vertex colors as a multiplier according to the 2.0 spec..

What is being proposed here can be used if desired by creating something akin to this graph, where standard_surface can be replaced with the unlit surface variant.

<?xml version="1.0"?>
<materialx version="1.38">
  <nodegraph name="KHR_materials_unlit">
    <input name="Vertex_ColorSet" type="integer" value="0" />
    <input name="use_image" type="float" value="0" />
    <input name="use_vertex_color" type="float" value="0" />
    <input name="base_color" type="color3" value="1, 1, 1" />
    <input name="base_factor" type="float" value="1" />
    <input name="base_image" type="color3" nodename="image" value="0, 0, 0" />
    <geomcolor name="geomcolor" type="color3" nodedef="ND_geomcolor_color3">
      <input name="index" type="integer" uniform="true" interfacename="Vertex_ColorSet" value="0" />
    </geomcolor>
    <multiply name="multiply" type="color3" nodedef="ND_multiply_color3">
      <input name="in1" type="color3" nodename="use_vertex_color_test" />
      <input name="in2" type="color3" nodename="use_image_test" />
    </multiply>
    <ifequal name="use_image_test" type="color3" nodedef="ND_ifequal_color3">
      <input name="value1" type="float" value="1" />
      <input name="value2" type="float" interfacename="use_image" value="0" />
      <input name="in1" type="color3" interfacename="base_image" value="0, 0, 0" />
      <input name="in2" type="color3" interfacename="base_color" value="1, 1, 1" />
    </ifequal>
    <ifequal name="use_vertex_color_test" type="color3" nodedef="ND_ifequal_color3">
      <input name="value1" type="float" value="1" />
      <input name="value2" type="float" interfacename="use_vertex_color" value="0" />
      <input name="in1" type="color3" nodename="geomcolor" />
      <input name="in2" type="color3" value="1, 1, 1" />
    </ifequal>
    <standard_surface name="standard_surface" type="surfaceshader" nodedef="ND_standard_surface_surfaceshader" version="1.0.1">
      <input name="base" type="float" value="0" />
      <input name="specular" type="float" value="0" />
      <input name="emission" type="float" interfacename="base_factor" value="1" />
      <input name="emission_color" type="color3" nodename="multiply" />
    </standard_surface>
    <output name="out" type="surfaceshader" nodename="standard_surface" />
  </nodegraph>
  <image name="image" type="color3" nodedef="ND_image_color3">
    <input name="file" type="filename" uniform="true" value="checker.png" />
  </image>
</materialx>
jstone-lucasfilm commented 2 years ago

Thanks for writing up this proposal, @kwokcb, and thanks to @niklasharrysson for the implementation in #860.