Render Texture

A render texture is a texture on the GPU. Usually, we set it to the camera’s target texture, so that the content illuminated by the camera is drawn to the texture via an off-screen frambuffer. This can typically be used to create car mirrors, dynamic shadows, etc.

Creating a RenderTexture

Click the + button in the top left of the Assets panel and select RenderTexture to create a Render Texture:

add-render-texture

The properties associated with the render texture asset can then be set in the Inspector panel.

render-texture-property

PropertyDescription
WidthSet the width of the render texture.
HeightSet the height of the render texture.
AnisotropyAnisotropy value.
Min FilterNarrowing filtering algorithm.
Mag FilterAmplification filtering algorithm.
Mip FilterMulti-level texture filtering algorithm.
Wrap Mode SS(U) direction texture addressing mode.
Wrap Mode TT(V) direction texture addressing mode.

Use RenderTexture in editor

In the camera component, assigning RenderTexture to the camera’s TargetTexture property will draw the result of the camera’s illumination onto the RenderTexture.

camera

Use RenderTexture in 2D / UI

RenderTexture can be used like a normal texture. Take Sprite Component as an example, drag and drop from Assets panel onto the SpriteFrame property on Sprite’s Inspector panel.

sprite rt

Use RenderTexture in material

To use RenderTexture in material includes the following two steps:

  1. Handle uv in effect asset. Determine SAMPLE_FROM_RT, and call the CC_HANDLE_RT_SAMPLE_FLIP function:

    1. #if USE_TEXTURE
    2. v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw;
    3. #if SAMPLE_FROM_RT
    4. CC_HANDLE_RT_SAMPLE_FLIP(v_uv);
    5. #endif
    6. #endif
  2. Select the corresponding material in the Assets panel, then check SAMPLE FROM RT in the Inspector panel:

    SAMPLE_FROM_RT

RenderTexture program guide

There are two ways to use RenderTexture programmatically:

  • Method 1: Draw the contents illuminated by the 3D camera to the sprite frame of the UI.

    1. import { _decorator, Component, RenderTexture, SpriteFrame, Sprite, Camera } from 'cc';
    2. const { ccclass, property } = _decorator;
    3. @ccclass('CaptureToWeb')
    4. export class CaptureToWeb extends Component {
    5. @property(Sprite)
    6. sprite: Sprite = null;
    7. @property(Camera)
    8. camera: Camera = null;
    9. protected _renderTex: RenderTexture = null;
    10. start() {
    11. const sp = new SpriteFrame();
    12. const renderTex = this._renderTex = new RenderTexture();
    13. renderTex.reset({
    14. width: 256,
    15. height: 256,
    16. });
    17. this.camera.targetTexture = renderTex;
    18. sp.texture = renderTex;
    19. this.sprite.spriteFrame = sp;
    20. }
    21. }
  • Method 2: Draw the contents illuminated by the 3D camera to the 3D model.

    1. import { _decorator, Component, MeshRenderer, RenderTexture, Camera, Material } from 'cc';
    2. const { ccclass, property, requireComponent } = _decorator;
    3. @ccclass("RenderCameraToModel")
    4. @requireComponent(Camera)
    5. export class RenderCameraToModel extends Component {
    6. @property(MeshRenderer)
    7. model: MeshRenderer = null;
    8. start() {
    9. const renderTex = new RenderTexture();
    10. renderTex.reset({
    11. width: 256,
    12. height: 256,
    13. });
    14. const cameraComp = this.getComponent(Camera);
    15. cameraComp.targetTexture = renderTex;
    16. const pass = this.model.material.passes[0];
    17. // The purpose of setting the 'SAMPLE_FROM_RT' Macro to 'true' is to enable the RenderTexture to display correctly on all platforms
    18. const defines = { SAMPLE_FROM_RT: true, ...pass.defines };
    19. const renderMat = new Material();
    20. renderMat.initialize({
    21. effectAsset: this.model.material.effectAsset,
    22. defines,
    23. });
    24. this.model.setMaterial(renderMat, 0);
    25. renderMat.setProperty('mainTexture', renderTex, 0);
    26. }
    27. }
  • Method 3:Read the content drawn by the 3D camera into the ArrayBuffer through the readPixels method

    1. import { _decorator, Component, RenderTexture } from 'cc';
    2. const { ccclass, property } = _decorator;
    3. @ccclass("RenderReadPixels")
    4. export class RenderReadPixels extends Component {
    5. @property(RenderTexture)
    6. public renderTexture: RenderTexture;
    7. start() {
    8. const width = this.renderTexture.width;
    9. const height = this.renderTexture.height;
    10. const texPixels = new Uint8Array(width * height * 4);
    11. this.renderTexture.readPixels(0, 0,
    12. this.renderTexture.width, this.renderTexture.height,
    13. texPixels);
    14. }
    15. }

    Make sure that the shader has a mainTexture property and is enabled in the material if you want to display the drawing results correctly. For example, if using the builtin-standard shader, make sure the USE ALBEDO MAP option is checked:

    use albedo

For more information about the usage, please refer to the example RenderTexture (GitHub).