如何在MonoGame的MGFX着色器中修改纹理坐标实现灯光移动
在MonoGame中通过Effect修改纹理坐标实现灯光移动效果
问题
我想通过MonoGame的Effect类修改纹理坐标,实现灯光在屏幕上移动的效果,该怎么操作?
现有代码
C# 部分
lighting.CurrentTechnique = lighting.Techniques["LightDrawing"]; lighting.Parameters["RenderTargetTexture"].SetValue(_melttown[0].Texture); lighting.Parameters["MaskTexture"].SetValue(_lightMask[0].Texture);
MGFX 着色器部分
float4 MainPS(float2 textureCoords : TEXCOORD0) : COLOR { float4 pixelColor = tex2D(RenderTargetSampler, textureCoords); float4 lightColor = tex2D(MaskSampler, textureCoords); return pixelColor * lightColor; } technique LightDrawing { pass P0 { PixelShader = compile PS_SHADERMODEL MainPS(); } };
解决方法
1. 修改着色器,添加灯光偏移参数
在着色器中新增一个float2类型的参数控制灯光遮罩的偏移,采样遮罩纹理时给原坐标加上这个偏移值,就能实现灯光移动:
// 新增灯光偏移参数,用于控制遮罩位置 float2 LightOffset; // 显式声明采样器与纹理(若之前未声明) sampler RenderTargetSampler : register(s0); texture RenderTargetTexture; sampler MaskSampler : register(s1); texture MaskTexture; float4 MainPS(float2 textureCoords : TEXCOORD0) : COLOR { float4 pixelColor = tex2D(RenderTargetSampler, textureCoords); // 给遮罩纹理坐标添加偏移,实现灯光移动 float2 lightUV = textureCoords + LightOffset; float4 lightColor = tex2D(MaskSampler, lightUV); return pixelColor * lightColor; } technique LightDrawing { pass P0 { PixelShader = compile PS_SHADERMODEL MainPS(); } };
2. 在C#中实时更新偏移量
每一帧绘制时,计算灯光的偏移值并传递给Effect参数。示例实现一个平滑的循环移动效果:
// 在Update或Draw方法中计算灯光偏移 // 用总游戏时间计算,实现无卡顿的循环运动 Vector2 lightOffset = new Vector2( (float)Math.Sin(GameTime.TotalGameTime.TotalSeconds) * 0.2f, (float)Math.Cos(GameTime.TotalGameTime.TotalSeconds) * 0.2f ); // 将偏移值传入Effect参数 lighting.Parameters["LightOffset"].SetValue(lightOffset); // 原有设置代码保持不变 lighting.CurrentTechnique = lighting.Techniques["LightDrawing"]; lighting.Parameters["RenderTargetTexture"].SetValue(_melttown[0].Texture); lighting.Parameters["MaskTexture"].SetValue(_lightMask[0].Texture); // 绘制时记得将Effect传入SpriteBatch // spriteBatch.Begin(effect: lighting); // ...执行绘制逻辑... // spriteBatch.End();
额外提示
- 偏移值范围:纹理坐标为0-1的相对值,偏移量建议控制在-1到1之间。若采样器设为Wrap模式,灯光移出屏幕后会循环显示;设为Clamp模式则边缘会拉伸。
- 自定义采样器模式:若要实现灯光循环显示,可给遮罩采样器添加状态:
sampler MaskSampler = sampler_state { Texture = <MaskTexture>; AddressU = Wrap; AddressV = Wrap; MinFilter = Linear; MagFilter = Linear; }; - 复杂移动逻辑:也可根据玩家位置、预设路径计算
lightOffset,实现跟随或路径移动的灯光效果。
内容的提问来源于stack exchange,提问作者Ne1gh
相关产品推荐
相关产品推荐

