Phaser3 麦克风输入Shader实现音频可视化遇阻求助
解决Phaser 3中麦克风音频数据传入Shader的问题
核心问题在于你需要将Uint8Array格式的音频数据转换为Phaser Shader可识别的纹理对象,而非直接传递数组。以下是具体实现步骤:
1. 创建可更新的Canvas纹理
在场景的create方法中,先创建一个与音频数组长度匹配的Canvas纹理(这里是1024x1,对应1024个音频样本):
create() { this.shader = this.add.shader('simplesound', 400, 300, 800, 600); // 创建1024x1的Canvas纹理,用于承载音频数据 this.audioTexture = this.textures.createCanvas('audioTexture', 1024, 1); this.audioCtx = this.audioTexture.getContext(); // 初始化纹理(避免初始黑帧) const initData = new Uint8Array(1024 * 4); // RGBA格式,每个像素4字节 this.audioCtx.putImageData(new ImageData(new Uint8ClampedArray(initData), 1024, 1), 0, 0); this.audioTexture.refresh(); const GKey = this.input.keyboard.addKey('G'); GKey.on('down', () => { setupAudioContext((array) => { // 后续更新纹理逻辑写在这里 }); }); }
2. 在音频回调中更新纹理数据
每次获取到麦克风的Uint8Array数据后,将其写入Canvas纹理的R通道(其他通道固定为255保证不透明),然后刷新纹理并传递给Shader:
GKey.on('down', () => { setupAudioContext((array) => { const imageData = this.audioCtx.getImageData(0, 0, 1024, 1); const data = imageData.data; // 将Uint8Array音频值写入纹理的R通道 for (let i = 0; i < array.length; i++) { data[i * 4] = array[i]; // R通道存储音频样本(0-255) data[i * 4 + 1] = 255; // G通道固定 data[i * 4 + 2] = 255; // B通道固定 data[i * 4 + 3] = 255; // Alpha通道不透明 } // 更新纹理并传递给Shader的iChannel0 this.audioCtx.putImageData(imageData, 0, 0); this.audioTexture.refresh(); this.shader.setChannel0(this.audioTexture); }); });
3. 调整Shader采样逻辑
由于纹理是1024x1的一维纹理,需要修改Shader中的采样方式,用uv.x对应音频样本的索引,同时将纹理值从0-255范围转换为0-1的归一化值:
#ifdef GL_ES precision highp float; #endif precision mediump float; uniform vec2 resolution; uniform sampler2D iChannel0; varying vec2 fragCoord; void main() { vec2 uv = fragCoord.xy / resolution.xy; // 采样1024x1纹理:x轴对应音频样本索引,y轴取纹理中间位置 float audioValue = texture2D(iChannel0, vec2(uv.x, 0.5)).r / 255.0; // 可视化逻辑:绘制随音频变化的水平线 float y = abs(uv.y - audioValue); float intensity = smoothstep(0.0, 0.02, y); gl_FragColor = vec4(1.0 - intensity, 0.2, 0.2, 1.0); // 红色波形 }
关键注意事项
- 确保纹理尺寸与音频数组长度完全一致(这里都是1024),否则采样会出现错位。
- 使用
setChannel0时必须传递Phaser的Texture对象,而非原始Canvas或数组。 - Shader中要将纹理的8位值转换为0-1的归一化值,否则计算会超出范围。
内容的提问来源于stack exchange,提问作者rikas
相关产品推荐
相关产品推荐

