mirror of
https://github.com/zeldaret/Z64Utils.git
synced 2026-09-29 23:14:37 -04:00
Add TextDrawer + Add lazy alpha test + move rdp vertex bomswap to vertex shader
This commit is contained in:
@@ -14,7 +14,8 @@ namespace F3DZEX.Render
|
||||
_shader = new ShaderHandler("Shaders/rdpVtx.vert", "Shaders/rdpVtx.frag");
|
||||
_attrs = new VertexAttribs();
|
||||
// position
|
||||
_attrs.LayoutAddFloat(3, VertexAttribPointerType.Short, false);
|
||||
//_attrs.LayoutAddFloat(3, VertexAttribPointerType.Short, false);
|
||||
_attrs.LayoutAddInt(3, VertexAttribIntegerType.UnsignedShort);
|
||||
//flag
|
||||
_attrs.LayoutAddInt(1, VertexAttribIntegerType.UnsignedShort);
|
||||
// tex coords
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace F3DZEX.Render
|
||||
RdpVertexDrawer _rdpVtxDrawer;
|
||||
SimpleVertexDrawer _gridDrawer;
|
||||
ColoredVertexDrawer _axisDrawer;
|
||||
TextDrawer _textDrawer;
|
||||
TextureHandler _curTex;
|
||||
Stack<Matrix4> _mtxStack = new Stack<Matrix4>();
|
||||
|
||||
@@ -150,6 +151,7 @@ namespace F3DZEX.Render
|
||||
_rdpVtxDrawer = new RdpVertexDrawer();
|
||||
_gridDrawer = new SimpleVertexDrawer();
|
||||
_axisDrawer = new ColoredVertexDrawer();
|
||||
_textDrawer = new TextDrawer();
|
||||
|
||||
float[] vertices = RenderHelper.GenerateGridVertices(CurrentConfig.GridScale, 6, false);
|
||||
_gridDrawer.SetData(vertices, BufferUsageHint.StaticDraw);
|
||||
@@ -180,9 +182,12 @@ namespace F3DZEX.Render
|
||||
_mtxStack = new Stack<Matrix4>();
|
||||
PushMatrix(Matrix4.Identity);
|
||||
|
||||
|
||||
_gridDrawer.SendProjViewMatrices(ref proj, ref view);
|
||||
_axisDrawer.SendProjViewMatrices(ref proj, ref view);
|
||||
_rdpVtxDrawer.SendProjViewMatrices(ref proj, ref view);
|
||||
Matrix4 id = Matrix4.Identity;
|
||||
_textDrawer.SendProjViewMatrices(ref id, ref id);
|
||||
|
||||
SendHighlightColor(Color.Transparent);
|
||||
|
||||
@@ -217,6 +222,13 @@ namespace F3DZEX.Render
|
||||
if (CurrentConfig.ShowAxis)
|
||||
RenderHelper.DrawAxis(_axisDrawer);
|
||||
|
||||
_textDrawer.DrawString(
|
||||
//$"Extensions: {GL.GetString(StringName.Extensions)}\n" +
|
||||
$"Shading Language Version: {GL.GetString(StringName.ShadingLanguageVersion)}\n" +
|
||||
$"Version: {GL.GetString(StringName.Version)}\n" +
|
||||
$"Renderer: {GL.GetString(StringName.Renderer)}\n" +
|
||||
$"Vendor: {GL.GetString(StringName.Vendor)}");
|
||||
|
||||
CheckGLErros();
|
||||
}
|
||||
|
||||
@@ -407,8 +419,12 @@ namespace F3DZEX.Render
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] indices = new byte[] { cmd.v00, cmd.v01, cmd.v02, cmd.v00, cmd.v10, cmd.v11, cmd.v12, cmd.v10 };
|
||||
_rdpVtxDrawer.Draw(PrimitiveType.LineStrip, indices);
|
||||
//byte[] indices = new byte[] { cmd.v00, cmd.v01, cmd.v02, cmd.v00, cmd.v10, cmd.v11, cmd.v12, cmd.v10 };
|
||||
//_rdpVtxDrawer.Draw(PrimitiveType.LineStrip, indices);
|
||||
byte[] indices = new byte[] { cmd.v00, cmd.v01, cmd.v02 };
|
||||
_rdpVtxDrawer.Draw(PrimitiveType.LineLoop, indices);
|
||||
indices = new byte[] { cmd.v10, cmd.v11, cmd.v12 };
|
||||
_rdpVtxDrawer.Draw(PrimitiveType.LineLoop, indices);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenTK;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace F3DZEX.Render
|
||||
{
|
||||
public class TextDrawer
|
||||
{
|
||||
TexturedVertexDrawer _vtxDrawer;
|
||||
TextureHandler _tex;
|
||||
Font _font;
|
||||
Color _color;
|
||||
//float _scale;
|
||||
byte[] _texData;
|
||||
int _texWidth;
|
||||
int _texHeight;
|
||||
RectangleF[] _charSpaces;
|
||||
string _lastStr;
|
||||
float[] _lastVertices;
|
||||
|
||||
public Vector2 Position { get; set; }
|
||||
public Font TextFont {
|
||||
get => _font;
|
||||
set { _font = value; GenerateAlphabetTexture(); }
|
||||
}
|
||||
public Color Color
|
||||
{
|
||||
get => _color;
|
||||
set { _color = value; SendColor(_color); }
|
||||
}
|
||||
|
||||
public float Scale { get; set; }
|
||||
public int TextHSpace { get; set; }
|
||||
public int TextVSpace { get; set; }
|
||||
|
||||
|
||||
public TextDrawer()
|
||||
{
|
||||
_vtxDrawer = new TexturedVertexDrawer();
|
||||
_tex = new TextureHandler();
|
||||
TextFont = new Font("Arial", 50);
|
||||
_lastStr = null;
|
||||
Scale = 0.4f;
|
||||
Color = Color.White;
|
||||
TextHSpace = -15;
|
||||
TextVSpace = -5;
|
||||
}
|
||||
|
||||
public float GetTextWidth(string text)
|
||||
{
|
||||
using (var g = Graphics.FromImage(new Bitmap(1, 1)))
|
||||
return g.MeasureString(text, TextFont).Width;
|
||||
}
|
||||
|
||||
private SizeF GetCharSize(char c)
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(new Bitmap(1, 1)))
|
||||
{
|
||||
return g.MeasureString(c.ToString(), TextFont);
|
||||
}
|
||||
}
|
||||
|
||||
private RectangleF[] GetCharRange(string text)
|
||||
{
|
||||
RectangleF[] ret = new RectangleF[text.Length];
|
||||
|
||||
using (var g = Graphics.FromImage(new Bitmap(1, 1)))
|
||||
{
|
||||
float x = 0;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
var size = g.MeasureString(text[i].ToString(), _font);
|
||||
|
||||
ret[i] = new RectangleF(x, 0, size.Width, size.Height);
|
||||
x += size.Width;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
|
||||
/*CharacterRange[] charRanges = new CharacterRange[text.Length];
|
||||
for (int i = 0; i < text.Length-1; i++)
|
||||
charRanges[i] = new CharacterRange(i, 1);
|
||||
*/
|
||||
/*
|
||||
CharacterRange[] charRanges = new CharacterRange[] { new CharacterRange(0, text.Length) };
|
||||
|
||||
StringFormat strFmt = new StringFormat();
|
||||
strFmt.FormatFlags = StringFormatFlags.NoClip;
|
||||
strFmt.SetMeasurableCharacterRanges(charRanges);
|
||||
|
||||
var region = g.MeasureCharacterRanges(text, TextFont, new RectangleF(0, 0, 100, 100), strFmt);
|
||||
List<RectangleF> ret = new List<RectangleF>();
|
||||
region.ToList().ForEach(r => ret.Add(r.GetBounds(g)));
|
||||
return ret;*/
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateAlphabetTexture()
|
||||
{
|
||||
string alphabet = GetAlphabet();
|
||||
_charSpaces = GetCharRange(alphabet);
|
||||
|
||||
// calculate texture size
|
||||
_texWidth = (int)(_charSpaces.Last().X + _charSpaces.Last().Width);
|
||||
_texHeight = 0;
|
||||
for (int i = 0; i < alphabet.Length; i++)
|
||||
_texHeight = Math.Max(_texHeight, (int)_charSpaces[i].Height);
|
||||
|
||||
// draw alphabet
|
||||
Bitmap bmp = new Bitmap(_texWidth, _texHeight);
|
||||
using (var g = Graphics.FromImage(bmp))
|
||||
for (int i = 0; i < alphabet.Length; i++)
|
||||
g.DrawString(alphabet[i].ToString(), _font, new SolidBrush(Color.White), _charSpaces[i].X, 0);
|
||||
//g.DrawString(alphabet, _font, new SolidBrush(Color.White), new PointF(0, 0));
|
||||
|
||||
_texData = new byte[bmp.Width * bmp.Height * 4];
|
||||
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
|
||||
Marshal.Copy(bmpData.Scan0, _texData, 0, _texData.Length);
|
||||
|
||||
bmp.UnlockBits(bmpData);
|
||||
|
||||
_tex.SetDataRGBA(_texData, _texWidth, _texHeight);
|
||||
}
|
||||
|
||||
private static string GetAlphabet()
|
||||
{
|
||||
string ret = "";
|
||||
for (int i = 0; i < 0x100; i++)
|
||||
ret += (char)i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public float[] GenerateVertices(string text)
|
||||
{
|
||||
int stride = 3 + 2;
|
||||
float[] vertices = new float[stride * 4 * text.Replace("\n", "").Length];
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
int vtxIdx = 0;
|
||||
for (int i = 0; i < text.Length; i++)
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
y -= _texHeight + TextVSpace;
|
||||
x = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
RectangleF rec = _charSpaces[text[i] >= 0x100 ? 0 : text[i]];
|
||||
|
||||
// top left
|
||||
vertices[vtxIdx++] = x;
|
||||
vertices[vtxIdx++] = y;
|
||||
vertices[vtxIdx++] = 0;
|
||||
vertices[vtxIdx++] = rec.X / _texWidth;
|
||||
vertices[vtxIdx++] = -(rec.Y / _texHeight);
|
||||
|
||||
// top right
|
||||
vertices[vtxIdx++] = x + rec.Width;
|
||||
vertices[vtxIdx++] = y;
|
||||
vertices[vtxIdx++] = 0;
|
||||
vertices[vtxIdx++] = (rec.X + rec.Width) / _texWidth;
|
||||
vertices[vtxIdx++] = -(rec.Y / _texHeight);
|
||||
|
||||
// bottom right
|
||||
vertices[vtxIdx++] = x + rec.Width;
|
||||
vertices[vtxIdx++] = y + rec.Height;
|
||||
vertices[vtxIdx++] = 0;
|
||||
vertices[vtxIdx++] = (rec.X + rec.Width) / _texWidth;
|
||||
vertices[vtxIdx++] = -((rec.Y + rec.Height) / _texHeight);
|
||||
|
||||
// bottom left
|
||||
vertices[vtxIdx++] = x;
|
||||
vertices[vtxIdx++] = y + rec.Height;
|
||||
vertices[vtxIdx++] = 0;
|
||||
vertices[vtxIdx++] = rec.X / _texWidth;
|
||||
vertices[vtxIdx++] = -((rec.Y + rec.Height) / _texHeight);
|
||||
|
||||
|
||||
x += rec.Width;
|
||||
if (text[i] != ' ')
|
||||
x += TextHSpace;
|
||||
}
|
||||
|
||||
return vertices;
|
||||
}
|
||||
|
||||
public void DrawString(string str)
|
||||
{
|
||||
_tex.Use();
|
||||
if (str != _lastStr)
|
||||
{
|
||||
_lastStr = str;
|
||||
_lastVertices = GenerateVertices(str);
|
||||
_vtxDrawer.SetData(_lastVertices, BufferUsageHint.DynamicDraw);
|
||||
}
|
||||
|
||||
_vtxDrawer.SendModelMatrix(GetMatrix());
|
||||
_vtxDrawer.Draw(PrimitiveType.Quads);
|
||||
}
|
||||
|
||||
public Matrix4 GetMatrix()
|
||||
{
|
||||
GL.GetFloat(GetPName.Viewport, out Vector4 view);
|
||||
|
||||
Vector3 pos = new Vector3(Position);
|
||||
pos.X -= 1;
|
||||
pos.Y += 1 - ((float)_texHeight / 2 / view.W);
|
||||
|
||||
return Matrix4.CreateScale(Scale / view.Z, Scale / view.W, 1) * Matrix4.CreateTranslation(pos);
|
||||
}
|
||||
|
||||
public void SendColor(Color color)
|
||||
{
|
||||
_vtxDrawer.SendColor(color);
|
||||
}
|
||||
|
||||
|
||||
public void SendProjViewMatrices(ref Matrix4 proj, ref Matrix4 view)
|
||||
{
|
||||
_vtxDrawer.SendProjViewMatrices(ref proj, ref view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using OpenTK;
|
||||
|
||||
namespace F3DZEX.Render
|
||||
{
|
||||
public class TexturedVertexDrawer : VertexDrawer
|
||||
{
|
||||
public TexturedVertexDrawer()
|
||||
{
|
||||
_shader = new ShaderHandler("Shaders/texturedVtx.vert", "Shaders/texturedVtx.frag");
|
||||
_attrs = new VertexAttribs();
|
||||
|
||||
// pos
|
||||
_attrs.LayoutAddFloat(3, VertexAttribPointerType.Float, false);
|
||||
// texture coordinates
|
||||
_attrs.LayoutAddFloat(2, VertexAttribPointerType.Float, false);
|
||||
}
|
||||
|
||||
public void SendColor(Color color)
|
||||
{
|
||||
_shader.Send("u_Color", color);
|
||||
}
|
||||
|
||||
public void SetData(float[] data, BufferUsageHint hint) => SetVertexData(data, data.Length * sizeof(float), hint);
|
||||
|
||||
public void SendProjViewMatrices(ref Matrix4 proj, ref Matrix4 view)
|
||||
{
|
||||
_shader.Send("u_Projection", proj);
|
||||
_shader.Send("u_View", view);
|
||||
}
|
||||
public void SendModelMatrix(Matrix4 model) => _shader.Send("u_Model", model);
|
||||
}
|
||||
}
|
||||
@@ -147,6 +147,7 @@ namespace F3DZEX.Render
|
||||
|
||||
private void BomSwap(byte[] buffer)
|
||||
{
|
||||
/*
|
||||
int off = 0;
|
||||
while (off < buffer.Length)
|
||||
{
|
||||
@@ -162,6 +163,7 @@ namespace F3DZEX.Render
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void SetSubData(byte[] data, int off, bool bigEndian)
|
||||
@@ -169,8 +171,10 @@ namespace F3DZEX.Render
|
||||
if (!_built)
|
||||
BuildLayout();
|
||||
|
||||
/*
|
||||
if (bigEndian)
|
||||
BomSwap(data);
|
||||
*/
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
|
||||
GL.BufferSubData(BufferTarget.ArrayBuffer, new IntPtr(off), data.Length, data);
|
||||
@@ -180,9 +184,10 @@ namespace F3DZEX.Render
|
||||
{
|
||||
if (!_built)
|
||||
BuildLayout();
|
||||
|
||||
/*
|
||||
if (bigEndian)
|
||||
BomSwap(data);
|
||||
*/
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, data.Length, data, hint);
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace Z64.Forms
|
||||
{
|
||||
_renderer.RenderStart(proj, view);
|
||||
RenderLimb(0);
|
||||
|
||||
/*
|
||||
GL.PointSize(10.0f);
|
||||
GL.LineWidth(2.0f);
|
||||
|
||||
@@ -12,10 +12,22 @@ uniform bool u_TexEnabled;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
/* texture */
|
||||
gl_FragColor = u_TexEnabled
|
||||
? texture(u_Tex, v_VtxTexCoords)
|
||||
: vec4(0, 0, 0, 1);
|
||||
if (u_TexEnabled)
|
||||
{
|
||||
vec4 color = texture(u_Tex, v_VtxTexCoords);
|
||||
|
||||
/* lazy alpha check */
|
||||
if (color.a < 0.1)
|
||||
discard;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_FragColor = vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/* blending */
|
||||
// FragColor *= v_VtxColor;
|
||||
@@ -42,5 +54,4 @@ void main()
|
||||
z -= 0.4;
|
||||
gl_FragColor *= vec4(vec3(z), 1.0);
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 pos;
|
||||
layout(location = 0) in ivec3 pos;
|
||||
layout(location = 1) in int flag;
|
||||
layout(location = 2) in ivec2 texCoords;
|
||||
layout(location = 3) in vec4 color;
|
||||
@@ -19,19 +19,35 @@ float S105ToFloat(int fp)
|
||||
return fp >> 5;
|
||||
}
|
||||
|
||||
int bomSwap16(int x)
|
||||
{
|
||||
return (((x >> 0) & 0xFF) << 24) >> 16 |
|
||||
((x >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
vec2 decodeTexCoords(sampler2D tex, ivec2 coords)
|
||||
{
|
||||
ivec2 size = textureSize(tex, 0);
|
||||
return vec2(S105ToFloat(coords.x) / size.x, S105ToFloat(coords.y) / size.y);
|
||||
}
|
||||
|
||||
vec2 getTexCoords()
|
||||
{
|
||||
return decodeTexCoords(u_Tex, ivec2(bomSwap16(texCoords.x), bomSwap16(texCoords.y)));
|
||||
}
|
||||
|
||||
vec3 getPos()
|
||||
{
|
||||
return vec3(float(bomSwap16(pos.x)), float(bomSwap16(pos.y)), float(bomSwap16(pos.z)));
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
v_VtxId = gl_VertexID;
|
||||
|
||||
/* The vertices coordinates are multiplied by the model view matrix during the G_VTX command processing */
|
||||
gl_Position = u_Projection * u_View /* u_Model*/ * vec4(pos, 1);
|
||||
v_VtxTexCoords = decodeTexCoords(u_Tex, texCoords);
|
||||
gl_Position = u_Projection * u_View /* u_Model*/ * vec4(getPos(), 1);
|
||||
v_VtxTexCoords = getTexCoords();
|
||||
v_VtxColor = color;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#version 330 core
|
||||
|
||||
uniform sampler2D u_Tex;
|
||||
uniform vec4 u_Color;
|
||||
|
||||
in vec2 v_TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = texture(u_Tex, v_TexCoords) * u_Color;
|
||||
if (color.a < 0.1)
|
||||
discard;
|
||||
gl_FragColor = color;
|
||||
//gl_FragColor = vec4(1, v_TexCoords.y, 0, 1);
|
||||
//gl_FragColor = vec4(v_TexCoords.x, 1, 0, 1);
|
||||
//gl_FragColor = vec4(1, 0, 0, 1);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#version 330 core
|
||||
|
||||
uniform mat4 u_Projection;
|
||||
uniform mat4 u_View;
|
||||
uniform mat4 u_Model;
|
||||
|
||||
layout (location = 0) in vec3 coords;
|
||||
layout (location = 1) in vec2 texCoords;
|
||||
|
||||
out vec2 v_TexCoords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_Projection * u_View * u_Model * vec4(coords, 1);
|
||||
v_TexCoords = texCoords;
|
||||
}
|
||||
@@ -62,6 +62,12 @@
|
||||
<None Update="Shaders\rdpVtx.vert">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Shaders\texturedVtx.frag">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Shaders\texturedVtx.vert">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>kaeton.ico</ApplicationIcon>
|
||||
|
||||
Reference in New Issue
Block a user