Browse Source

Alpha blending support for Canvases.

* Canvas objects now support a few different blending modes.
    * Canvas.HasTexture now has a private setter.
    * Updated, corrected, and filled in missing XMLDocs.
    * Added some "fancy" alpha blending stuff in Sample.Sprites.
improved_timing
Ian Burgmyer 5 years ago
parent
commit
4e54f841fc
  1. 26
      DotSDL/Graphics/BlendMode.cs
  2. 29
      DotSDL/Graphics/Canvas.cs
  3. 4
      DotSDL/Graphics/ScalingQuality.cs
  4. 5
      DotSDL/Graphics/SdlWindow.cs
  5. 11
      DotSDL/Interop/Core/Render.cs
  6. 9
      Samples/Sample.Sprites/Player.cs
  7. 4
      Samples/Sample.Sprites/Window.cs

26
DotSDL/Graphics/BlendMode.cs

@ -0,0 +1,26 @@
namespace DotSDL.Graphics {
/// <summary>
/// The blend mode that should be used when plotting an texture.
/// </summary>
/// <!-- This enum must match SDL_BlendMode. -->
public enum BlendMode {
/// <summary>
/// No blending is performed. The source will be copied directly to the
/// destination.
/// </summary>
None,
/// <summary>
/// Alpha blending will be performed. This uses the alpha channel of the
/// texture to control the texture's visibility when the copy operation
/// is performed.
/// </summary>
Alpha,
/// <summary>
/// Additive blending will be performed. The source's RGB value, modified
/// by the alpha channel, will be added to that of that destination
/// </summary>
Additive
}
}

29
DotSDL/Graphics/Canvas.cs

@ -13,7 +13,7 @@ namespace DotSDL.Graphics {
/// <summary>
/// <c>true</c> if this <see cref="Canvas"/> has an SDL texture associated with it, otherwise <c>false</c>.
/// </summary>
protected bool HasTexture { get; set; }
protected bool HasTexture { get; private set; }
/// <summary>
/// The scaling type that should be used to draw this <see cref="Canvas"/>. This field should not be
@ -22,9 +22,19 @@ namespace DotSDL.Graphics {
protected ScalingQuality ScalingQualityValue;
/// <summary>
/// The SDL_Texture that this <see cref="Canvas"/> maintains.
/// The blend mode that should be used to draw this <see cref="Canvas"/>. This field should
/// not be manipulated directly--use <see cref="BlendMode"/> instead.
/// </summary>
protected BlendMode BlendModeValue = BlendMode.Alpha;
/// <summary>
/// The SDL_Renderer that this <see cref="Canvas"/> will be drawn by.
/// </summary>
internal IntPtr Renderer;
/// <summary>
/// The SDL_Texture that this <see cref="Canvas"/> maintains.
/// </summary>
internal IntPtr Texture;
/// <summary>
@ -37,8 +47,8 @@ namespace DotSDL.Graphics {
/// useful if you're maintaining your own ARGB framebuffer and don't plan to use DotSDL's <see cref="Canvas"/>
/// object. You usually do not need to override this method.
/// </summary>
/// <remarks>If an invalid <see cref="IntPtr"/> is generated by this method, your application may
/// crash with a segmentation fault. When in doubt, override <see cref="OnDraw"/> instead!</remarks>
/// <remarks>If an invalid <see cref="IntPtr"/> is generated by this method, your application will
/// crash with a segmentation fault.</remarks>
/// <returns>An <see cref="IntPtr"/> containing the contents of the window's background.</returns>
public Func<IntPtr> GetCanvasPointer;
@ -68,6 +78,16 @@ namespace DotSDL.Graphics {
}
}
public BlendMode BlendMode {
get => BlendModeValue;
set {
BlendModeValue = value;
if(HasTexture)
Render.SetTextureBlendMode(Texture, BlendModeValue);
}
}
/// <summary>
/// Determines the method that will be used to scale this sprite when it is plotted to the
/// screen.
@ -138,6 +158,7 @@ namespace DotSDL.Graphics {
Texture = Render.CreateTexture(Renderer, SdlPixels.PixelFormatArgb8888, textureAccess, Width, Height);
HasTexture = true;
Render.SetTextureBlendMode(Texture, BlendModeValue);
}
/// <summary>

4
DotSDL/Graphics/ScalingQuality.cs

@ -1,6 +1,8 @@
namespace DotSDL.Graphics {
/// <summary>
/// The scaling (filtering) style that should be used for the application.</summary>
/// The scaling (filtering) style that should be used for the application or a texture.
/// </summary>
/// <!-- This enum must match the values that are valid for SDL_HINT_RENDER_SCALE_QUALITY. -->
public enum ScalingQuality {
/// <summary>
/// Nearest pixel sampling. This should be used if crisp, square pixels are desired.

5
DotSDL/Graphics/SdlWindow.cs

@ -160,7 +160,10 @@ namespace DotSDL.Graphics {
ScalingQuality = scalingQuality;
CreateTexture();
Background = new Canvas(textureWidth, textureHeight) { Renderer = _renderer };
Background = new Canvas(textureWidth, textureHeight) {
Renderer = _renderer,
BlendMode = BlendMode.None
};
Background.CreateTexture();
Sprites = new SpriteList(_renderer);

11
DotSDL/Interop/Core/Render.cs

@ -152,10 +152,19 @@ namespace DotSDL.Interop.Core {
/// <param name="renderer">The rendering context.</param>
/// <param name="texture">The targeted texture, or <see cref="IntPtr.Zero"/> for the default render target.
/// If a texture is used, it must have been created with the <see cref="TextureAccess.Target"/> flag.</param>
/// <returns></returns>
/// <returns>Returns 0 on success or a negative error code on failure.</returns>
[DllImport(Meta.CoreLib, EntryPoint = "SDL_SetRenderTarget", CallingConvention = CallingConvention.Cdecl)]
internal static extern int SetRenderTarget(IntPtr renderer, IntPtr texture);
/// <summary>
/// Sets the blend mode for a texture, used by <see cref="RenderCopy(System.IntPtr,System.IntPtr,DotSDL.Interop.Core.Rect.SdlRect,DotSDL.Interop.Core.Rect.SdlRect)"/>.
/// </summary>
/// <param name="texture">The texture to update.</param>
/// <param name="blendMode">The <see cref="BlendMode"/> to use for texture blending.</param>
/// <returns>Returns 0 on success or a negative error code on failure.</returns>
[DllImport(Meta.CoreLib, EntryPoint = "SDL_SetTextureBlendMode", CallingConvention = CallingConvention.Cdecl)]
internal static extern int SetTextureBlendMode(IntPtr texture, BlendMode blendMode);
/// <summary>
/// Update the given texture rectangle with new pixel data.
/// </summary>

9
Samples/Sample.Sprites/Player.cs

@ -9,6 +9,8 @@ namespace Sample.Sprites {
private int _speed;
public Player(Color color, int speed, int playerId) : base(Size, Size, playerId) {
const int baseAlpha = 128;
_color = color;
_speed = speed;
@ -35,7 +37,10 @@ namespace Sample.Sprites {
}
}
// Increase the brightness as we move further inside.
// Increase the brightness and alpha as we move further inside.
_color.A = (byte)(baseAlpha + ((float)Radius - x + 1) / Radius * (255 - baseAlpha));
System.Console.WriteLine(_color.A);
var newR = (short)(_color.R * 1.1);
_color.R = (byte)(newR > 255 ? 255 : newR);
@ -48,7 +53,7 @@ namespace Sample.Sprites {
// Plot a little line so that we can show rotation.
for(var y = Radius; y >= 0; y--) {
Pixels[GetIndex(Radius, y)] = new Color { R = 64, G = 255, B = 64 };
Pixels[GetIndex(Radius, y)] = new Color { R = 64, G = 255, B = 64, A = 255 };
}
}

4
Samples/Sample.Sprites/Window.cs

@ -2,7 +2,6 @@
using DotSDL.Graphics;
using DotSDL.Input.Keyboard;
using System;
using System.Numerics;
namespace Sample.Sprites {
public class Window : SdlWindow {
@ -40,7 +39,7 @@ namespace Sample.Sprites {
}
}
// Darken every other layer, because why not. :)
// Darken every other line, because why not. :)
for(var y = 2; y < Background.Height; y += 2) {
for(var x = 0; x < Background.Width; x++) {
var pix = Background.Width * y + x;
@ -89,6 +88,7 @@ namespace Sample.Sprites {
_player2Delta = new Point();
_player1.Scale.X = 1.5f;
_player1.BlendMode = BlendMode.Additive;
_player2.ScalingQuality = ScalingQuality.Linear;
_player2.Scale.Y = 2.0f;

Loading…
Cancel
Save