Implement sonic blast rendering effect.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
3111d06fcf
commit
5da2f1ba8a
65
OpenRA.Mods.D2k/Graphics/SonicBlastRenderable.cs
Normal file
65
OpenRA.Mods.D2k/Graphics/SonicBlastRenderable.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.D2k.Traits;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.D2k.Graphics
|
||||||
|
{
|
||||||
|
public class SonicBlastRenderable : IRenderable, IFinalizedRenderable
|
||||||
|
{
|
||||||
|
public static readonly IEnumerable<IRenderable> None = Array.Empty<IRenderable>();
|
||||||
|
readonly SonicBlastRenderer renderer;
|
||||||
|
readonly float3 r;
|
||||||
|
|
||||||
|
public WPos Pos { get; }
|
||||||
|
public int ZOffset => 0;
|
||||||
|
|
||||||
|
public SonicBlastRenderable(SonicBlastRenderer renderer, WPos pos)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
Pos = pos;
|
||||||
|
r = renderer.Info.Size * new float3(0.5f, 0.5f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDecoration => false;
|
||||||
|
|
||||||
|
public IRenderable WithZOffset(int newOffset) => this;
|
||||||
|
public IRenderable OffsetBy(in WVec offset) => this;
|
||||||
|
public IRenderable AsDecoration() => this;
|
||||||
|
|
||||||
|
public IFinalizedRenderable PrepareRender(WorldRenderer wr) { return this; }
|
||||||
|
|
||||||
|
public void Render(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
renderer.Draw(wr.Screen3DPxPosition(Pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RenderDebugGeometry(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
var pos = wr.Screen3DPxPosition(Pos);
|
||||||
|
var tl = wr.Viewport.WorldToViewPx(pos - r);
|
||||||
|
var br = wr.Viewport.WorldToViewPx(pos + r);
|
||||||
|
Game.Renderer.RgbaColorRenderer.DrawRect(tl, br, 1, Color.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle ScreenBounds(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
var pos = wr.Screen3DPxPosition(Pos);
|
||||||
|
var tl = wr.Viewport.WorldToViewPx(pos - r);
|
||||||
|
var br = wr.Viewport.WorldToViewPx(pos + r);
|
||||||
|
return new Rectangle(tl.X, tl.Y, br.X - tl.X, br.Y - tl.Y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,9 +14,9 @@ using System.Linq;
|
|||||||
using OpenRA.GameRules;
|
using OpenRA.GameRules;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common;
|
using OpenRA.Mods.Common;
|
||||||
using OpenRA.Mods.Common.Graphics;
|
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Mods.D2k.Graphics;
|
||||||
|
using OpenRA.Mods.D2k.Traits;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.D2k.Projectiles
|
namespace OpenRA.Mods.D2k.Projectiles
|
||||||
@@ -30,9 +30,6 @@ namespace OpenRA.Mods.D2k.Projectiles
|
|||||||
[Desc("The number of ticks between the blast causing warhead impacts in its area of effect.")]
|
[Desc("The number of ticks between the blast causing warhead impacts in its area of effect.")]
|
||||||
public readonly int DamageInterval = 1;
|
public readonly int DamageInterval = 1;
|
||||||
|
|
||||||
[Desc("Equivalent to sequence ZOffset. Controls Z sorting.")]
|
|
||||||
public readonly int ZOffset = 0;
|
|
||||||
|
|
||||||
[Desc("The minimum distance the blast travels.")]
|
[Desc("The minimum distance the blast travels.")]
|
||||||
public readonly WDist MinDistance = WDist.Zero;
|
public readonly WDist MinDistance = WDist.Zero;
|
||||||
|
|
||||||
@@ -57,9 +54,6 @@ namespace OpenRA.Mods.D2k.Projectiles
|
|||||||
[Desc("Can this projectile be blocked when hitting actors with an nameof(BlocksProjectiles) trait.")]
|
[Desc("Can this projectile be blocked when hitting actors with an nameof(BlocksProjectiles) trait.")]
|
||||||
public readonly bool Blockable = false;
|
public readonly bool Blockable = false;
|
||||||
|
|
||||||
[Desc("Color of the blast.")]
|
|
||||||
public readonly Color Color = Color.SkyBlue;
|
|
||||||
|
|
||||||
public IProjectile Create(ProjectileArgs args)
|
public IProjectile Create(ProjectileArgs args)
|
||||||
{
|
{
|
||||||
return new SonicBlast(this, args);
|
return new SonicBlast(this, args);
|
||||||
@@ -72,6 +66,7 @@ namespace OpenRA.Mods.D2k.Projectiles
|
|||||||
readonly ProjectileArgs args;
|
readonly ProjectileArgs args;
|
||||||
|
|
||||||
readonly WDist speed;
|
readonly WDist speed;
|
||||||
|
readonly SonicBlastRenderer renderer;
|
||||||
|
|
||||||
[Sync]
|
[Sync]
|
||||||
WPos pos, lastPos;
|
WPos pos, lastPos;
|
||||||
@@ -85,6 +80,8 @@ namespace OpenRA.Mods.D2k.Projectiles
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
var world = args.SourceActor.World;
|
var world = args.SourceActor.World;
|
||||||
|
renderer = world.WorldActor.Trait<SonicBlastRenderer>();
|
||||||
|
|
||||||
if (info.Speed.Length > 1)
|
if (info.Speed.Length > 1)
|
||||||
speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
|
speed = new WDist(world.SharedRandom.Next(info.Speed[0].Length, info.Speed[1].Length));
|
||||||
else
|
else
|
||||||
@@ -151,10 +148,7 @@ namespace OpenRA.Mods.D2k.Projectiles
|
|||||||
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
public IEnumerable<IRenderable> Render(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
if (!wr.World.FogObscures(pos))
|
if (!wr.World.FogObscures(pos))
|
||||||
{
|
return new[] { (IRenderable)new SonicBlastRenderable(renderer, pos) };
|
||||||
var blastRender = new BeamRenderable(pos, info.ZOffset, lastPos - pos, BeamRenderableShape.Cylindrical, info.Width, info.Color);
|
|
||||||
return new[] { (IRenderable)blastRender };
|
|
||||||
}
|
|
||||||
|
|
||||||
return SpriteRenderable.None;
|
return SpriteRenderable.None;
|
||||||
}
|
}
|
||||||
|
|||||||
96
OpenRA.Mods.D2k/Traits/World/SonicBlastRenderer.cs
Normal file
96
OpenRA.Mods.D2k/Traits/World/SonicBlastRenderer.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright (c) The OpenRA Developers and Contributors
|
||||||
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
|
* available to you under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version. For more
|
||||||
|
* information, see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.D2k.Traits
|
||||||
|
{
|
||||||
|
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
|
||||||
|
[Desc("Renders sonic blasts")]
|
||||||
|
public class SonicBlastRendererInfo : TraitInfo
|
||||||
|
{
|
||||||
|
[Desc("Diameter of the sonic effect circle.")]
|
||||||
|
public readonly int Size = 16;
|
||||||
|
|
||||||
|
[Desc("Amount to scale the visuals within the effect circle.")]
|
||||||
|
public readonly float Zoom = 2.5f;
|
||||||
|
|
||||||
|
public override object Create(ActorInitializer init) { return new SonicBlastRenderer(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class SonicBlastRenderer : IRenderPostProcessPass, INotifyActorDisposing
|
||||||
|
{
|
||||||
|
public readonly SonicBlastRendererInfo Info;
|
||||||
|
|
||||||
|
readonly Renderer renderer;
|
||||||
|
readonly IShader shader;
|
||||||
|
readonly IVertexBuffer<RenderPostProcessPassTexturedVertex> buffer;
|
||||||
|
readonly List<float3> positions = new();
|
||||||
|
|
||||||
|
public SonicBlastRenderer(SonicBlastRendererInfo info)
|
||||||
|
{
|
||||||
|
Info = info;
|
||||||
|
renderer = Game.Renderer;
|
||||||
|
shader = renderer.CreateShader(new RenderPostProcessPassTexturedShaderBindings("sonic"));
|
||||||
|
buffer = renderer.CreateVertexBuffer<RenderPostProcessPassTexturedVertex>(6);
|
||||||
|
|
||||||
|
var r = 0.5f * info.Size;
|
||||||
|
shader.SetVec("Scale", r * (1f / info.Zoom - 1));
|
||||||
|
var vertices = new RenderPostProcessPassTexturedVertex[]
|
||||||
|
{
|
||||||
|
new(-r, -r, -1, -1),
|
||||||
|
new(r, -r, 1, -1),
|
||||||
|
new(r, r, 1, 1),
|
||||||
|
new(r, r, 1, 1),
|
||||||
|
new(-r, r, -1, 1),
|
||||||
|
new(-r, -r, -1, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
buffer.SetData(ref vertices, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(float3 pos)
|
||||||
|
{
|
||||||
|
positions.Add(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
PostProcessPassType IRenderPostProcessPass.Type => PostProcessPassType.AfterWorld;
|
||||||
|
bool IRenderPostProcessPass.Enabled => positions.Count > 0;
|
||||||
|
|
||||||
|
void IRenderPostProcessPass.Draw(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
var scroll = wr.Viewport.TopLeft;
|
||||||
|
var size = renderer.WorldFrameBufferSize;
|
||||||
|
var width = 2f / (renderer.WorldDownscaleFactor * size.Width);
|
||||||
|
var height = 2f / (renderer.WorldDownscaleFactor * size.Height);
|
||||||
|
|
||||||
|
shader.SetVec("Scroll", scroll.X, scroll.Y);
|
||||||
|
shader.SetVec("p1", width, height);
|
||||||
|
shader.SetVec("p2", -1, -1);
|
||||||
|
shader.SetTexture("WorldTexture", Game.Renderer.WorldBufferSnapshot());
|
||||||
|
shader.PrepareRender();
|
||||||
|
foreach (var pos in positions)
|
||||||
|
{
|
||||||
|
shader.SetVec("Pos", pos.X, pos.Y);
|
||||||
|
renderer.DrawBatch(buffer, shader, 0, 6, PrimitiveType.TriangleList);
|
||||||
|
}
|
||||||
|
|
||||||
|
positions.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void INotifyActorDisposing.Disposing(Actor self)
|
||||||
|
{
|
||||||
|
buffer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
glsl/postprocess_textured_sonic.frag
Normal file
18
glsl/postprocess_textured_sonic.frag
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#version {VERSION}
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2D WorldTexture;
|
||||||
|
uniform float Scale;
|
||||||
|
|
||||||
|
in vec2 vTexCoord;
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
if (dot(vTexCoord, vTexCoord) >= 1.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
fragColor = texelFetch(WorldTexture, ivec2(gl_FragCoord.xy + Scale * vTexCoord), 0);
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
TerrainGeometryOverlay:
|
TerrainGeometryOverlay:
|
||||||
DebugVisualizations:
|
DebugVisualizations:
|
||||||
TerrainRenderer:
|
TerrainRenderer:
|
||||||
|
SonicBlastRenderer:
|
||||||
ShroudRenderer:
|
ShroudRenderer:
|
||||||
ShroudVariants: shrouda, shroudb, shroudc, shroudd
|
ShroudVariants: shrouda, shroudb, shroudc, shroudd
|
||||||
FogVariants: foga, fogb, fogc, fogd
|
FogVariants: foga, fogb, fogc, fogd
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ Sound:
|
|||||||
Falloff: 0, 0, 100, 0
|
Falloff: 0, 0, 100, 0
|
||||||
Range: 0, 0c512, 4c0, 6c0
|
Range: 0, 0c512, 4c0, 6c0
|
||||||
MinDistance: 5c0
|
MinDistance: 5c0
|
||||||
Color: 00FFFFC8
|
|
||||||
Warhead@1Dam: SpreadDamage
|
Warhead@1Dam: SpreadDamage
|
||||||
Falloff: 100, 0
|
Falloff: 100, 0
|
||||||
Spread: 1c756
|
Spread: 1c756
|
||||||
|
|||||||
Reference in New Issue
Block a user