Custom Materials for 2D Rendering Objects

Custom materials for 2D rendering objects are a best practice to extend the performance of 2D rendering objects and enhance the capabilities of 2D rendering objects themselves, allowing for cool rendering effects such as dissolve and glow.

Most of the 2D renderable components in v3.0 support the use of custom materials, with the following interface (using the Sprite component as an example).

UIMaterial

The usage is no different from other built-in materials, just drag and drop the material to be used into the CustomMaterial property box, but there are some points to note as follows:

  1. When no custom material is specified, the built-in material will be used for rendering, please refer to the Sprite Component Reference documentation.
  2. 2D rendering objects do not support multiple materials, the maximum number of custom materials is one.
  3. Please use a 2D-specific shader such as builtin-spine or builtin-sprite to customize materials, do not choose a shader used by other 3D components.
  4. The Grayscale property on the panel is disabled when a custom material for 2D rendering objects is used, and the user can choose to implement this feature in the material itself.
  5. If the BlendFactor is set in the code, when a custom material is used, the BlendFactor setting in the custom material will prevail.
  6. When a custom material is used, the depth detection information of the component will be based on the material. To achieve occlusion with 3D objects, please use custom materials and turn on depth detection. See the example 2d-rendering-in-3d.
  7. For custom materials, getting the uploaded texture requires introducing the cc-sprite-texture header file in the shader, where cc_spriteTexture corresponds to the SpriteFrame image asset set in the 2D rendering component properties panel. For example, a fragment shader that simply uses the panel to set a SpriteFrame to sample textures should look like the following:

    1. CCProgram sprite-fs %{
    2. precision highp float;
    3. #include <cc-sprite-texture>
    4. in vec4 v_color;
    5. uniform ARGS{
    6. float time;
    7. };
    8. in vec2 uv0;
    9. uniform sampler2D u_normalMap;
    10. vec4 frag () {
    11. vec4 color = vec4(1, 1, 1, 1);
    12. color *= v_color;
    13. float value = 1.0;
    14. vec4 o = texture(u_normalMap, uv0);
    15. value *= o.r;
    16. if (value < time) {
    17. discard;
    18. }
    19. color *= texture(cc_spriteTexture, uv0);
    20. if (value < time + 0.05) {
    21. color = vec4(0.9, 0.6, 0.3, color.a);
    22. }
    23. return color;
    24. }
    25. }%

    dissolve

  8. If the user wants to assign a uniform to a custom material, it can be done by getting the customMaterial on the 2D renderer component. Creator provides different interfaces for different cases, see the following example code for Sprite:

    1. let spriteComp = this.node.getComponent(Sprite);
    2. // The sharedMaterial method is a "shared material asset", and operations performed on the material will affect all rendering objects that use the material, this operation will not instantiate the asset and will not affect the batch
    3. let material = spriteComp.sharedMaterial;
    4. // The material method gets the "example material used by the current renderable component", and operations on the Material Instance will only affect the current component, this operation will instantiate the asset, and once instantiated, this component cannot be combined with other components
    5. let materialInstance = spriteComp.material;

    Note: please be sure to read the annotations of the different interfaces!