1433 lines
49 KiB
C#
1433 lines
49 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
using OpenTK;
|
|
using OpenTK.Graphics.OpenGL;
|
|
|
|
using Vocaluxe.Base;
|
|
using Vocaluxe.Menu;
|
|
|
|
namespace Vocaluxe.Lib.Draw
|
|
{
|
|
struct SClientRect
|
|
{
|
|
public Point location;
|
|
public int width;
|
|
public int height;
|
|
};
|
|
|
|
struct STextureQueque
|
|
{
|
|
public int ID;
|
|
public int width;
|
|
public int height;
|
|
public byte[] data;
|
|
}
|
|
|
|
class COpenGL : Form, IDraw
|
|
{
|
|
#region private vars
|
|
|
|
private CKeys _Keys;
|
|
private CMouse _Mouse;
|
|
private bool _Run;
|
|
|
|
GLControl control = null;
|
|
|
|
private SClientRect _restore;
|
|
private bool _fullscreen = false;
|
|
|
|
private Dictionary<int, STexture> _Textures;
|
|
private Queue<int> _IDs;
|
|
private List<STextureQueque> _Queque;
|
|
|
|
private Object MutexTexture = new Object();
|
|
|
|
private int h = 1;
|
|
private int w = 1;
|
|
private int y = 0;
|
|
private int x = 0;
|
|
|
|
private bool _UsePBO = false;
|
|
|
|
#endregion private vars
|
|
|
|
public COpenGL()
|
|
{
|
|
this.Icon = new System.Drawing.Icon(Path.Combine(System.Environment.CurrentDirectory, CSettings.sIcon));
|
|
|
|
_Textures = new Dictionary<int, STexture>();
|
|
_Queque = new List<STextureQueque>();
|
|
_IDs = new Queue<int>(1000000);
|
|
|
|
for (int i = 1; i < 1000000; i++)
|
|
{
|
|
_IDs.Enqueue(i);
|
|
}
|
|
|
|
//Check AA Mode
|
|
CConfig.AAMode = (EAntiAliasingModes)CheckAntiAliasingMode((int)CConfig.AAMode);
|
|
|
|
OpenTK.Graphics.ColorFormat cf = new OpenTK.Graphics.ColorFormat(32);
|
|
OpenTK.Graphics.GraphicsMode gm;
|
|
|
|
bool ok = false;
|
|
try
|
|
{
|
|
gm = new OpenTK.Graphics.GraphicsMode(cf, 24, 0, (int)CConfig.AAMode);
|
|
control = new GLControl(gm, 2, 1, OpenTK.Graphics.GraphicsContextFlags.Default);
|
|
if (control.GraphicsMode != null)
|
|
ok = true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
ok = false;
|
|
}
|
|
|
|
if (!ok)
|
|
control = new GLControl();
|
|
|
|
control.MakeCurrent();
|
|
control.VSync = (CConfig.VSync == EOffOn.TR_CONFIG_ON);
|
|
|
|
this.Controls.Add(control);
|
|
|
|
|
|
_Keys = new CKeys();
|
|
this.Paint += new PaintEventHandler(this.OnPaintEvent);
|
|
this.Closing += new CancelEventHandler(this.OnClosingEvent);
|
|
this.Resize += new EventHandler(this.OnResizeEvent);
|
|
|
|
control.KeyDown += new KeyEventHandler(this.OnKeyDownEvent);
|
|
control.PreviewKeyDown += new PreviewKeyDownEventHandler(this.OnPreviewKeyDownEvent);
|
|
control.KeyPress += new KeyPressEventHandler(this.OnKeyPressEvent);
|
|
control.KeyUp += new KeyEventHandler(this.OnKeyUpEvent);
|
|
|
|
_Mouse = new CMouse();
|
|
control.MouseMove += new MouseEventHandler(this.OnMouseMove);
|
|
control.MouseWheel += new MouseEventHandler(this.OnMouseWheel);
|
|
control.MouseDown += new MouseEventHandler(this.OnMouseDown);
|
|
control.MouseUp += new MouseEventHandler(this.OnMouseUp);
|
|
control.MouseLeave += new EventHandler(this.OnMouseLeave);
|
|
control.MouseEnter += new EventHandler(this.OnMouseEnter);
|
|
|
|
this.ClientSize = new Size(CConfig.ScreenW, CConfig.ScreenH);
|
|
this.CenterToScreen();
|
|
}
|
|
|
|
#region Helpers
|
|
private int CheckAntiAliasingMode(int SetValue)
|
|
{
|
|
int _Result = 0;
|
|
OpenTK.Graphics.GraphicsMode _mode = null;
|
|
bool _done = false;
|
|
|
|
while (!_done && (_Result <= 32))
|
|
{
|
|
try
|
|
{
|
|
_mode = new OpenTK.Graphics.GraphicsMode(16, 0, 0, _Result);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_done = true;
|
|
_Result /= 2;
|
|
if (_Result == 1)
|
|
_Result = 0;
|
|
}
|
|
|
|
if (_mode != null)
|
|
{
|
|
try
|
|
{
|
|
if (_mode.Samples == _Result)
|
|
{
|
|
if (_Result == 0)
|
|
_Result = 2;
|
|
else
|
|
_Result *= 2;
|
|
}
|
|
else
|
|
{
|
|
_done = true;
|
|
_Result /= 2;
|
|
if (_Result == 1)
|
|
_Result = 0;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_done = true;
|
|
_Result /= 2;
|
|
if (_Result == 1)
|
|
_Result = 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
_done = true;
|
|
_Result /= 2;
|
|
if (_Result == 1)
|
|
_Result = 0;
|
|
}
|
|
|
|
}
|
|
|
|
if (_Result > 64)
|
|
_Result = 32;
|
|
|
|
if (SetValue < _Result)
|
|
return SetValue;
|
|
else
|
|
return _Result;
|
|
}
|
|
|
|
private int CheckColorDeep(int SetValue)
|
|
{
|
|
int _Result = 8;
|
|
OpenTK.Graphics.GraphicsMode _mode = null;
|
|
bool _done = false;
|
|
|
|
while (!_done && (_Result <= 32))
|
|
{
|
|
try
|
|
{
|
|
_mode = new OpenTK.Graphics.GraphicsMode(_Result, 0, 0, 0);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_done = true;
|
|
_Result -= 8;
|
|
if (_Result == 0)
|
|
_Result = 8;
|
|
}
|
|
|
|
if (_mode != null)
|
|
{
|
|
try
|
|
{
|
|
if (_mode.ColorFormat == _Result)
|
|
{
|
|
_Result += 8;
|
|
}
|
|
else
|
|
{
|
|
_done = true;
|
|
_Result -= 8;
|
|
if (_Result == 0)
|
|
_Result = 8;
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_done = true;
|
|
_Result -= 8;
|
|
if (_Result == 0)
|
|
_Result = 8;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
_done = true;
|
|
_Result -= 8;
|
|
if (_Result == 0)
|
|
_Result = 8;
|
|
}
|
|
}
|
|
|
|
if (_Result > 32)
|
|
_Result = 32;
|
|
|
|
if (SetValue < _Result)
|
|
return SetValue;
|
|
else
|
|
return _Result;
|
|
}
|
|
|
|
private void ToggleFullScreen()
|
|
{
|
|
if (!_fullscreen)
|
|
EnterFullScreen();
|
|
else
|
|
LeaveFullScreen();
|
|
}
|
|
|
|
private void EnterFullScreen()
|
|
{
|
|
_fullscreen = true;
|
|
CConfig.FullScreen = EOffOn.TR_CONFIG_ON;
|
|
|
|
_restore.location = this.Location;
|
|
_restore.width = this.Width;
|
|
_restore.height = this.Height;
|
|
|
|
this.FormBorderStyle = FormBorderStyle.None;
|
|
|
|
int ScreenNr = 0;
|
|
for (int i = 0; i < Screen.AllScreens.Length; i++)
|
|
{
|
|
Screen scr = Screen.AllScreens[i];
|
|
if (scr.Bounds.Top <= this.Top && scr.Bounds.Left <= this.Left)
|
|
ScreenNr = i;
|
|
}
|
|
|
|
this.DesktopBounds = new Rectangle(Screen.AllScreens[ScreenNr].Bounds.Location,
|
|
new Size(Screen.AllScreens[ScreenNr].Bounds.Width, Screen.AllScreens[ScreenNr].Bounds.Height));
|
|
|
|
if (this.WindowState == FormWindowState.Maximized)
|
|
{
|
|
this.WindowState = FormWindowState.Normal;
|
|
RResize();
|
|
this.WindowState = FormWindowState.Maximized;
|
|
}
|
|
else
|
|
RResize();
|
|
|
|
CConfig.SaveConfig();
|
|
}
|
|
|
|
private void LeaveFullScreen()
|
|
{
|
|
_fullscreen = false;
|
|
CConfig.FullScreen = EOffOn.TR_CONFIG_OFF;
|
|
|
|
this.FormBorderStyle = FormBorderStyle.Sizable;
|
|
this.DesktopBounds = new Rectangle(_restore.location, new Size(_restore.width, _restore.height));
|
|
|
|
CConfig.SaveConfig();
|
|
}
|
|
#endregion Helpers
|
|
|
|
#region form events
|
|
private void OnPaintEvent(object sender, PaintEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void OnResizeEvent(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void OnClosingEvent(object sender, CancelEventArgs e)
|
|
{
|
|
_Run = false;
|
|
}
|
|
|
|
protected override void OnLoad(EventArgs e)
|
|
{
|
|
GL.ClearColor(Color.Black);
|
|
}
|
|
|
|
protected override void OnResize(EventArgs e)
|
|
{
|
|
base.OnResize(e);
|
|
|
|
control.ClientSize = this.ClientSize;
|
|
RResize();
|
|
}
|
|
|
|
protected override void WndProc(ref Message m)
|
|
{
|
|
switch (m.Msg)
|
|
{
|
|
case 0x112: // WM_SYSCOMMAND
|
|
switch ((int)m.WParam & 0xFFF0)
|
|
{
|
|
case 0xF100: // SC_KEYMENU
|
|
m.Result = IntPtr.Zero;
|
|
break;
|
|
default:
|
|
base.WndProc(ref m);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
base.WndProc(ref m);
|
|
break;
|
|
}
|
|
}
|
|
#endregion form events
|
|
|
|
#region mouse event handlers
|
|
private void OnMouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
_Mouse.MouseMove(e);
|
|
}
|
|
|
|
private void OnMouseWheel(object sender, MouseEventArgs e)
|
|
{
|
|
_Mouse.MouseWheel(e);
|
|
}
|
|
|
|
private void OnMouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
_Mouse.MouseDown(e);
|
|
}
|
|
|
|
private void OnMouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
_Mouse.MouseUp(e);
|
|
}
|
|
|
|
private void OnMouseLeave(object sender, EventArgs e)
|
|
{
|
|
_Mouse.Visible = false;
|
|
Cursor.Show();
|
|
}
|
|
|
|
private void OnMouseEnter(object sender, EventArgs e)
|
|
{
|
|
Cursor.Hide();
|
|
_Mouse.Visible = true;
|
|
}
|
|
#endregion
|
|
|
|
#region keyboard event handlers
|
|
private void OnPreviewKeyDownEvent(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
|
|
{
|
|
OnKeyDownEvent(sender, new KeyEventArgs(e.KeyData));
|
|
}
|
|
|
|
private void OnKeyDownEvent(object sender, System.Windows.Forms.KeyEventArgs e)
|
|
{
|
|
_Keys.KeyDown(e);
|
|
}
|
|
|
|
|
|
private void OnKeyPressEvent(object sender, System.Windows.Forms.KeyPressEventArgs e)
|
|
{
|
|
_Keys.KeyPress(e);
|
|
}
|
|
|
|
private void OnKeyUpEvent(object sender, System.Windows.Forms.KeyEventArgs e)
|
|
{
|
|
_Keys.KeyUp(e);
|
|
}
|
|
#endregion keyboard event handlers
|
|
|
|
private void RResize()
|
|
{
|
|
h = control.Height;
|
|
w = control.Width;
|
|
y = 0;
|
|
x = 0;
|
|
|
|
|
|
if ((float)w / (float)h > CSettings.GetRenderAspect())
|
|
{
|
|
w = (int)Math.Round((float)h * CSettings.GetRenderAspect());
|
|
x = (control.Width - w) / 2;
|
|
}
|
|
else
|
|
{
|
|
h = (int)Math.Round((float)w / CSettings.GetRenderAspect());
|
|
y = (control.Height - h) / 2;
|
|
}
|
|
|
|
GL.MatrixMode(MatrixMode.Projection);
|
|
GL.LoadIdentity();
|
|
GL.Ortho(0, CSettings.iRenderW, CSettings.iRenderH, 0, (double)CSettings.zNear, (double)CSettings.zFar);
|
|
GL.Viewport(x, y, w, h);
|
|
}
|
|
|
|
|
|
#region implementation
|
|
#region main stuff
|
|
public bool Init()
|
|
{
|
|
this.Text = CSettings.GetFullVersionText();
|
|
|
|
// Init Texturing
|
|
GL.Enable(EnableCap.Texture2D);
|
|
|
|
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
|
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
|
|
|
GL.DepthRange(CSettings.zFar, CSettings.zNear);
|
|
GL.DepthFunc(DepthFunction.Lequal);
|
|
GL.Enable(EnableCap.DepthTest);
|
|
|
|
return true;
|
|
}
|
|
|
|
public void MainLoop()
|
|
{
|
|
_Run = true;
|
|
int delay = 0;
|
|
this.Show();
|
|
|
|
if (CConfig.FullScreen == EOffOn.TR_CONFIG_ON)
|
|
{
|
|
CSettings.bFullScreen = true;
|
|
EnterFullScreen();
|
|
}
|
|
|
|
while (_Run)
|
|
{
|
|
Application.DoEvents();
|
|
|
|
if (_Run)
|
|
{
|
|
ClearScreen();
|
|
_Run = _Run && CGraphics.Draw();
|
|
|
|
_Run = CGraphics.UpdateGameLogic(_Keys, _Mouse);
|
|
control.SwapBuffers();
|
|
|
|
if ((CSettings.bFullScreen && !_fullscreen) || (!CSettings.bFullScreen && _fullscreen))
|
|
ToggleFullScreen();
|
|
|
|
CheckQueque();
|
|
|
|
if (CTime.IsRunning())
|
|
delay = (int)Math.Floor(CConfig.CalcCycleTime() - CTime.GetMilliseconds());
|
|
|
|
if (delay >= 1 && CConfig.VSync == EOffOn.TR_CONFIG_OFF)
|
|
System.Threading.Thread.Sleep(delay);
|
|
|
|
CTime.CalculateFPS();
|
|
CTime.Restart();
|
|
}
|
|
else
|
|
this.Close();
|
|
}
|
|
}
|
|
|
|
public bool Unload()
|
|
{
|
|
STexture[] textures = new STexture[_Textures.Count];
|
|
_Textures.Values.CopyTo(textures, 0);
|
|
for (int i = 0; i < _Textures.Count; i++ )
|
|
{
|
|
RemoveTexture(ref textures[i]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public int GetScreenWidth()
|
|
{
|
|
return control.Width;
|
|
}
|
|
|
|
public int GetScreenHeight()
|
|
{
|
|
return control.Height;
|
|
}
|
|
|
|
public RectangleF GetTextBounds(CText text)
|
|
{
|
|
return GetTextBounds(text, text.Height);
|
|
}
|
|
|
|
public RectangleF GetTextBounds(CText text, float Height)
|
|
{
|
|
CFonts.Height = Height;
|
|
CFonts.SetFont(text.Fon);
|
|
CFonts.Style = text.Style;
|
|
return new RectangleF(text.X, text.Y, CFonts.GetTextWidth(CLanguage.Translate(text.Text)), CFonts.GetTextHeight(CLanguage.Translate(text.Text)));
|
|
}
|
|
#endregion main stuff
|
|
|
|
#region Basic Draw Methods
|
|
public void ClearScreen()
|
|
{
|
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
|
}
|
|
|
|
public STexture CopyScreen()
|
|
{
|
|
STexture texture = new STexture(-1);
|
|
|
|
int id = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, id);
|
|
texture.ID = id;
|
|
|
|
texture.width = w;
|
|
texture.height = h;
|
|
texture.w2 = (float)MathHelper.NextPowerOfTwo(texture.width);
|
|
texture.h2 = (float)MathHelper.NextPowerOfTwo(texture.height);
|
|
|
|
texture.width_ratio = texture.width / texture.w2;
|
|
texture.height_ratio = texture.height / texture.h2;
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)texture.w2, (int)texture.h2, 0,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, x, y,
|
|
(int)texture.width, (int)texture.height);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
// Add to Texture List
|
|
texture.color = new SColorF(1f, 1f, 1f, 1f);
|
|
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
|
|
|
|
lock (MutexTexture)
|
|
{
|
|
texture.index = _IDs.Dequeue();
|
|
_Textures[texture.index] = texture;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
public void CopyScreen(ref STexture Texture)
|
|
{
|
|
if (!_TextureExists(ref Texture) || (Texture.width != GetScreenWidth()) || (Texture.height != GetScreenHeight()))
|
|
{
|
|
RemoveTexture(ref Texture);
|
|
Texture = CopyScreen();
|
|
}
|
|
else
|
|
{
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
GL.CopyTexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, 0, 0,
|
|
(int)Texture.width, (int)Texture.height);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
}
|
|
|
|
public void MakeScreenShot()
|
|
{
|
|
string file = "Screenshot_";
|
|
string path = Path.Combine(Environment.CurrentDirectory, CSettings.sFolderScreenshots);
|
|
|
|
int i = 0;
|
|
while (File.Exists(Path.Combine(path, file + i.ToString("00000") + ".bmp")))
|
|
i++;
|
|
|
|
int width = GetScreenWidth();
|
|
int height = GetScreenHeight();
|
|
|
|
Bitmap screen = new Bitmap(width, height);
|
|
|
|
|
|
BitmapData bmp_data = screen.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
|
|
GL.ReadPixels(0, 0, width, height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
|
|
screen.UnlockBits(bmp_data);
|
|
|
|
screen.RotateFlip(RotateFlipType.RotateNoneFlipY);
|
|
screen.Save(Path.Combine(path, file + i.ToString("00000") + ".bmp"), ImageFormat.Bmp);
|
|
screen.Dispose();
|
|
}
|
|
|
|
public void DrawLine(int a, int r, int g, int b, int w, int x1, int y1, int x2, int y2)
|
|
{
|
|
|
|
}
|
|
|
|
// Draw Basic Text (must be deleted later)
|
|
public void DrawText(string Text, int x, int y, int h)
|
|
{
|
|
DrawText(Text, x, y, h, 0f);
|
|
}
|
|
|
|
public void DrawText(string Text, int x, int y, float h, float z)
|
|
{
|
|
CFonts.DrawText(Text, h, x, y, z, new SColorF(1, 1, 1, 1));
|
|
}
|
|
|
|
public void DrawColor(SColorF color, SRectF rect)
|
|
{
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
|
|
|
|
GL.Begin(BeginMode.Quads);
|
|
GL.Vertex3(rect.X, rect.Y, rect.Z + CGraphics.ZOffset);
|
|
GL.Vertex3(rect.X, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
|
|
GL.Vertex3(rect.X + rect.W, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
|
|
GL.Vertex3(rect.X + rect.W, rect.Y, rect.Z + CGraphics.ZOffset);
|
|
GL.End();
|
|
|
|
GL.Disable(EnableCap.Blend);
|
|
}
|
|
|
|
#endregion Basic Draw Methods
|
|
|
|
#region Textures
|
|
|
|
#region adding
|
|
public STexture AddTexture(string TexturePath)
|
|
{
|
|
if (System.IO.File.Exists(TexturePath))
|
|
{
|
|
Bitmap bmp;
|
|
try
|
|
{
|
|
bmp = new Bitmap(TexturePath);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
CLog.LogError("Error loading Texture: " + TexturePath);
|
|
return new STexture(-1);
|
|
}
|
|
return AddTexture(bmp, TexturePath);
|
|
}
|
|
CLog.LogError("Can't find File: " + TexturePath);
|
|
return new STexture(-1);
|
|
}
|
|
|
|
public STexture AddTexture(Bitmap bmp)
|
|
{
|
|
return AddTexture(bmp, String.Empty);
|
|
}
|
|
|
|
public STexture AddTexture(Bitmap bmp, string TexturePath)
|
|
{
|
|
STexture texture = new STexture(-1);
|
|
|
|
if (bmp.Height == 0 || bmp.Width == 0)
|
|
return texture;
|
|
|
|
int MaxSize;
|
|
switch (CConfig.TextureQuality)
|
|
{
|
|
case ETextureQuality.TR_CONFIG_TEXTURE_LOWEST:
|
|
MaxSize = 128;
|
|
break;
|
|
case ETextureQuality.TR_CONFIG_TEXTURE_LOW:
|
|
MaxSize = 256;
|
|
break;
|
|
case ETextureQuality.TR_CONFIG_TEXTURE_MEDIUM:
|
|
MaxSize = 512;
|
|
break;
|
|
case ETextureQuality.TR_CONFIG_TEXTURE_HIGH:
|
|
MaxSize = 1024;
|
|
break;
|
|
case ETextureQuality.TR_CONFIG_TEXTURE_HIGHEST:
|
|
MaxSize = 2048;
|
|
break;
|
|
default:
|
|
MaxSize = 512;
|
|
break;
|
|
}
|
|
|
|
int w = bmp.Width;
|
|
int h = bmp.Height;
|
|
|
|
if (h >= w && w > MaxSize)
|
|
{
|
|
h = (int)Math.Round((float)MaxSize / bmp.Width * bmp.Height);
|
|
w = MaxSize;
|
|
}
|
|
|
|
if (w >= h && h > MaxSize)
|
|
{
|
|
w = (int)Math.Round((float)MaxSize / bmp.Height * bmp.Width);
|
|
h = MaxSize;
|
|
}
|
|
|
|
int id = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, id);
|
|
texture.ID = id;
|
|
|
|
texture.width = w;
|
|
texture.height = h;
|
|
|
|
texture.w2 = (float)MathHelper.NextPowerOfTwo(w);
|
|
texture.h2 = (float)MathHelper.NextPowerOfTwo(h);
|
|
|
|
Bitmap bmp2 = new Bitmap((int)texture.w2, (int)texture.h2);
|
|
Graphics g = Graphics.FromImage(bmp2);
|
|
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
|
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
|
|
g.DrawImage(bmp, new Rectangle(0, 0, bmp2.Width, bmp2.Height));
|
|
g.Dispose();
|
|
|
|
texture.width_ratio = 1f;
|
|
texture.height_ratio = 1f;
|
|
|
|
BitmapData bmp_data = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
|
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)texture.w2, (int)texture.h2, 0,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bmp_data.Width, bmp_data.Height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bmp_data.Scan0);
|
|
|
|
bmp2.UnlockBits(bmp_data);
|
|
bmp2.Dispose();
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
|
|
// Add to Texture List
|
|
texture.color = new SColorF(1f, 1f, 1f, 1f);
|
|
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
|
|
texture.TexturePath = String.Empty;
|
|
|
|
lock (MutexTexture)
|
|
{
|
|
texture.index = _IDs.Dequeue();
|
|
_Textures[texture.index] = texture;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
public STexture AddTexture(int W, int H, IntPtr Data)
|
|
{
|
|
STexture texture = new STexture(-1);
|
|
|
|
if (_UsePBO)
|
|
{
|
|
try
|
|
{
|
|
GL.GenBuffers(1, out texture.PBO);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
|
|
GL.BufferData(BufferTarget.PixelUnpackBuffer, (IntPtr)(W * H * 4), IntPtr.Zero, BufferUsageHint.StreamDraw);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_UsePBO = false;
|
|
}
|
|
}
|
|
|
|
int id = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, id);
|
|
texture.ID = id;
|
|
|
|
texture.width = W;
|
|
texture.height = H;
|
|
texture.w2 = (float)MathHelper.NextPowerOfTwo(texture.width);
|
|
texture.h2 = (float)MathHelper.NextPowerOfTwo(texture.height);
|
|
|
|
texture.width_ratio = texture.width / texture.w2;
|
|
texture.height_ratio = texture.height / texture.h2;
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)texture.w2, (int)texture.h2, 0,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, W, H,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data);
|
|
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
//GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
// Add to Texture List
|
|
texture.color = new SColorF(1f, 1f, 1f, 1f);
|
|
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
|
|
texture.TexturePath = String.Empty;
|
|
|
|
lock (MutexTexture)
|
|
{
|
|
texture.index = _IDs.Dequeue();
|
|
_Textures[texture.index] = texture;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
public STexture AddTexture(int W, int H, ref byte[] Data)
|
|
{
|
|
STexture texture = new STexture(-1);
|
|
|
|
if (_UsePBO)
|
|
{
|
|
try
|
|
{
|
|
GL.GenBuffers(1, out texture.PBO);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
|
|
GL.BufferData(BufferTarget.PixelUnpackBuffer, (IntPtr)Data.Length, IntPtr.Zero, BufferUsageHint.StreamDraw);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//throw;
|
|
_UsePBO = false;
|
|
}
|
|
}
|
|
|
|
int id = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, id);
|
|
texture.ID = id;
|
|
|
|
texture.width = W;
|
|
texture.height = H;
|
|
texture.w2 = (float)MathHelper.NextPowerOfTwo(texture.width);
|
|
texture.h2 = (float)MathHelper.NextPowerOfTwo(texture.height);
|
|
|
|
texture.width_ratio = texture.width / texture.w2;
|
|
texture.height_ratio = texture.height / texture.h2;
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)texture.w2, (int)texture.h2, 0,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, W, H,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data);
|
|
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
//GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
// Add to Texture List
|
|
texture.color = new SColorF(1f, 1f, 1f, 1f);
|
|
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
|
|
texture.TexturePath = String.Empty;
|
|
|
|
lock (MutexTexture)
|
|
{
|
|
texture.index = _IDs.Dequeue();
|
|
_Textures[texture.index] = texture;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
|
|
public STexture QuequeTexture(int W, int H, ref byte[] Data)
|
|
{
|
|
STexture texture = new STexture(-1);
|
|
STextureQueque queque = new STextureQueque();
|
|
|
|
queque.data = Data;
|
|
queque.height = H;
|
|
queque.width = W;
|
|
texture.height = H;
|
|
texture.width = W;
|
|
|
|
lock (MutexTexture)
|
|
{
|
|
texture.index = _IDs.Dequeue();
|
|
queque.ID = texture.index;
|
|
_Queque.Add(queque);
|
|
_Textures[texture.index] = texture;
|
|
}
|
|
|
|
return texture;
|
|
}
|
|
#endregion adding
|
|
|
|
#region updating
|
|
public bool UpdateTexture(ref STexture Texture, IntPtr Data)
|
|
{
|
|
if (_TextureExists(ref Texture))
|
|
{
|
|
if (_UsePBO)
|
|
{
|
|
try
|
|
{
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, Texture.PBO);
|
|
|
|
IntPtr Buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
|
|
byte[] d = new byte[(int)Texture.height * (int)Texture.width * 4];
|
|
|
|
Marshal.Copy(Data, d, 0, (int)Texture.height * (int)Texture.width * 4);
|
|
Marshal.Copy(d, 0, Buffer, (int)Texture.height * (int)Texture.width * 4);
|
|
|
|
GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (int)Texture.width, (int)Texture.height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_UsePBO = false;
|
|
}
|
|
}
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (int)Texture.width, (int)Texture.height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool UpdateTexture(ref STexture Texture, ref byte[] Data)
|
|
{
|
|
if (_TextureExists(ref Texture))
|
|
{
|
|
if (_UsePBO)
|
|
{
|
|
try
|
|
{
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, Texture.PBO);
|
|
|
|
IntPtr Buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
|
|
Marshal.Copy(Data, 0, Buffer, Data.Length);
|
|
|
|
GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (int)Texture.width, (int)Texture.height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
|
|
|
return true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
throw;
|
|
//_UsePBO = false;
|
|
}
|
|
}
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, (int)Texture.width, (int)Texture.height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, Data);
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
//GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
//GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
//GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endregion updating
|
|
|
|
public void RemoveTexture(ref STexture Texture)
|
|
{
|
|
if ((Texture.index > 0) && (_Textures.Count > 0))
|
|
{
|
|
lock (MutexTexture)
|
|
{
|
|
_IDs.Enqueue(Texture.index);
|
|
GL.DeleteTexture(Texture.ID);
|
|
if (Texture.PBO > 0)
|
|
GL.DeleteBuffers(1, ref Texture.PBO);
|
|
_Textures.Remove(Texture.index);
|
|
Texture.index = -1;
|
|
Texture.ID = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _TextureExists(ref STexture Texture)
|
|
{
|
|
lock (MutexTexture)
|
|
{
|
|
if(_Textures.ContainsKey((Texture.index)))
|
|
{
|
|
if(_Textures[Texture.index].ID > 0)
|
|
{
|
|
Texture = _Textures[Texture.index];
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#region drawing
|
|
public void DrawTexture(STexture Texture)
|
|
{
|
|
DrawTexture(Texture, Texture.rect, Texture.color);
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect)
|
|
{
|
|
DrawTexture(Texture, rect, Texture.color, false);
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect, SColorF color)
|
|
{
|
|
DrawTexture(Texture, rect, color, false);
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect, SColorF color, SRectF bounds)
|
|
{
|
|
DrawTexture(Texture, rect, color, bounds, false);
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect, SColorF color, bool mirrored)
|
|
{
|
|
DrawTexture(Texture, rect, color, new SRectF(0, 0, CSettings.iRenderW, CSettings.iRenderH, rect.Z), mirrored);
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect, SColorF color, SRectF bounds, bool mirrored)
|
|
{
|
|
if (rect.W == 0f || rect.H == 0f || bounds.H == 0f || bounds.W == 0f || color.A == 0f)
|
|
return;
|
|
|
|
if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
|
|
return;
|
|
|
|
if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
|
|
return;
|
|
|
|
if (_TextureExists(ref Texture))
|
|
{
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
float x1 = (bounds.X - rect.X) / rect.W * Texture.width_ratio;
|
|
float x2 = (bounds.X + bounds.W - rect.X) / rect.W * Texture.width_ratio;
|
|
float y1 = (bounds.Y - rect.Y) / rect.H * Texture.height_ratio;
|
|
float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * Texture.height_ratio;
|
|
|
|
if (x1 < 0)
|
|
x1 = 0f;
|
|
|
|
if (x2 > Texture.width_ratio)
|
|
x2 = Texture.width_ratio;
|
|
|
|
if (y1 < 0)
|
|
y1 = 0f;
|
|
|
|
if (y2 > Texture.height_ratio)
|
|
y2 = Texture.height_ratio;
|
|
|
|
|
|
float rx1 = rect.X;
|
|
float rx2 = rect.X + rect.W;
|
|
float ry1 = rect.Y;
|
|
float ry2 = rect.Y + rect.H;
|
|
|
|
if (rx1 < bounds.X)
|
|
rx1 = bounds.X;
|
|
|
|
if (rx2 > bounds.X + bounds.W)
|
|
rx2 = bounds.X + bounds.W;
|
|
|
|
if (ry1 < bounds.Y)
|
|
ry1 = bounds.Y;
|
|
|
|
if (ry2 > bounds.Y + bounds.H)
|
|
ry2 = bounds.Y + bounds.H;
|
|
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
|
|
|
|
GL.MatrixMode(MatrixMode.Texture);
|
|
GL.PushMatrix();
|
|
|
|
if (rect.Rotation != 0f)
|
|
{
|
|
GL.Translate(0.5f, 0.5f, 0);
|
|
GL.Rotate(-rect.Rotation, 0f, 0f, 1f);
|
|
GL.Translate(-0.5f, -0.5f, 0);
|
|
}
|
|
|
|
if (!mirrored)
|
|
{
|
|
GL.Begin(BeginMode.Quads);
|
|
|
|
GL.TexCoord2(x1, y1);
|
|
GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x1, y2);
|
|
GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x2, y2);
|
|
GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x2, y1);
|
|
GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.End();
|
|
}
|
|
else
|
|
{
|
|
GL.Begin(BeginMode.Quads);
|
|
|
|
GL.TexCoord2(x2, y2);
|
|
GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x2, y1);
|
|
GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x1, y1);
|
|
GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(x1, y2);
|
|
GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.End();
|
|
}
|
|
|
|
GL.PopMatrix();
|
|
|
|
GL.Disable(EnableCap.Blend);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
}
|
|
|
|
public void DrawTexture(STexture Texture, SRectF rect, SColorF color, float begin, float end)
|
|
{
|
|
if (_TextureExists(ref Texture))
|
|
{
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
GL.Enable(EnableCap.Blend);
|
|
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
|
|
|
|
|
|
GL.Begin(BeginMode.Quads);
|
|
|
|
GL.TexCoord2(0f + begin * Texture.width_ratio, 0f);
|
|
GL.Vertex3(rect.X + begin * rect.W, rect.Y, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(0f + begin * Texture.width_ratio, Texture.height_ratio);
|
|
GL.Vertex3(rect.X + begin * rect.W, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(Texture.width_ratio * end, Texture.height_ratio);
|
|
GL.Vertex3(rect.X + end * rect.W, rect.Y + rect.H, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.TexCoord2(Texture.width_ratio * end, 0f);
|
|
GL.Vertex3(rect.X + end * rect.W, rect.Y, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.End();
|
|
|
|
|
|
GL.Disable(EnableCap.Blend);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
}
|
|
|
|
public void DrawTextureReflection(STexture Texture, SRectF rect, SColorF color, SRectF bounds, float space, float height)
|
|
{
|
|
if (rect.W == 0f || rect.H == 0f || bounds.H == 0f || bounds.W == 0f || color.A == 0f || height <= 0f)
|
|
return;
|
|
|
|
if (bounds.X > rect.X + rect.W || bounds.X + bounds.W < rect.X)
|
|
return;
|
|
|
|
if (bounds.Y > rect.Y + rect.H || bounds.Y + bounds.H < rect.Y)
|
|
return;
|
|
|
|
if (height > bounds.H)
|
|
height = bounds.H;
|
|
|
|
if (_TextureExists(ref Texture))
|
|
{
|
|
GL.BindTexture(TextureTarget.Texture2D, Texture.ID);
|
|
|
|
float x1 = (bounds.X - rect.X) / rect.W * Texture.width_ratio;
|
|
float x2 = (bounds.X + bounds.W - rect.X) / rect.W * Texture.width_ratio;
|
|
float y1 = (bounds.Y - rect.Y + rect.H - height) / rect.H * Texture.height_ratio;
|
|
float y2 = (bounds.Y + bounds.H - rect.Y) / rect.H * Texture.height_ratio;
|
|
|
|
if (x1 < 0)
|
|
x1 = 0f;
|
|
|
|
if (x2 > Texture.width_ratio)
|
|
x2 = Texture.width_ratio;
|
|
|
|
if (y1 < 0)
|
|
y1 = 0f;
|
|
|
|
if (y2 > Texture.height_ratio)
|
|
y2 = Texture.height_ratio;
|
|
|
|
|
|
float rx1 = rect.X;
|
|
float rx2 = rect.X + rect.W;
|
|
float ry1 = rect.Y + rect.H + space;
|
|
float ry2 = rect.Y + rect.H + space + height;
|
|
|
|
if (rx1 < bounds.X)
|
|
rx1 = bounds.X;
|
|
|
|
if (rx2 > bounds.X + bounds.W)
|
|
rx2 = bounds.X + bounds.W;
|
|
|
|
if (ry1 < bounds.Y + space)
|
|
ry1 = bounds.Y + space;
|
|
|
|
if (ry2 > bounds.Y + bounds.H + space + height)
|
|
ry2 = bounds.Y + bounds.H + space + height;
|
|
|
|
GL.Enable(EnableCap.Blend);
|
|
|
|
GL.MatrixMode(MatrixMode.Texture);
|
|
GL.PushMatrix();
|
|
|
|
if (rect.Rotation != 0f)
|
|
{
|
|
GL.Translate(0.5f, 0.5f, 0);
|
|
GL.Rotate(-rect.Rotation, 0f, 0f, 1f);
|
|
GL.Translate(-0.5f, -0.5f, 0);
|
|
}
|
|
|
|
|
|
GL.Begin(BeginMode.Quads);
|
|
|
|
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
|
|
GL.TexCoord2(x2, y2);
|
|
GL.Vertex3(rx2, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.Color4(color.R, color.G, color.B, 0f);
|
|
GL.TexCoord2(x2, y1);
|
|
GL.Vertex3(rx2, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.Color4(color.R, color.G, color.B, 0f);
|
|
GL.TexCoord2(x1, y1);
|
|
GL.Vertex3(rx1, ry2, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.Color4(color.R, color.G, color.B, color.A * CGraphics.GlobalAlpha);
|
|
GL.TexCoord2(x1, y2);
|
|
GL.Vertex3(rx1, ry1, rect.Z + CGraphics.ZOffset);
|
|
|
|
GL.End();
|
|
|
|
|
|
GL.PopMatrix();
|
|
|
|
GL.Disable(EnableCap.Blend);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
}
|
|
#endregion drawing
|
|
|
|
public int TextureCount()
|
|
{
|
|
return _Textures.Count;
|
|
}
|
|
|
|
private void CheckQueque()
|
|
{
|
|
lock (MutexTexture)
|
|
{
|
|
if (_Queque.Count == 0)
|
|
return;
|
|
|
|
STextureQueque q = _Queque[0];
|
|
STexture texture = new STexture(-1);
|
|
if (_Textures.ContainsKey(q.ID))
|
|
{
|
|
texture = _Textures[q.ID];
|
|
}
|
|
|
|
if (texture.index < 1)
|
|
return;
|
|
|
|
if (_UsePBO)
|
|
{
|
|
try
|
|
{
|
|
GL.GenBuffers(1, out texture.PBO);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
|
|
GL.BufferData(BufferTarget.PixelUnpackBuffer, (IntPtr)q.data.Length, IntPtr.Zero, BufferUsageHint.StreamDraw);
|
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//throw;
|
|
_UsePBO = false;
|
|
}
|
|
}
|
|
|
|
int id = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, id);
|
|
texture.ID = id;
|
|
|
|
texture.width = q.width;
|
|
texture.height = q.height;
|
|
texture.w2 = (float)MathHelper.NextPowerOfTwo(texture.width);
|
|
texture.h2 = (float)MathHelper.NextPowerOfTwo(texture.height);
|
|
|
|
texture.width_ratio = texture.width / texture.w2;
|
|
texture.height_ratio = texture.height / texture.h2;
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)texture.w2, (int)texture.h2, 0,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
|
|
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, q.width, q.height,
|
|
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, q.data);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
|
|
// Add to Texture List
|
|
texture.color = new SColorF(1f, 1f, 1f, 1f);
|
|
texture.rect = new SRectF(0f, 0f, texture.width, texture.height, 0f);
|
|
texture.TexturePath = String.Empty;
|
|
|
|
_Textures[texture.index] = texture;
|
|
q.data = null;
|
|
_Queque.RemoveAt(0);
|
|
}
|
|
}
|
|
#endregion Textures
|
|
|
|
#endregion implementation
|
|
}
|
|
}
|