Add TextDrawer + Add lazy alpha test + move rdp vertex bomswap to vertex shader

This commit is contained in:
Random
2021-03-26 00:53:26 +01:00
parent 5fef4d38a9
commit f29f0def43
11 changed files with 371 additions and 12 deletions
+2 -1
View File
@@ -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
+18 -2
View File
@@ -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;
+233
View File
@@ -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);
}
}
+6 -1
View File
@@ -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);
+1
View File
@@ -102,6 +102,7 @@ namespace Z64.Forms
{
_renderer.RenderStart(proj, view);
RenderLimb(0);
/*
GL.PointSize(10.0f);
GL.LineWidth(2.0f);
+15 -4
View File
@@ -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);
*/
}
+20 -4
View File
@@ -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;
}
+17
View File
@@ -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);
}
+16
View File
@@ -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;
}
+6
View File
@@ -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>