Does anyone see why is this about 20% slower then the regular sprite batch when im not even switching textures. Im trying to figure out what the magic is within spritebatch and friends that im missing. I poped in pointer indexing and that only got me like 10 more fps at the cost of using unsafe so i removed it.
Also why in the gl version would going from a smaller window to a maximized window make the frame rate incredibly slower. Am i the only one seeing this ? In one extreme test case, i got a drop from 1500 fps to 150 fps just enlarging the window to close to be maximized its the weirdest thing. I see it as well with regular spritebatch a huge drop in fps.
public void DrawText
(
StringBuilder text, Vector2 position, Color color,
float rotation, Vector2 origin, Vector2 scale,float depth
)
{
unchecked
{
//precalculate
var firstGlyphOfLine = true;
var currentGlyph = defaultGlyph;
var lineHeight = (float)tsf.LineSpacing * scale.Y;
var Spacing = tsf.Spacing;
Vector2 offset = Vector2.Zero;
Vector2 q = new Vector2((float)(Math.Sin(rotation)), (float)(Math.Cos(rotation)));
char c;
for (var i = 0; i < text.Length; i++)
{
c = text[i];
if (c == '\r')
continue;
if (c == '\n')
{
offset.Y += lineHeight;
offset.X = 0;
firstGlyphOfLine = true;
continue;
}
if (_glyphs.ContainsKey(c))
currentGlyph = _glyphs[c];
else
currentGlyph = defaultGlyph;
// calculate and scale
if (firstGlyphOfLine == false)
offset.X += Spacing + currentGlyph.LeftSideBearing * scale.X;
firstGlyphOfLine = false;
Vector2 localDrawXY = new Vector2(currentGlyph.Cropping.X, currentGlyph.Cropping.Y) * scale + offset;
Vector2 localDrawRB = localDrawXY + new Vector2(currentGlyph.BoundsInTexture.Width * scale.X, currentGlyph.BoundsInTexture.Height * scale.Y);
offset.X = (currentGlyph.Width + currentGlyph.RightSideBearing) * scale.X + offset.X;
// prep vertices to directly draw
Vector2 lt = new Vector2(localDrawXY.X, localDrawXY.Y);
Vector2 lb = new Vector2(localDrawXY.X, localDrawRB.Y);
Vector2 rt = new Vector2(localDrawRB.X, localDrawXY.Y);
Vector2 rb = new Vector2(localDrawRB.X, localDrawRB.Y);
// rotate
if (rotation != 0)
{
lt = new Vector2(lt.X * q.Y - lt.Y * q.X, lt.X * q.X + lt.Y * q.Y);
lb = new Vector2(lb.X * q.Y - lb.Y * q.X, lb.X * q.X + lb.Y * q.Y);
rt = new Vector2(rt.X * q.Y - rt.Y * q.X, rt.X * q.X + rt.Y * q.Y);
rb = new Vector2(rb.X * q.Y - rb.Y * q.X, rb.X * q.X + rb.Y * q.Y);
}
// translate
lt += position;
lb += position;
rt += position;
rb += position;
// project
var LT = new Vector3(lt.X * cw - 1f, lt.Y * -ch + 1f, depth);
var LB = new Vector3(lb.X * cw - 1f, lb.Y * -ch + 1f, depth);
var RT = new Vector3(rt.X * cw - 1f, rt.Y * -ch + 1f, depth);
var RB = new Vector3(rb.X * cw - 1f, rb.Y * -ch + 1f, depth);
// uv coordinates in screen space
float uvL = (float)currentGlyph.BoundsInTexture.Left * cu;
float uvR = (float)currentGlyph.BoundsInTexture.Right * cu;
float uvT = (float)currentGlyph.BoundsInTexture.Top * cv;
float uvB = (float)currentGlyph.BoundsInTexture.Bottom * cv;
Vector2 uv0 = new Vector2(uvL, uvT);
Vector2 uv1 = new Vector2(uvL, uvB);
Vector2 uv2 = new Vector2(uvR, uvT);
Vector2 uv3 = new Vector2(uvR, uvB);
// create the vertice quad
spriteVertices[vi_pointer + 0] = new VertexPositionColorTexture(LT, color, uv0);
spriteVertices[vi_pointer + 1] = new VertexPositionColorTexture(LB, color, uv1);
spriteVertices[vi_pointer + 2] = new VertexPositionColorTexture(RT, color, uv2);
spriteVertices[vi_pointer + 3] = new VertexPositionColorTexture(RB, color, uv3);
// create the indexs
//
// LT 0 2 RT
// | /| Triangle 1 is 0 1 2 ccw
// | / | Triangle 2 is 2 1 3 ccw
// LB 1 3 RB
triangleIndexs[ti_pointer + 0] = 0 + vi_pointer;
triangleIndexs[ti_pointer + 1] = 1 + vi_pointer;
triangleIndexs[ti_pointer + 2] = 2 + vi_pointer;
triangleIndexs[ti_pointer + 3] = 2 + vi_pointer;
triangleIndexs[ti_pointer + 4] = 1 + vi_pointer;
triangleIndexs[ti_pointer + 5] = 3 + vi_pointer;
// increment the counts and indexs
currentTriangles += 2;
vi_pointer += 4;
ti_pointer += 6;
// check capacity
if (currentTriangles >= triangleCapacity - 2)
{
IncreaseCapacity();
}
}
}
}
Well here is what i’ve been working on while my internet was down. Wrapped text directly bypassing spritebatch and draw via drawuserindex primitives and directly using the loaded spritefont.
Though this is still just a prototype its basically a fancy version of the above with a small word buffer class helper.
Taking a screenshot creates garbage i guess.
Im cheating here with alpha blending though this would break on separate calls. I still haven’t made a shader to do it properly this is just using basiceffect.
These all align to or can align to spritebatch kerning i already tested it, i get per pixel alignment. Though i yanked out sprite effects because the more i reflect on it the more i just think its stupid and ugly.
but ya i really can’t see why that first method would be slightly slower then spritebatch i really expected it to be faster as it is doing less overall and is compacted.