mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-03-21 17:11:30 +00:00
583 lines
22 KiB
C#
583 lines
22 KiB
C#
|
using System;
|
|||
|
using Microsoft.Xna.Framework.Graphics;
|
|||
|
using Microsoft.Xna.Framework;
|
|||
|
|
|||
|
namespace FSO.Common.Utils
|
|||
|
{
|
|||
|
public class TextureGenerator //a fun class for cpu generating textures
|
|||
|
{
|
|||
|
private static Texture2D PxWhite;
|
|||
|
private static Texture2D DefaultAdvLight;
|
|||
|
private static Texture2D PieButtonImg;
|
|||
|
|
|||
|
private static Texture2D InteractionInactive;
|
|||
|
private static Texture2D InteractionActive;
|
|||
|
private static Texture2D CatalogInactive;
|
|||
|
private static Texture2D CatalogActive;
|
|||
|
private static Texture2D CatalogDisabled;
|
|||
|
private static Texture2D PieBG;
|
|||
|
private static Texture2D[] WallZBuffer;
|
|||
|
private static Texture2D[] AirTiles;
|
|||
|
private static Texture2D MotiveArrow; //actually a diamond, clip to get required direction
|
|||
|
private static Texture2D TerrainNoise;
|
|||
|
private static Texture2D UniformNoise;
|
|||
|
|
|||
|
public static Texture2D GetPxWhite(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (PxWhite == null) PxWhite = TextureUtils.TextureFromColor(gd, Color.White);
|
|||
|
return PxWhite;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetDefaultAdv(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (DefaultAdvLight == null) DefaultAdvLight = TextureUtils.TextureFromColor(gd, new Color(128, 0, 0, 255)); //outdoors color max
|
|||
|
return DefaultAdvLight;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetPieButtonImg(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (PieButtonImg == null) PieButtonImg = GenerateRoundedRectangle(gd, new Color(0, 40, 140), 27, 27, 6);
|
|||
|
return PieButtonImg;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetInteractionActive(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (InteractionActive == null) InteractionActive = GenerateObjectIconBorder(gd, new Color(255, 255, 0), new Color(56, 88, 120));
|
|||
|
return InteractionActive;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetInteractionInactive(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (InteractionInactive == null) InteractionInactive = GenerateObjectIconBorder(gd, new Color(128, 128, 128), new Color(56, 88, 120));
|
|||
|
return InteractionInactive;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetCatalogInactive(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (CatalogInactive == null) CatalogInactive = GenerateCatalogIconBorder(gd, new Color(140, 170, 206), new Color(56, 88, 120));
|
|||
|
return CatalogInactive;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetCatalogDisabled(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (CatalogDisabled == null) CatalogDisabled = GenerateCatalogIconBorder(gd, new Color(255, 0, 0), new Color(56, 88, 120));
|
|||
|
return CatalogDisabled;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetCatalogActive(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (CatalogActive == null) CatalogActive = GenerateCatalogIconBorder(gd, new Color(140, 170, 206), new Color(189, 215, 247));
|
|||
|
return CatalogActive;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetPieBG(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (PieBG == null)
|
|||
|
{
|
|||
|
PieBG = new Texture2D(gd, 200, 200);
|
|||
|
Color[] data = new Color[200 * 200];
|
|||
|
int offset = 0;
|
|||
|
for (int y = 0; y < 200; y++)
|
|||
|
{
|
|||
|
for (int x = 0; x < 200; x++)
|
|||
|
{
|
|||
|
data[offset++] = new Color(0, 0, 0, (float)Math.Min(1, 2 - Math.Sqrt(Math.Pow(y - 100, 2) + Math.Pow(x - 100, 2)) / 50) * 0.5f);
|
|||
|
}
|
|||
|
}
|
|||
|
PieBG.SetData<Color>(data);
|
|||
|
}
|
|||
|
|
|||
|
return PieBG;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetMotiveArrow(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (MotiveArrow == null)
|
|||
|
{
|
|||
|
MotiveArrow = new Texture2D(gd, 5, 5);
|
|||
|
Color[] data = new Color[5 * 5];
|
|||
|
var size = new Vector2(5, 5);
|
|||
|
|
|||
|
FillRect(data, size, new Rectangle(2, 0, 1, 1), Color.White);
|
|||
|
FillRect(data, size, new Rectangle(1, 1, 3, 1), Color.White);
|
|||
|
FillRect(data, size, new Rectangle(0, 2, 5, 1), Color.White);
|
|||
|
FillRect(data, size, new Rectangle(1, 3, 3, 1), Color.White);
|
|||
|
FillRect(data, size, new Rectangle(2, 4, 1, 1), Color.White);
|
|||
|
|
|||
|
MotiveArrow.SetData<Color>(data);
|
|||
|
}
|
|||
|
return MotiveArrow;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetTerrainNoise(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (TerrainNoise == null)
|
|||
|
{
|
|||
|
TerrainNoise = new Texture2D(gd, 512, 512, true, SurfaceFormat.Color);
|
|||
|
Color[] data = new Color[512 * 512];
|
|||
|
|
|||
|
var rd = new Random();
|
|||
|
for (int i = 0; i < data.Length; i++)
|
|||
|
{
|
|||
|
//distribution is an average of two noise functions.
|
|||
|
data[i].R = (byte)((rd.Next(255) + rd.Next(255)) / 2);
|
|||
|
data[i].G = (byte)((rd.Next(255) + rd.Next(255)) / 2);
|
|||
|
data[i].B = (byte)((rd.Next(255) + rd.Next(255)) / 2);
|
|||
|
data[i].A = (byte)((rd.Next(255) + rd.Next(255)) / 2);
|
|||
|
}
|
|||
|
TextureUtils.UploadWithMips(TerrainNoise, gd, data);
|
|||
|
}
|
|||
|
return TerrainNoise;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GetUniformNoise(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (UniformNoise == null)
|
|||
|
{
|
|||
|
UniformNoise = new Texture2D(gd, 512, 512, true, SurfaceFormat.Color);
|
|||
|
Color[] data = new Color[512 * 512];
|
|||
|
|
|||
|
var rd = new Random();
|
|||
|
for (int i = 0; i < data.Length; i++)
|
|||
|
{
|
|||
|
//distribution is an average of two noise functions.
|
|||
|
data[i].R = (byte)(rd.Next(255));
|
|||
|
data[i].G = (byte)(rd.Next(255));
|
|||
|
data[i].B = (byte)(rd.Next(255));
|
|||
|
data[i].A = (byte)(rd.Next(255));
|
|||
|
}
|
|||
|
TextureUtils.UploadWithMips(UniformNoise, gd, data);
|
|||
|
}
|
|||
|
return UniformNoise;
|
|||
|
}
|
|||
|
|
|||
|
public static float FLAT_Z_INC = 1.525f;
|
|||
|
public static float[][] WallZBufferConfig = new float[][] {
|
|||
|
// format: width, height, startIntensity, Xdiff, Ydiff
|
|||
|
|
|||
|
new float[] {64, 271, 74, 1, 0.5f}, //near top left
|
|||
|
new float[] {64, 271, 135, -1, 0.5f}, //near top right
|
|||
|
new float[] {128, 240, 89.5f, 0, 0.5f}, //near horiz diag
|
|||
|
new float[] {16, 232, 45, 0, 0.5f}, //near vert diag
|
|||
|
|
|||
|
new float[] {32, 135, 74, 2, 1f}, //med top left
|
|||
|
new float[] {32, 135, 135, -2, 1f}, //med top right
|
|||
|
new float[] {64, 120, 89.5f, 0, 1f}, //med horiz diag
|
|||
|
new float[] {8, 116, 45, 0, 1f}, //med vert diag
|
|||
|
|
|||
|
new float[] {16, 67, 74, 4, 2f}, //far top left
|
|||
|
new float[] {16, 67, 135, -4, 2f}, //far top right
|
|||
|
new float[] {32, 60, 89.5f, 0, 2f}, //far horiz diag
|
|||
|
new float[] {4, 58, 45, 0, 2f}, //far vert diag
|
|||
|
|
|||
|
//12
|
|||
|
new float[] {128, 64, 255, 0, -FLAT_Z_INC}, //near floor
|
|||
|
new float[] {64, 32, 255, 0, -FLAT_Z_INC*2}, //med floor
|
|||
|
new float[] {32, 16, 255, 0, -FLAT_Z_INC*4}, //far floor
|
|||
|
|
|||
|
//vert flips of the above
|
|||
|
//15
|
|||
|
new float[] {128, 64, 153, 0, FLAT_Z_INC},
|
|||
|
new float[] {64, 32, 153, 0, FLAT_Z_INC*2},
|
|||
|
new float[] {32, 16, 153, 0, FLAT_Z_INC*4},
|
|||
|
|
|||
|
//18
|
|||
|
new float[] {128, 64, 263, 0, -FLAT_Z_INC}, //near junction walls up
|
|||
|
new float[] {64, 32, 263, 0, -FLAT_Z_INC*2}, //med junction walls up
|
|||
|
new float[] {32, 16, 263, 0, -FLAT_Z_INC*4}, //far junction walls up
|
|||
|
|
|||
|
|
|||
|
//versions for corners (man this is getting complicated)
|
|||
|
//21
|
|||
|
//top corner
|
|||
|
new float[] {43, 22, 254, 0, -FLAT_Z_INC}, //near
|
|||
|
new float[] {21, 12, 254, 0, -FLAT_Z_INC*2}, //med
|
|||
|
new float[] {13, 7, 254, 0, -FLAT_Z_INC*4}, //far
|
|||
|
|
|||
|
//24
|
|||
|
//side corner
|
|||
|
new float[] {35, 21, 254 - (FLAT_Z_INC* 22), 0, -FLAT_Z_INC}, //near
|
|||
|
new float[] {16, 13, 254 - (FLAT_Z_INC * 22), 0, -FLAT_Z_INC*2}, //med
|
|||
|
new float[] {11, 8, 254 - (FLAT_Z_INC * 22), 0, -FLAT_Z_INC*4}, //far
|
|||
|
|
|||
|
//27
|
|||
|
new float[] {41, 23, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC}, //near
|
|||
|
new float[] {18, 13, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC*2}, //med
|
|||
|
new float[] {9, 8, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC*4}, //far
|
|||
|
|
|||
|
//30
|
|||
|
new float[] {1, 1, 49, 0, 0} //balloon
|
|||
|
};
|
|||
|
|
|||
|
public static Texture2D[] GetWallZBuffer(GraphicsDevice gd)
|
|||
|
{
|
|||
|
float bias = 0f;
|
|||
|
if (WallZBuffer == null)
|
|||
|
{
|
|||
|
var count = WallZBufferConfig.Length;
|
|||
|
WallZBuffer = new Texture2D[count];
|
|||
|
for (int i = 0; i < count; i++)
|
|||
|
{
|
|||
|
var config = WallZBufferConfig[i];
|
|||
|
int width = (int)config[0];
|
|||
|
int height = (int)config[1];
|
|||
|
|
|||
|
WallZBuffer[i] = new Texture2D(gd, width, height);
|
|||
|
Color[] data = new Color[width * height];
|
|||
|
int offset = 0;
|
|||
|
|
|||
|
float yInt = config[2];
|
|||
|
for (int y = 0; y < height; y++)
|
|||
|
{
|
|||
|
float xInt = yInt;
|
|||
|
for (int x = 0; x < width; x++)
|
|||
|
{
|
|||
|
byte zCol = (byte)Math.Round(Math.Min(255, xInt + bias));
|
|||
|
data[offset++] = new Color(zCol, zCol, zCol, zCol);
|
|||
|
xInt += config[3];
|
|||
|
}
|
|||
|
yInt += config[4];
|
|||
|
}
|
|||
|
WallZBuffer[i].SetData<Color>(data);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return WallZBuffer;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D[] GetAirTiles(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (AirTiles == null)
|
|||
|
{
|
|||
|
AirTiles = new Texture2D[3];
|
|||
|
AirTiles[0] = GenerateAirTile(gd, 127, 64);
|
|||
|
AirTiles[1] = GenerateAirTile(gd, 63, 32);
|
|||
|
AirTiles[2] = GenerateAirTile(gd, 31, 16);
|
|||
|
|
|||
|
}
|
|||
|
return AirTiles;
|
|||
|
}
|
|||
|
|
|||
|
private static Texture2D GenerateAirTile(GraphicsDevice gd, int width, int height)
|
|||
|
{
|
|||
|
var tex = new Texture2D(gd, width+1, height);
|
|||
|
Color[] data = new Color[width * height];
|
|||
|
|
|||
|
int center = width/2;
|
|||
|
int middleOff = 0;
|
|||
|
for (int i=0; i<height; i++)
|
|||
|
{
|
|||
|
int index = i * width + (center - middleOff);
|
|||
|
for (int j=0; j<((middleOff==0)?1:2); j++)
|
|||
|
data[index++] = (i+j > height / 2)?Color.Black:Color.White;
|
|||
|
for (int j = 0; j < (middleOff * 2) - 3; j++)
|
|||
|
if (i % 2 == 0 && (i + (center - middleOff)+j) % 4 == 0) data[index++] = Color.Black;
|
|||
|
else index++;
|
|||
|
if (middleOff != 0)
|
|||
|
{
|
|||
|
for (int j = 0; j < 2; j++)
|
|||
|
data[index++] = (i + (1-j) > height / 2) ? Color.Black : Color.White;
|
|||
|
}
|
|||
|
|
|||
|
middleOff += (i == height/2-1)?1:((i<height/2)?2:-2);
|
|||
|
}
|
|||
|
tex.SetData<Color>(FloorCopy(data, width, height));
|
|||
|
return tex;
|
|||
|
}
|
|||
|
|
|||
|
public static Color[] FloorCopy(Color[] data, int width, int height)
|
|||
|
{
|
|||
|
if (width % 2 != 0)
|
|||
|
{
|
|||
|
var target = new Color[(width + 1) * height];
|
|||
|
for (int y = 0; y < height; y++)
|
|||
|
{
|
|||
|
Array.Copy(data, y * width, target, y * (width + 1), width);
|
|||
|
}
|
|||
|
data = target;
|
|||
|
width += 1;
|
|||
|
}
|
|||
|
var ndat = new Color[data.Length];
|
|||
|
int hw = (width) / 2;
|
|||
|
int hh = (height) / 2;
|
|||
|
int idx = 0;
|
|||
|
for (int y = 0; y < height; y++)
|
|||
|
{
|
|||
|
for (int x = 0; x < width; x++)
|
|||
|
{
|
|||
|
var xp = (x + hw) % width;
|
|||
|
var yp = (y + hh) % height;
|
|||
|
var rep = data[xp + yp * width];
|
|||
|
if (rep.A >= 254) ndat[idx] = rep;
|
|||
|
else ndat[idx] = data[idx];
|
|||
|
idx++;
|
|||
|
}
|
|||
|
}
|
|||
|
return ndat;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GenerateObjectIconBorder(GraphicsDevice gd, Color highlight, Color bg)
|
|||
|
{
|
|||
|
var tex = new Texture2D(gd, 45, 45);
|
|||
|
Color[] data = new Color[45*45];
|
|||
|
var size = new Vector2(45, 45);
|
|||
|
|
|||
|
//border
|
|||
|
FillRect(data, size, new Rectangle(3, 0, 39, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(0, 3, 2, 39), highlight);
|
|||
|
FillRect(data, size, new Rectangle(3, 43, 39, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(43, 3, 2, 39), highlight);
|
|||
|
//end border
|
|||
|
|
|||
|
//bg
|
|||
|
FillRect(data, size, new Rectangle(2, 2, 41, 41), bg);
|
|||
|
//end bg
|
|||
|
|
|||
|
//top left rounded
|
|||
|
FillRect(data, size, new Rectangle(2, 1, 2, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(1, 2, 2, 2), highlight);
|
|||
|
|
|||
|
//top right rounded
|
|||
|
FillRect(data, size, new Rectangle(41, 1, 2, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(42, 2, 2, 2), highlight);
|
|||
|
|
|||
|
//btm left rounded
|
|||
|
FillRect(data, size, new Rectangle(1, 41, 2, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(2, 42, 2, 2), highlight);
|
|||
|
|
|||
|
//btm right rounded
|
|||
|
FillRect(data, size, new Rectangle(41, 42, 2, 2), highlight);
|
|||
|
FillRect(data, size, new Rectangle(42, 41, 2, 2), highlight);
|
|||
|
|
|||
|
tex.SetData<Color>(data);
|
|||
|
return tex;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GenerateCatalogIconBorder(GraphicsDevice gd, Color highlight, Color bg)
|
|||
|
{
|
|||
|
var tex = new Texture2D(gd, 41, 41);
|
|||
|
Color[] data = new Color[41 * 41];
|
|||
|
var size = new Vector2(41, 41);
|
|||
|
|
|||
|
//border
|
|||
|
FillRect(data, size, new Rectangle(2, 0, 37, 1), highlight);
|
|||
|
FillRect(data, size, new Rectangle(0, 2, 1, 37), highlight);
|
|||
|
FillRect(data, size, new Rectangle(2, 40, 37, 1), highlight);
|
|||
|
FillRect(data, size, new Rectangle(40, 2, 1, 37), highlight);
|
|||
|
//end border
|
|||
|
|
|||
|
//bg
|
|||
|
FillRect(data, size, new Rectangle(1, 1, 39, 39), bg);
|
|||
|
//end bg
|
|||
|
|
|||
|
//top left rounded
|
|||
|
FillRect(data, size, new Rectangle(1, 1, 1, 1), highlight);
|
|||
|
|
|||
|
//top right rounded
|
|||
|
FillRect(data, size, new Rectangle(39, 1, 1, 1), highlight);
|
|||
|
|
|||
|
//btm left rounded
|
|||
|
FillRect(data, size, new Rectangle(1, 39, 1, 1), highlight);
|
|||
|
|
|||
|
//btm right rounded
|
|||
|
FillRect(data, size, new Rectangle(39, 39, 1, 1), highlight);
|
|||
|
|
|||
|
tex.SetData<Color>(data);
|
|||
|
return tex;
|
|||
|
}
|
|||
|
|
|||
|
public static Texture2D GenerateRoundedRectangle(GraphicsDevice gd, Color color, int width, int height, int radius)
|
|||
|
{
|
|||
|
var tex = new Texture2D(gd, width, height);
|
|||
|
Color[] data = new Color[width * height];
|
|||
|
var size = new Vector2(width, height);
|
|||
|
|
|||
|
//rect fills
|
|||
|
FillRect(data, size, new Rectangle(radius, radius, width - radius * 2, height - radius * 2), color);
|
|||
|
FillRect(data, size, new Rectangle(radius, 0, width - radius * 2, radius), color);
|
|||
|
FillRect(data, size, new Rectangle(radius, height-radius, width - radius * 2, radius), color);
|
|||
|
FillRect(data, size, new Rectangle(0, radius, radius, height-radius*2), color);
|
|||
|
FillRect(data, size, new Rectangle(width - radius, radius, radius, height - radius * 2), color);
|
|||
|
|
|||
|
//corners now
|
|||
|
for (int i = 0; i < radius; i++)
|
|||
|
{
|
|||
|
int seg = (int)Math.Round(Math.Sin(Math.Acos((radius-(i+0.5))/radius))*radius);
|
|||
|
FillRect(data, size, new Rectangle(radius-seg, i, seg, 1), color);
|
|||
|
FillRect(data, size, new Rectangle(width-radius, i, seg, 1), color);
|
|||
|
FillRect(data, size, new Rectangle(radius - seg, height - i - 1, seg, 1), color);
|
|||
|
FillRect(data, size, new Rectangle(width-radius, height - i - 1, seg, 1), color);
|
|||
|
}
|
|||
|
|
|||
|
tex.SetData<Color>(data);
|
|||
|
return tex;
|
|||
|
}
|
|||
|
|
|||
|
private static void FillRect(Color[] data, Vector2 texSize, Rectangle dest, Color fillColor)
|
|||
|
{
|
|||
|
int x;
|
|||
|
int y=dest.Y;
|
|||
|
for (int i = 0; i < dest.Height; i++)
|
|||
|
{
|
|||
|
x = dest.X;
|
|||
|
for (int j = 0; j < dest.Width; j++)
|
|||
|
{
|
|||
|
data[y * (int)texSize.X + x] = fillColor;
|
|||
|
x++;
|
|||
|
}
|
|||
|
y++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static Texture2D Sun;
|
|||
|
public static Texture2D GetSun(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (Sun == null)
|
|||
|
{
|
|||
|
Sun = new Texture2D(gd, 256, 256);
|
|||
|
Color[] data = new Color[256 * 256];
|
|||
|
int offset = 0;
|
|||
|
for (int y = 0; y < 256; y++)
|
|||
|
{
|
|||
|
for (int x = 0; x < 256; x++)
|
|||
|
{
|
|||
|
var distance = Math.Sqrt((y - 128) * (y - 128) + (x - 128) * (x - 128));
|
|||
|
var intensity = (1 - (distance - 25) / 103f);
|
|||
|
if (intensity < 0) data[offset++] = Color.Transparent;
|
|||
|
else
|
|||
|
{
|
|||
|
intensity *= intensity;
|
|||
|
data[offset++] = new Color(1, 1, 1, (float)intensity);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
Sun.SetData<Color>(data);
|
|||
|
}
|
|||
|
|
|||
|
return Sun;
|
|||
|
}
|
|||
|
|
|||
|
private static Texture2D Moon;
|
|||
|
public static Texture2D GetMoon(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (Moon == null)
|
|||
|
{
|
|||
|
Moon = new Texture2D(gd, 64, 64);
|
|||
|
Color[] data = new Color[64 * 64];
|
|||
|
int offset = 0;
|
|||
|
for (int y = 0; y < 64; y++)
|
|||
|
{
|
|||
|
for (int x = 0; x < 64; x++)
|
|||
|
{
|
|||
|
var distance = Math.Sqrt((y - 32) * (y - 32) + (x - 32) * (x - 32));
|
|||
|
var intensity = Math.Min(1, Math.Max(0, 32 - distance));
|
|||
|
|
|||
|
if (intensity > 0)
|
|||
|
{
|
|||
|
//calculate crescent
|
|||
|
if (x < 32) distance = 0;
|
|||
|
else distance = Math.Sqrt((y - 32) * (y - 32) + (x - 32)*2 * (x - 32)*2);
|
|||
|
|
|||
|
intensity *= 0.2f+(1-Math.Min(1, Math.Max(0, 32 - distance)))*0.8f;
|
|||
|
}
|
|||
|
|
|||
|
data[offset++] = new Color(1, 1, 1, (float)intensity);
|
|||
|
}
|
|||
|
}
|
|||
|
Moon.SetData<Color>(data);
|
|||
|
}
|
|||
|
|
|||
|
return Moon;
|
|||
|
}
|
|||
|
|
|||
|
public static Color FromHSV(float h, float s, float v)
|
|||
|
{
|
|||
|
var h2 = (int)h / 60;
|
|||
|
var chroma = s * v; //times value, but it is always one
|
|||
|
var X = chroma * (1 - Math.Abs(((h / 60f) % 2) - 1));
|
|||
|
Color result;
|
|||
|
switch (h2)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
result = new Color(chroma, X, 0); break;
|
|||
|
case 1:
|
|||
|
result = new Color(X, chroma, 0); break;
|
|||
|
case 2:
|
|||
|
result = new Color(0, chroma, X); break;
|
|||
|
case 3:
|
|||
|
result = new Color(0, X, chroma); break;
|
|||
|
case 4:
|
|||
|
result = new Color(X, 0, chroma); break;
|
|||
|
case 5:
|
|||
|
result = new Color(chroma, 0, X); break;
|
|||
|
default:
|
|||
|
result = Color.Black; break; //undefined
|
|||
|
}
|
|||
|
var m = v - chroma;
|
|||
|
var blend = Color.White * m;
|
|||
|
result.R += blend.R;
|
|||
|
result.G += blend.G;
|
|||
|
result.B += blend.B;
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
public static Tuple<float, float, float> ToHSV(Color color)
|
|||
|
{
|
|||
|
var r = color.R / 255f;
|
|||
|
var g = color.G / 255f;
|
|||
|
var b = color.B / 255f;
|
|||
|
var min = Math.Min(Math.Min(r, g), b);
|
|||
|
var max = Math.Max(Math.Max(r, g), b);
|
|||
|
if (min == max) return new Tuple<float, float, float>(0, 0, min);
|
|||
|
|
|||
|
var d = (r == min) ? (g - b) : ((b == min) ? r - g : b - r);
|
|||
|
var h = (r == min) ? 3 : ((b == min) ? 1 : 5);
|
|||
|
return new Tuple<float, float, float>(
|
|||
|
60 * (h - d / (max - min)),
|
|||
|
(max - min) / max,
|
|||
|
max);
|
|||
|
}
|
|||
|
|
|||
|
private static Texture2D HSMatrix;
|
|||
|
public static Texture2D GetHSMatrix(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (HSMatrix == null)
|
|||
|
{
|
|||
|
HSMatrix = new Texture2D(gd, 360, 256);
|
|||
|
Color[] data = new Color[360 * 256];
|
|||
|
int offset = 0;
|
|||
|
for (int y = 0; y < 256; y++) //y is saturation
|
|||
|
{
|
|||
|
for (int x = 0; x < 360; x++) //x is hue
|
|||
|
{
|
|||
|
data[offset++] = FromHSV(x, 1 - (y / 256f), 1f);
|
|||
|
}
|
|||
|
}
|
|||
|
HSMatrix.SetData<Color>(data);
|
|||
|
}
|
|||
|
|
|||
|
return HSMatrix;
|
|||
|
}
|
|||
|
|
|||
|
private static Texture2D HSGrad;
|
|||
|
public static Texture2D GetHSGrad(GraphicsDevice gd)
|
|||
|
{
|
|||
|
if (HSGrad == null)
|
|||
|
{
|
|||
|
HSGrad = new Texture2D(gd, 1, 256);
|
|||
|
Color[] data = new Color[1 * 256];
|
|||
|
int offset = 0;
|
|||
|
for (int y = 0; y < 256; y++) //y is saturation
|
|||
|
{
|
|||
|
var mod = Color.White * (1 - y / 255f);
|
|||
|
mod.A = 255;
|
|||
|
data[offset++] = mod;
|
|||
|
}
|
|||
|
HSGrad.SetData<Color>(data);
|
|||
|
}
|
|||
|
|
|||
|
return HSGrad;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|