Use premultiplied alpha for all textures and blending.
This commit is contained in:
@@ -49,15 +49,9 @@ namespace OpenRA.Graphics
|
|||||||
using (var bitmap = (Bitmap)Image.FromStream(stream))
|
using (var bitmap = (Bitmap)Image.FromStream(stream))
|
||||||
{
|
{
|
||||||
Size = bitmap.Size;
|
Size = bitmap.Size;
|
||||||
|
data = new byte[4 * Size.Width * Size.Height];
|
||||||
|
|
||||||
var dataStride = 4 * Size.Width;
|
Util.FastCopyIntoSprite(new Sprite(this, bitmap.Bounds(), TextureChannel.Red), bitmap);
|
||||||
data = new byte[dataStride * Size.Height];
|
|
||||||
|
|
||||||
var bd = bitmap.LockBits(bitmap.Bounds(),
|
|
||||||
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
|
||||||
for (var y = 0; y < Size.Height; y++)
|
|
||||||
Marshal.Copy(IntPtr.Add(bd.Scan0, y * bd.Stride), data, y * dataStride, dataStride);
|
|
||||||
bitmap.UnlockBits(bd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseBuffer();
|
ReleaseBuffer();
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
// A new bitmap is generated each time this property is accessed, so we do need to dispose it.
|
||||||
using (var bitmap = face.Glyph.Bitmap)
|
using (var bitmap = face.Glyph.Bitmap)
|
||||||
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
var p = (byte*)bitmap.Buffer;
|
var p = (byte*)bitmap.Buffer;
|
||||||
@@ -123,18 +124,23 @@ namespace OpenRA.Graphics
|
|||||||
for (var j = 0; j < s.Size.Y; j++)
|
for (var j = 0; j < s.Size.Y; j++)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < s.Size.X; i++)
|
for (var i = 0; i < s.Size.X; i++)
|
||||||
|
{
|
||||||
if (p[i] != 0)
|
if (p[i] != 0)
|
||||||
{
|
{
|
||||||
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
|
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
|
||||||
dest[q] = c.Second.B;
|
var pmc = Util.PremultiplyAlpha(Color.FromArgb(p[i], c.Second));
|
||||||
dest[q + 1] = c.Second.G;
|
|
||||||
dest[q + 2] = c.Second.R;
|
dest[q] = pmc.B;
|
||||||
dest[q + 3] = p[i];
|
dest[q + 1] = pmc.G;
|
||||||
|
dest[q + 2] = pmc.R;
|
||||||
|
dest[q + 3] = pmc.A;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p += bitmap.Pitch;
|
p += bitmap.Pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s.Sheet.CommitBufferedData();
|
s.Sheet.CommitBufferedData();
|
||||||
|
|
||||||
|
|||||||
@@ -73,18 +73,37 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = dest.Sheet.GetData();
|
var destData = dest.Sheet.GetData();
|
||||||
var dataStride = dest.Sheet.Size.Width * 4;
|
var destStride = dest.Sheet.Size.Width;
|
||||||
var x = dest.Bounds.Left * 4;
|
var width = dest.Bounds.Width;
|
||||||
var width = dest.Bounds.Width * 4;
|
|
||||||
var y = dest.Bounds.Top;
|
|
||||||
var height = dest.Bounds.Height;
|
var height = dest.Bounds.Height;
|
||||||
|
|
||||||
var bd = src.LockBits(src.Bounds(),
|
var srcData = src.LockBits(src.Bounds(),
|
||||||
ImageLockMode.ReadWrite, src.PixelFormat);
|
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
for (var row = 0; row < height; row++)
|
|
||||||
Marshal.Copy(IntPtr.Add(bd.Scan0, row * bd.Stride), data, (y + row) * dataStride + x, width);
|
unsafe
|
||||||
src.UnlockBits(bd);
|
{
|
||||||
|
var c = (int*)srcData.Scan0;
|
||||||
|
|
||||||
|
// Cast the data to an int array so we can copy the src data directly
|
||||||
|
fixed (byte* bd = &destData[0])
|
||||||
|
{
|
||||||
|
var data = (int*)bd;
|
||||||
|
var x = dest.Bounds.Left;
|
||||||
|
var y = dest.Bounds.Top;
|
||||||
|
|
||||||
|
for (var j = 0; j < height; j++)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < width; i++)
|
||||||
|
{
|
||||||
|
var cc = Color.FromArgb(*(c + (j * srcData.Stride >> 2) + i));
|
||||||
|
data[(y + j) * destStride + x + i] = PremultiplyAlpha(cc).ToArgb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
src.UnlockBits(srcData);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -93,6 +112,12 @@ namespace OpenRA.Graphics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Color PremultiplyAlpha(Color c)
|
||||||
|
{
|
||||||
|
var a = c.A / 255f;
|
||||||
|
return Color.FromArgb(c.A, (byte)(c.R * a + 0.5f), (byte)(c.G * a + 0.5f), (byte)(c.B * a + 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
public static float[] IdentityMatrix()
|
public static float[] IdentityMatrix()
|
||||||
{
|
{
|
||||||
return Exts.MakeArray(16, j => (j % 5 == 0) ? 1.0f : 0);
|
return Exts.MakeArray(16, j => (j % 5 == 0) ? 1.0f : 0);
|
||||||
|
|||||||
@@ -643,6 +643,7 @@
|
|||||||
<Compile Include="Traits\World\EditorActorPreview.cs" />
|
<Compile Include="Traits\World\EditorActorPreview.cs" />
|
||||||
<Compile Include="Traits\World\EditorResourceLayer.cs" />
|
<Compile Include="Traits\World\EditorResourceLayer.cs" />
|
||||||
<Compile Include="Widgets\EditorViewportControllerWidget.cs" />
|
<Compile Include="Widgets\EditorViewportControllerWidget.cs" />
|
||||||
|
<Compile Include="Traits\World\PaletteFromPaletteWithAlpha.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2015 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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. For more information,
|
||||||
|
* see COPYING.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.D2k.Traits
|
||||||
|
{
|
||||||
|
[Desc("Create a palette by applying alpha transparency to another palette.")]
|
||||||
|
class PaletteFromPaletteWithAlphaInfo : ITraitInfo
|
||||||
|
{
|
||||||
|
[Desc("Internal palette name")]
|
||||||
|
public readonly string Name = null;
|
||||||
|
|
||||||
|
[Desc("The name of the palette to base off.")]
|
||||||
|
public readonly string BasePalette = null;
|
||||||
|
|
||||||
|
[Desc("Allow palette modifiers to change the palette.")]
|
||||||
|
public readonly bool AllowModifiers = true;
|
||||||
|
|
||||||
|
[Desc("Alpha component that is applied to the base palette.")]
|
||||||
|
public readonly float Alpha = 1.0f;
|
||||||
|
|
||||||
|
[Desc("Premultiply color by the alpha component.")]
|
||||||
|
public readonly bool Premultiply = true;
|
||||||
|
|
||||||
|
public object Create(ActorInitializer init) { return new PaletteFromPaletteWithAlpha(this); }
|
||||||
|
}
|
||||||
|
|
||||||
|
class PaletteFromPaletteWithAlpha : ILoadsPalettes, IProvidesAssetBrowserPalettes
|
||||||
|
{
|
||||||
|
readonly PaletteFromPaletteWithAlphaInfo info;
|
||||||
|
|
||||||
|
public PaletteFromPaletteWithAlpha(PaletteFromPaletteWithAlphaInfo info) { this.info = info; }
|
||||||
|
|
||||||
|
public void LoadPalettes(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
var remap = new AlphaPaletteRemap(info.Alpha, info.Premultiply);
|
||||||
|
wr.AddPalette(info.Name, new ImmutablePalette(wr.Palette(info.BasePalette).Palette, remap), info.AllowModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> PaletteNames { get { yield return info.Name; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlphaPaletteRemap : IPaletteRemap
|
||||||
|
{
|
||||||
|
readonly float alpha;
|
||||||
|
readonly bool premultiply;
|
||||||
|
|
||||||
|
public AlphaPaletteRemap(float alpha, bool premultiply)
|
||||||
|
{
|
||||||
|
this.alpha = alpha;
|
||||||
|
this.premultiply = premultiply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetRemappedColor(Color original, int index)
|
||||||
|
{
|
||||||
|
var a = (int)(original.A * alpha).Clamp(0, 255);
|
||||||
|
var r = premultiply ? (int)(alpha * original.R + 0.5f).Clamp(0, 255) : original.R;
|
||||||
|
var g = premultiply ? (int)(alpha * original.G + 0.5f).Clamp(0, 255) : original.G;
|
||||||
|
var b = premultiply ? (int)(alpha * original.B + 0.5f).Clamp(0, 255) : original.B;
|
||||||
|
|
||||||
|
return Color.FromArgb(a, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -50,7 +51,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (info.Tileset != null && info.Tileset.ToLowerInvariant() != world.Map.Tileset.ToLowerInvariant())
|
if (info.Tileset != null && info.Tileset.ToLowerInvariant() != world.Map.Tileset.ToLowerInvariant())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var c = (uint)((info.A << 24) | (info.R << 16) | (info.G << 8) | info.B);
|
var a = info.A / 255f;
|
||||||
|
var r = (int)(a * info.R + 0.5f).Clamp(0, 255);
|
||||||
|
var g = (int)(a * info.G + 0.5f).Clamp(0, 255);
|
||||||
|
var b = (int)(a * info.B + 0.5f).Clamp(0, 255);
|
||||||
|
var c = (uint)Color.FromArgb(info.A, r, g, b).ToArgb();
|
||||||
wr.AddPalette(info.Name, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => (i == 0) ? 0 : c)), info.AllowModifiers);
|
wr.AddPalette(info.Name, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => (i == 0) ? 0 : c)), info.AllowModifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
static readonly Color[] Fog = new[]
|
static readonly Color[] Fog = new[]
|
||||||
{
|
{
|
||||||
Color.Transparent, Color.Green,
|
Color.FromArgb(0, 0, 0, 0),
|
||||||
Color.Blue, Color.Yellow,
|
Color.Green, Color.Blue, Color.Yellow,
|
||||||
Color.FromArgb(128, 0, 0, 0),
|
Color.FromArgb(128, 0, 0, 0),
|
||||||
Color.FromArgb(96, 0, 0, 0),
|
Color.FromArgb(96, 0, 0, 0),
|
||||||
Color.FromArgb(64, 0, 0, 0),
|
Color.FromArgb(64, 0, 0, 0),
|
||||||
@@ -52,8 +52,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
static readonly Color[] Shroud = new[]
|
static readonly Color[] Shroud = new[]
|
||||||
{
|
{
|
||||||
Color.Transparent, Color.Green,
|
Color.FromArgb(0, 0, 0, 0),
|
||||||
Color.Blue, Color.Yellow,
|
Color.Green, Color.Blue, Color.Yellow,
|
||||||
Color.Black,
|
Color.Black,
|
||||||
Color.FromArgb(160, 0, 0, 0),
|
Color.FromArgb(160, 0, 0, 0),
|
||||||
Color.FromArgb(128, 0, 0, 0),
|
Color.FromArgb(128, 0, 0, 0),
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ namespace OpenRA.Renderer.Sdl2
|
|||||||
case BlendMode.Alpha:
|
case BlendMode.Alpha:
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(EnableCap.Blend);
|
||||||
ErrorHandler.CheckGlError();
|
ErrorHandler.CheckGlError();
|
||||||
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);
|
||||||
break;
|
break;
|
||||||
case BlendMode.Additive:
|
case BlendMode.Additive:
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(EnableCap.Blend);
|
||||||
|
|||||||
@@ -49,6 +49,14 @@
|
|||||||
G: 0
|
G: 0
|
||||||
B: 0
|
B: 0
|
||||||
A: 180
|
A: 180
|
||||||
|
PaletteFromPaletteWithAlpha@effect75alpha:
|
||||||
|
Name: effect75alpha
|
||||||
|
BasePalette: effect
|
||||||
|
Alpha: 0.75
|
||||||
|
PaletteFromPaletteWithAlpha@effect50alpha:
|
||||||
|
Name: effect50alpha
|
||||||
|
BasePalette: effect
|
||||||
|
Alpha: 0.5
|
||||||
PaletteFromScaledPalette@starportlights:
|
PaletteFromScaledPalette@starportlights:
|
||||||
Name: starportlights
|
Name: starportlights
|
||||||
BasePalette: d2k
|
BasePalette: d2k
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ harvester:
|
|||||||
LeavesHusk:
|
LeavesHusk:
|
||||||
HuskActor: Harvester.Husk
|
HuskActor: Harvester.Husk
|
||||||
WithHarvestAnimation:
|
WithHarvestAnimation:
|
||||||
|
Palette: effect50alpha
|
||||||
AttractsWorms:
|
AttractsWorms:
|
||||||
Intensity: 700
|
Intensity: 700
|
||||||
|
|
||||||
|
|||||||
@@ -71,30 +71,24 @@ small_trail:
|
|||||||
Start: 3735
|
Start: 3735
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: SoftAdditive
|
|
||||||
|
|
||||||
small_trail2:
|
small_trail2:
|
||||||
idle: DATA.R8
|
idle: DATA.R8
|
||||||
Start: 3540
|
Start: 3540
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: SoftAdditive
|
|
||||||
|
|
||||||
bazooka_trail:
|
bazooka_trail:
|
||||||
idle: DATA.R8
|
idle: DATA.R8
|
||||||
Start: 3381
|
Start: 3381
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: Translucency
|
|
||||||
Alpha: 0.75
|
|
||||||
|
|
||||||
bazooka_trail2:
|
bazooka_trail2:
|
||||||
idle: DATA.R8
|
idle: DATA.R8
|
||||||
Start: 3544
|
Start: 3544
|
||||||
Length: 4
|
Length: 4
|
||||||
Tick: 80
|
Tick: 80
|
||||||
BlendMode: Translucency
|
|
||||||
Alpha: 0.75
|
|
||||||
|
|
||||||
deviator_trail:
|
deviator_trail:
|
||||||
idle: DATA.R8
|
idle: DATA.R8
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ harvester:
|
|||||||
Tick: 80
|
Tick: 80
|
||||||
ZOffset: 1
|
ZOffset: 1
|
||||||
BlendMode: Multiply
|
BlendMode: Multiply
|
||||||
Alpha: 0.5
|
|
||||||
dock: DATA.R8
|
dock: DATA.R8
|
||||||
Start: 3370
|
Start: 3370
|
||||||
Length: 10
|
Length: 10
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ Bazooka:
|
|||||||
Image: RPG
|
Image: RPG
|
||||||
RateOfTurn: 5
|
RateOfTurn: 5
|
||||||
Trail: bazooka_trail
|
Trail: bazooka_trail
|
||||||
|
TrailPalette: effect75alpha
|
||||||
TrailInterval: 1
|
TrailInterval: 1
|
||||||
RangeLimit: 35
|
RangeLimit: 35
|
||||||
Warhead@1Dam: SpreadDamage
|
Warhead@1Dam: SpreadDamage
|
||||||
@@ -193,6 +194,7 @@ QuadRockets:
|
|||||||
Image: RPG
|
Image: RPG
|
||||||
RateOfTurn: 10
|
RateOfTurn: 10
|
||||||
Trail: bazooka_trail2
|
Trail: bazooka_trail2
|
||||||
|
TrailPalette: effect75alpha
|
||||||
TrailInterval: 1
|
TrailInterval: 1
|
||||||
Speed: 256
|
Speed: 256
|
||||||
RangeLimit: 40
|
RangeLimit: 40
|
||||||
|
|||||||
@@ -73,6 +73,10 @@
|
|||||||
G: 0
|
G: 0
|
||||||
B: 0
|
B: 0
|
||||||
A: 180
|
A: 180
|
||||||
|
PaletteFromPaletteWithAlpha@placebuilding:
|
||||||
|
Name: placebuilding
|
||||||
|
BasePalette: ra
|
||||||
|
Alpha: 0.75
|
||||||
TSShroudPalette@shroud:
|
TSShroudPalette@shroud:
|
||||||
Type: Shroud
|
Type: Shroud
|
||||||
VoxelNormalsPalette@normals:
|
VoxelNormalsPalette@normals:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Player:
|
|||||||
LowPowerSlowdown: 3
|
LowPowerSlowdown: 3
|
||||||
SpeedUp: True
|
SpeedUp: True
|
||||||
PlaceBuilding:
|
PlaceBuilding:
|
||||||
Palette: ra
|
Palette: placebuilding
|
||||||
SupportPowerManager:
|
SupportPowerManager:
|
||||||
ScriptTriggers:
|
ScriptTriggers:
|
||||||
MissionObjectives:
|
MissionObjectives:
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
overlay:
|
overlay:
|
||||||
Defaults: place
|
Defaults: place
|
||||||
Offset: 0, -12
|
Offset: 0, -12
|
||||||
BlendMode: Translucency
|
|
||||||
Alpha: 0.75
|
|
||||||
build-valid-snow:
|
build-valid-snow:
|
||||||
build-valid-temperat:
|
build-valid-temperat:
|
||||||
build-invalid:
|
build-invalid:
|
||||||
@@ -114,10 +112,10 @@ explosion:
|
|||||||
Length: *
|
Length: *
|
||||||
building: twlt070
|
building: twlt070
|
||||||
ionring: ring1
|
ionring: ring1
|
||||||
BlendMode: SoftAdditive
|
BlendMode: Additive
|
||||||
Tick: 120
|
Tick: 120
|
||||||
pulse_explosion: pulsefx2
|
pulse_explosion: pulsefx2
|
||||||
BlendMode: SoftAdditive
|
BlendMode: Additive
|
||||||
Tick: 80
|
Tick: 80
|
||||||
small_watersplash: h2o_exp2
|
small_watersplash: h2o_exp2
|
||||||
large_watersplash: h2o_exp1
|
large_watersplash: h2o_exp1
|
||||||
|
|||||||
Reference in New Issue
Block a user