mcpField
R
render-textures

render-textures

github.com/phaserjs开发40.6k788 次安装10 周前更新
代码仓库

关于 render-textures

Phaser 4 纹理绘制技能,面向需要在离屏纹理上合成、生成或采样游戏画面的开发者。内容涵盖 RenderTexture 与 DynamicTexture 的差异、命令缓冲区及常见图案。

主要功能

  1. 01RenderTexture 与 DynamicTexture 用法
  2. 02命令缓冲区渲染
  3. 03纹理绘制、填充与擦除
  4. 04纹理快照与像素读取
  5. 05程序化纹理和小地图模式

适用场景

  1. 01将多个游戏对象合成为纹理
  2. 02生成平铺或星空等程序化纹理
  3. 03制作固定在摄像机上的小地图
  4. 04读取纹理区域或像素数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/phaserjs/phaser --skill render-textures

安装后在 Claude Code 中输入/render-textures确认已加载。

详细介绍

渲染纹理与动态纹理

在 Phaser 4 中将游戏对象绘制到离屏纹理 -- RenderTexture 游戏对象、用于共享纹理的 DynamicTexture、Stamp 辅助工具、命令缓冲区渲染、快照、程序化生成以及小地图模式。

关键源码路径: src/gameobjects/rendertexture/、src/textures/DynamicTexture.js、src/gameobjects/stamp/、src/textures/typedefs/StampConfig.js、src/textures/typedefs/CaptureConfig.js 相关技能: ../sprites-and-images/SKILL.md、../loading-assets/SKILL.md、../cameras/SKILL.md

快速开始

// In a Scene's create() method:

// 1. RenderTexture -- a visible game object with its own DynamicTexture
const rt = this.add.renderTexture(400, 300, 256, 256);
rt.draw('player', 128, 128);          // draw a texture by key at center
rt.fill(0x222244, 0.5);               // semi-transparent fill
rt.render();                           // flush the command buffer

// 2. DynamicTexture -- a shared texture in the Texture Manager
const dt = this.textures.addDynamicTexture('composite', 512, 512);
dt.stamp('coin', null, 64, 64, { scale: 2, angle: 45 });
dt.render();
this.add.image(400, 300, 'composite'); // any game object can use it

// 3. Stamp game object -- lightweight Image that ignores camera scroll
const hud = this.add.stamp(10, 10, 'heart');

核心概念

RenderTexture 与 DynamicTexture

Phaser 4 将纹理绘制拆分为两个层级:

RenderTextureDynamicTexture
它是什么Image 游戏对象 + 自动创建的 DynamicTextureTexture Manager 中的纹理
创建方式this.add.renderTexture(x, y, w, h)this.textures.addDynamicTexture(key, w, h)
自身是否可见是(它继承自 Image)否(必须赋值给某个游戏对象)
可否跨对象共享可通过 saveTexture(key) 实现可以,通过 key
可否跨场景使用否(属于单个 Scene)可以(纹理是全局的)
是否有位置/缩放/透明度是(具备所有 Image 组件)否(它是 Texture,不是 GameObject)

何时使用哪一个:

  • 当你需要一个可绘制的单一可见表面时(绘画画布、拖尾效果、合成精灵),使用 RenderTexture。
  • 当许多游戏对象共享同一张生成纹理时,或者你需要为遮罩/着色器提供纹理,或者需要跨场景访问时,使用 DynamicTexture。

RenderTexture 是一个轻量代理。诸如 draw()、stamp()、fill()、clear()、erase()、snapshot() 之类的方法都会委托给它底层的 this.texture(一个 DynamicTexture)。

原点说明: RenderTexture 继承自 Image,因此其原点默认为 (0.5, 0.5)。如果你想要左上角定位(常见于全屏或小地图 RT),请调用 rt.setOrigin(0, 0)。

命令缓冲区(v4 架构)

在 Phaser 4 中,绘制调用(draw、stamp、fill、clear、erase、repeat、capture)不会立即执行。它们会把命令推入一个 commandBuffer 数组。你必须调用 .render() 来刷新并执行缓冲区。

rt.clear();
rt.fill(0x000000);
rt.draw(sprite, 128, 128);
rt.render();  // REQUIRED -- nothing appears without this

对于 RenderTexture 游戏对象,renderMode 属性控制自动渲染:

模式行为
'render'(默认)每个 tick 将纹理内容绘制到帧上。内容变化时你需手动调用 render()。
'redraw'每帧自动调用 render(),但不会显示自身。适用于被其他对象复用的纹理。
'all'每帧调用 render(),并且将自身绘制到帧上。
rt.setRenderMode('all');       // auto-render + display every frame
rt.setRenderMode('all', true); // same, plus preserve the command buffer
保留模式

默认情况下,命令缓冲区在 render() 后会被清空。调用 preserve(true) 可在多次渲染之间保留命令,从而让相同的绘制每帧重放:

rt.preserve(true);
rt.clear();
rt.draw(sprite);
// On every subsequent render(), clear + draw will repeat
Stamp 游戏对象

Stamp(this.add.stamp(x, y, texture, frame))是一个轻量级 Image 子类,在渲染时会忽略相机滚动和变换。它在 DynamicTexture 内部被用于绘制操作,也可用于 HUD 元素。它继承了 Image,并带有自定义渲染节点(DefaultStampNodes)。

stamp() 方法与 Stamp 游戏对象的区别

它们是不同的东西:

  • rt.stamp(key, frame, x, y, config) -- RenderTexture/DynamicTexture 上的一个方法,用于将纹理帧绘制到表面,并支持变换选项(alpha、tint、angle、scale、origin、blendMode)。
  • this.add.stamp(x, y, texture, frame) -- 一个工厂方法,用于创建一个 Stamp 游戏对象并添加到 Scene 显示列表中。

常见模式

绘制精灵和游戏对象
const rt = this.add.renderTexture(0, 0, 800, 600);

// Single game object at an offset
rt.draw(sprite, 100, 100);

// Array of objects
rt.draw([sprite1, sprite2, sprite3]);

// Group or Container (only visible children are drawn)
rt.draw(enemyGroup);
rt.draw(myContainer, 50, 50);  // offset added to children positions

// Entire Scene display list
rt.draw(this.children);

// Texture by string key
rt.draw('explosion', 200, 200);

// Don't forget to flush
rt.render();

draw() 方法接受:可渲染的游戏对象、Group、Container、Display List、其他 RenderTexture/DynamicTexture、纹理帧、纹理键字符串,或上述任意类型的数组。

注意:draw() 上的 alpha 和 tint 参数仅适用于纹理帧/字符串。游戏对象在绘制时会使用自身的 alpha 和 tint。

使用 Config 盖章纹理

stamp() 方法在完全变换控制下绘制纹理帧。该帧默认以 x/y 位置为中心(原点 0.5)。

rt.stamp('bullet', null, 100, 100, {
    alpha: 0.8,
    tint: 0xff0000,
    angle: 45,          // degrees (takes precedence over rotation)
    scale: 2,           // uniform scale
    scaleX: 1.5,        // overrides scale for X
    scaleY: 0.5,        // overrides scale for Y
    originX: 0,         // top-left origin
    originY: 0,
    blendMode: 0
});
rt.render();
Capture —— 使用覆盖项绘制(v4)

capture() 方法在临时属性覆盖下绘制游戏对象,之后恢复原始属性:

rt.capture(player, {
    x: 64,
    y: 64,
    scale: 0.5,
    alpha: 0.8,
    rotation: Math.PI / 4,
    transform: 'world',    // 'local', 'world', or a TransformMatrix
    camera: someCamera      // optional camera override
});
rt.render();

这适用于在不修改对象本身的情况下,以不同的位置/缩放绘制对象。

填充和清除
// Fill entire texture with color
rt.fill(0xff0000);          // solid red
rt.fill(0x000000, 0.5);     // semi-transparent black

// Fill a region
rt.fill(0x00ff00, 1, 10, 10, 100, 50);  // green rect at (10,10) size 100x50

// Clear everything (transparent)
rt.clear();

// Clear a region
rt.clear(10, 10, 100, 50);

rt.render();
擦除

擦除使用 ERASE 混合模式在纹理中切出空洞:

rt.fill(0xffffff);           // white background
rt.erase(circleSprite, 100, 100);  // punch a hole shaped like the sprite
rt.render();
重复 / 平铺纹理
// Fill the entire RenderTexture with a tiled pattern
rt.repeat('grass', null);                        // tile the whole surface
rt.repeat('brick', null, 0, 0, 256, 128);       // tile a specific region
rt.repeat('tile', 'frame2', 0, 0, 512, 512, {
    tileScaleX: 2,
    tileScaleY: 2,
    tilePositionX: 16,
    alpha: 0.8
});
rt.render();
快照(像素捕获)

快照从帧缓冲读取像素数据。它们开销大且会阻塞——请谨慎使用。

// Full texture snapshot -- callback receives an HTMLImageElement
rt.snapshot(function (image) {
    document.body.appendChild(image);  // or use as texture source
});

// Area snapshot
rt.snapshotArea(0, 0, 128, 128, function (image) {
    // image is 128x128 region from top-left
}, 'image/jpeg', 0.8);

// Single pixel -- callback receives a Phaser.Display.Color
rt.snapshotPixel(64, 64, function (color) {
    console.log(color.r, color.g, color.b, color.a);
});
用作其他对象的纹理源
const rt = this.add.renderTexture(0, 0, 256, 256);
rt.draw(complexScene);
rt.render();

// Register in the Texture Manager under a key
rt.saveTexture('composited');

// Now any game object can use it
this.add.image(400, 300, 'composited');
this.add.sprite(100, 100, 'composited');

// Updates to the RenderTexture automatically reflect on all users

对于 DynamicTexture,键在创建时设置:

const dt = this.textures.addDynamicTexture('terrain', 1024, 1024);
dt.repeat('grass', null);
dt.render();
this.add.image(512, 512, 'terrain');  // already keyed
程序化生成
const dt = this.textures.addDynamicTexture('starfield', 800, 600);
dt.fill(0x000011);
for (let i = 0; i < 200; i++) {
    const x = Phaser.Math.Between(0, 800);
    const y = Phaser.Math.Between(0, 600);
    const brightness = Phaser.Math.FloatBetween(0.3, 1);
    dt.stamp('star', null, x, y, { alpha: brightness, scale: Phaser.Math.FloatBetween(0.5, 1.5) });
}
dt.render();
this.add.image(400, 300, 'starfield');
小地图模式
create() {
    // Small RenderTexture as minimap
    this.minimap = this.add.renderTexture(700, 50, 150, 100);
    this.minimap.setScrollFactor(0);  // fixed to camera
    this.minimap.setRenderMode('all'); // auto-render every frame
    this.minimap.preserve(true);
}

// In update or a callback:
this.minimap.clear();
this.minimap.fill(0x111111);
// Draw scaled-down versions of world objects
this.minimap.capture(player, { x: px * 0.1, y: py * 0.1, scale: 0.1 });
// render() is automatic in 'all' mode
命令缓冲区中的回调

在绘制命令之间插入逻辑,这些逻辑会在 render() 期间执行:

rt.clear();
rt.draw(background);
rt.callback(() => {
    // Runs during render, after background is drawn
    sprite.setTint(0xff0000);
});
rt.draw(sprite);
rt.callback(() => {
    sprite.setTint(0xffffff);  // restore after drawing
});
rt.render();
调整大小
// Resize erases all content and recreates the framebuffer
rt.resize(512, 512);

// Optional: disable force-even rounding
rt.resize(513, 513, false);
内部摄像机

RenderTexture 和 DynamicTexture 都有一个 .camera 属性,用于控制绘制时游戏对象的定位方式。滚动、缩放和旋转此摄像机以变换绘制的内容。注意:stamp() 会忽略摄像机;只有 draw() 和游戏对象渲染会遵循它。

rt.camera.setScroll(100, 50);
rt.camera.setZoom(2);
rt.draw(sprite);  // sprite drawn with camera transform applied
rt.render();

API 快速参考

RenderTexture(继承自 Image)
方法签名描述
draw(entries, x?, y?, alpha?, tint?)绘制游戏对象、纹理、组等
capture(entry, config)使用临时属性覆盖进行绘制
stamp(key, frame?, x?, y?, config?)使用变换盖章纹理帧
erase(entries, x?, y?)使用 ERASE 混合模式绘制
fill(rgb, alpha?, x?, y?, w?, h?)用颜色填充
clear(x?, y?, w?, h?)清除为透明
repeat(key, frame?, x?, y?, w?, h?, config?)将纹理平铺为填充图案
render()刷新命令缓冲区
preserve(bool)在渲染之间保留命令缓冲区
callback(fn)将回调插入命令缓冲区
resize(w, h?, forceEven?)调整大小(擦除内容)
saveTexture(key)在 Texture Manager 中注册
setRenderMode(mode, preserve?)设置 'render'、'redraw' 或 'all'
snapshot(callback, type?, quality?)完整快照到 Image
snapshotArea(x, y, w, h, callback, type?, quality?)区域快照
snapshotPixel(x, y, callback)单个像素到 Color
DynamicTexture(继承自 Texture)

与 RenderTexture 相同的绘制方法(draw、stamp、erase、fill、clear、repeat、capture、render、preserve、callback、snapshot、snapshotArea、snapshotPixel),另外还有:

方法/属性描述
setSize(w, h?, forceEven?)调整纹理大小
camera用于绘制定位的内部摄像机
commandBuffer待处理绘制命令的数组
drawingContext带帧缓冲的 WebGL DrawingContext
getWebGLTexture()返回底层 WebGLTextureWrapper
StampConfig(用于 stamp() 配置参数)
属性默认值描述
alpha1Alpha 值
tint0xffffff色调(仅 WebGL)
angle0角度(非零时覆盖 rotation)
rotation0弧度
scale1统一缩放
scaleX / scaleY1各轴缩放(覆盖 scale)
originX / originY0.5原点
blendMode0混合模式
CaptureConfig(用于 capture() 配置参数)
属性描述
transform'local'、'world' 或 TransformMatrix
camera用于渲染的相机覆盖
x、y、alpha、tint、angle、rotation临时覆盖游戏对象属性
scale、scaleX、scaleY缩放覆盖
originX、originY、blendMode其他覆盖
工厂方法
this.add.renderTexture(x, y, width?, height?)  // default 32x32
this.add.stamp(x, y, texture, frame?)
this.textures.addDynamicTexture(key, width?, height?, forceEven?)  // default 256x256

注意事项

  1. 必须调用 render()。 在 Phaser 4 中,绘制方法会缓冲命令。在调用 render() 之前不会显示任何内容(除非使用 renderMode: 'all' 或 'redraw')。

  2. 不能绘制到自身。 DynamicTexture/RenderTexture 会静默跳过引用自身的条目。

  3. 渲染后命令缓冲区会清空。 如果你需要相同的命令每帧重放,请在绘制前调用 preserve(true)。

  4. stamp() 忽略内部相机。 只有通过 draw() 或 capture() 绘制的游戏对象才会遵循 .camera 属性。纹理图章按绝对位置定位。

  5. 默认尺寸不同。 RenderTexture 默认为 32x32。DynamicTexture 默认为 256x256。

  6. forceEven 会将尺寸向上取整。 默认情况下,为保证渲染质量,宽度/高度会取整为偶数。如果你需要精确的奇数尺寸,请将 false 作为最后一个参数传入。

  7. 快照开销很大。 它们使用 readPixels(WebGL),会阻塞 GPU 管线。避免逐帧快照。snapshotPixel 比完整的 snapshot 更廉价。

  8. WebGL1 的帧缓冲没有抗锯齿。 绘制到 RenderTexture 的形状和 Graphics 可能会有锯齿边缘。请改用预渲染的 sprite 纹理。

  9. resize() 会擦除内容。 调整大小会销毁并重新创建帧缓冲。

  10. saveTexture 是重命名,不是复制。 调用 saveTexture(key) 会在 Texture Manager 中以该键分配 DynamicTexture。用不同的键再次调用会将其重命名。如果不先保存就销毁 RenderTexture,纹理会随之销毁。

  11. draw() 的 alpha/tint 参数仅影响 Texture Frame。 绘制游戏对象时,它们使用自己的 alpha 和 tint 值。draw() 上的 alpha 和 tint 参数仅在绘制纹理字符串或 Frame 实例时生效。

  12. WebGL 上下文丢失。 DynamicTexture 的内容会在上下文丢失时丢失。请监听 restorewebgl 事件以重新绘制。

  13. Group/Container:x、y 偏移是叠加的。 当使用 rt.draw(group, x, y) 绘制 Group 或 Container 时,x/y 偏移会加到每个子项的位置上。位于 (100, 50) 的子项在以偏移 (10, 10) 绘制后,会出现在纹理中的 (110, 60)。

源文件映射

文件描述
src/gameobjects/rendertexture/RenderTexture.jsRenderTexture 游戏对象(继承 Image,代理到 DynamicTexture)
src/gameobjects/rendertexture/RenderTextureFactory.jsthis.add.renderTexture() 工厂注册
src/gameobjects/rendertexture/RenderTextureRender.jsRenderTexture 的 WebGL/Canvas 渲染函数
src/gameobjects/rendertexture/RenderTextureRenderModes.js枚举:RENDER、REDRAW、ALL
src/textures/DynamicTexture.js核心 DynamicTexture 类(命令缓冲区、绘制、快照)
src/textures/DynamicTextureCommands.js命令常量(CLEAR、FILL、STAMP、DRAW、ERASE 等)
src/textures/typedefs/StampConfig.js用于 stamp() 的 StampConfig 类型定义
src/textures/typedefs/CaptureConfig.js用于 capture() 的 CaptureConfig 类型定义
src/gameobjects/stamp/Stamp.jsStamp 游戏对象(轻量 Image,忽略相机滚动)
src/gameobjects/stamp/StampFactory.jsthis.add.stamp() 工厂注册

评论

支持 Markdown