- move plotter texture into plotter

This commit is contained in:
Magnus Norddahl 2019-08-18 07:43:46 +02:00
parent 3b2d50cce0
commit 3142437444
3 changed files with 78 additions and 148 deletions

View file

@ -23,79 +23,60 @@ using CodeImp.DoomBuilder.Geometry;
namespace CodeImp.DoomBuilder.Rendering
{
internal unsafe sealed class Plotter
internal unsafe sealed class Plotter : IDisposable
{
#region ================== Constants
private const int DASH_INTERVAL = 16; //mxd
#endregion
#region ================== Variables
// Memory
private PixelColor* pixels;
private int width;
private int height;
private int visiblewidth;
private int visibleheight;
#endregion
#region ================== Properties
public int VisibleWidth { get { return visiblewidth; } }
public int VisibleHeight { get { return visibleheight; } }
public int Width { get { return width; } }
public int Height { get { return height; } }
#endregion
#region ================== Constructor / Disposer
// Constructor
public Plotter(PixelColor* pixels, int width, int height, int visiblewidth, int visibleheight)
public Plotter(int width, int height)
{
// Initialize
this.pixels = pixels;
this.width = width;
this.height = height;
this.visiblewidth = width;
this.visibleheight = height;
// We have no destructor
GC.SuppressFinalize(this);
}
this.Texture = new Texture(width, height);
}
#endregion
~Plotter()
{
Dispose();
}
public int Width { get { return Texture.Width; } }
public int Height { get { return Texture.Height; } }
public Texture Texture { get; set; }
public void Dispose()
{
if (Texture != null) Texture.Dispose();
}
public void Begin(RenderDevice graphics)
{
this.pixels = (PixelColor*)graphics.LockTexture(Texture).ToPointer();
}
public void DrawContents(RenderDevice graphics)
{
graphics.UnlockTexture(Texture);
}
#region ================== Pixel Rendering
// This clears all pixels black
public void Clear()
{
// Clear memory
General.ZeroMemory(new IntPtr(pixels), width * height * sizeof(PixelColor));
General.ZeroMemory(new IntPtr(pixels), Width * Height * sizeof(PixelColor));
}
// This draws a pixel normally
public void DrawPixelSolid(int x, int y, ref PixelColor c)
{
// Draw pixel when within range
if((x >= 0) && (x < visiblewidth) && (y >= 0) && (y < visibleheight))
pixels[y * width + x] = c;
}
// This draws a pixel normally
public void DrawVertexSolid(int x, int y, int size, ref PixelColor c, ref PixelColor l, ref PixelColor d)
{
int width = Width;
int height = Height;
int x1 = x - size;
int x2 = x + size;
int y1 = y - size;
int y2 = y + size;
// Do unchecked?
if((x1 >= 0) && (x2 < visiblewidth) && (y1 >= 0) && (y2 < visibleheight))
if((x1 >= 0) && (x2 < width) && (y1 >= 0) && (y2 < height))
{
// Filled square
for(int yp = y1; yp <= y2; yp++)
@ -152,7 +133,9 @@ namespace CodeImp.DoomBuilder.Rendering
// This draws a dotted grid line horizontally
public void DrawGridLineH(int y, int x1, int x2, ref PixelColor c)
{
int numpixels = visiblewidth >> 1;
int width = Width;
int height = Height;
int numpixels = width >> 1;
int offset = y & 0x01;
int ywidth = y * width;
x1 = General.Clamp(x1 >> 1, 0, numpixels - 1);
@ -168,7 +151,9 @@ namespace CodeImp.DoomBuilder.Rendering
// This draws a dotted grid line vertically
public void DrawGridLineV(int x, int y1, int y2, ref PixelColor c)
{
int numpixels = visibleheight >> 1;
int width = Width;
int height = Height;
int numpixels = height >> 1;
int offset = x & 0x01;
y1 = General.Clamp(y1 >> 1, 0, numpixels - 1);
y2 = General.Clamp(y2 >> 1, 0, numpixels - 1);
@ -180,44 +165,20 @@ namespace CodeImp.DoomBuilder.Rendering
}
}
// This draws a pixel alpha blended
public void DrawPixelAlpha(int x, int y, ref PixelColor c)
{
// Draw only when within range
if((x >= 0) && (x < visiblewidth) && (y >= 0) && (y < visibleheight))
{
// Get the target pixel
PixelColor* p = pixels + (y * width + x);
// Not drawn on target yet?
if(*(int*)p == 0)
{
// Simply apply color to pixel
*p = c;
}
else
{
// Blend with pixel
float a = c.a * 0.003921568627450980392156862745098f;
if(p->a + c.a > 255) p->a = 255; else p->a += c.a;
p->r = (byte)(p->r * (1f - a) + c.r * a);
p->g = (byte)(p->g * (1f - a) + c.g * a);
p->b = (byte)(p->b * (1f - a) + c.b * a);
}
}
}
// This draws a line normally
// See: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
public void DrawLineSolid(int x1, int y1, int x2, int y2, ref PixelColor c, uint mask = 0xffffffff)
{
// Check if the line is outside the screen for sure.
// This is quickly done by checking in which area both points are. When this
// is above, below, right or left of the screen, then skip drawing the line.
if(((x1 < 0) && (x2 < 0)) ||
((x1 > visiblewidth) && (x2 > visiblewidth)) ||
int width = Width;
int height = Height;
// Check if the line is outside the screen for sure.
// This is quickly done by checking in which area both points are. When this
// is above, below, right or left of the screen, then skip drawing the line.
if (((x1 < 0) && (x2 < 0)) ||
((x1 > width) && (x2 > width)) ||
((y1 < 0) && (y2 < 0)) ||
((y1 > visibleheight) && (y2 > visibleheight))) return;
((y1 > height) && (y2 > height))) return;
// Distance of the line
int dx = x2 - x1;
@ -242,8 +203,8 @@ namespace CodeImp.DoomBuilder.Rendering
// When the line is completely inside screen,
// then do an unchecked draw, because all of its pixels are
// guaranteed to be within the memory range
if((x1 >= 0) && (x2 >= 0) && (x1 < visiblewidth) && (x2 < visiblewidth) &&
(y1 >= 0) && (y2 >= 0) && (y1 < visibleheight) && (y2 < visibleheight))
if((x1 >= 0) && (x2 >= 0) && (x1 < width) && (x2 < width) &&
(y1 >= 0) && (y2 >= 0) && (y1 < height) && (y2 < height))
{
// Draw first pixel
pixels[py * width + px] = c;
@ -290,7 +251,7 @@ namespace CodeImp.DoomBuilder.Rendering
else
{
// Draw first pixel
if((px >= 0) && (px < visiblewidth) && (py >= 0) && (py < visibleheight))
if((px >= 0) && (px < width) && (py >= 0) && (py < height))
pixels[py * width + px] = c;
// Check if the line is more horizontal than vertical
@ -308,7 +269,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Draw pixel
if ((mask & (1 << (i & 0x7))) != 0) {
if((px >= 0) && (px < visiblewidth) && (py >= 0) && (py < visibleheight))
if((px >= 0) && (px < width) && (py >= 0) && (py < height))
pixels[py * width + px] = c;
}
}
@ -328,7 +289,7 @@ namespace CodeImp.DoomBuilder.Rendering
// Draw pixel
if ((mask & (1 << (i & 0x7))) != 0) {
if((px >= 0) && (px < visiblewidth) && (py >= 0) && (py < visibleheight))
if((px >= 0) && (px < width) && (py >= 0) && (py < height))
pixels[py * width + px] = c;
}
}
@ -359,7 +320,5 @@ namespace CodeImp.DoomBuilder.Rendering
DrawLineSolid((int)p2.x, (int)p2.y, (int)end.x, (int)end.y, ref c2);
}
}
#endregion
}
}

View file

@ -313,16 +313,12 @@ namespace CodeImp.DoomBuilder.Rendering
bitmap.UnlockBits(bmpdata);
}
internal Plotter LockPlotter(Texture texture, int visibleWidth, int visibleHeight)
internal IntPtr LockTexture(Texture texture)
{
unsafe
{
IntPtr data = RenderDevice_LockTexture(Handle, texture.Handle);
return new Plotter((PixelColor*)data.ToPointer(), texture.Width, texture.Height, Math.Min(texture.Width, visibleWidth), Math.Min(texture.Height, visibleHeight));
}
return RenderDevice_LockTexture(Handle, texture.Handle);
}
public void UnlockPlotter(Texture texture)
public void UnlockTexture(Texture texture)
{
RenderDevice_UnlockTexture(Handle, texture.Handle);
}

View file

@ -60,21 +60,14 @@ namespace CodeImp.DoomBuilder.Rendering
#region ================== Variables
// Rendertargets
private Texture backtex;
private Texture plottertex;
private Texture thingstex;
private Plotter gridplotter;
private Plotter plotter;
private Texture thingstex;
private Texture overlaytex;
private Texture surfacetex;
// Rendertarget sizes
private Size windowsize;
private Size structsize;
private Size thingssize;
private Size overlaysize;
private Size backsize;
// Geometry plotter
private Plotter plotter;
// Vertices to present the textures
private VertexBuffer screenverts;
@ -247,16 +240,16 @@ namespace CodeImp.DoomBuilder.Rendering
// GRID
case RendererLayer.Grid:
graphics.SetShader(aapass);
graphics.SetTexture(backtex);
SetDisplay2DSettings(1f / backsize.Width, 1f / backsize.Height, FSAA_FACTOR, layer.alpha, false, true);
graphics.SetTexture(gridplotter.Texture);
SetDisplay2DSettings(1f / gridplotter.Width, 1f / gridplotter.Height, FSAA_FACTOR, layer.alpha, false, true);
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
break;
// GEOMETRY
case RendererLayer.Geometry:
graphics.SetShader(aapass);
graphics.SetTexture(plottertex);
SetDisplay2DSettings(1f / structsize.Width, 1f / structsize.Height, FSAA_FACTOR, layer.alpha, false, false);
graphics.SetTexture(plotter.Texture);
SetDisplay2DSettings(1f / plotter.Width, 1f / plotter.Height, FSAA_FACTOR, layer.alpha, false, false);
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
break;
@ -264,7 +257,7 @@ namespace CodeImp.DoomBuilder.Rendering
case RendererLayer.Things:
graphics.SetShader(aapass);
graphics.SetTexture(thingstex);
SetDisplay2DSettings(1f / thingssize.Width, 1f / thingssize.Height, FSAA_FACTOR, layer.alpha, false, true);
SetDisplay2DSettings(1f / thingstex.Width, 1f / thingstex.Height, FSAA_FACTOR, layer.alpha, false, true);
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
break;
@ -272,7 +265,7 @@ namespace CodeImp.DoomBuilder.Rendering
case RendererLayer.Overlay:
graphics.SetShader(aapass);
graphics.SetTexture(overlaytex);
SetDisplay2DSettings(1f / overlaysize.Width, 1f / overlaysize.Height, FSAA_FACTOR, layer.alpha, false, true);
SetDisplay2DSettings(1f / overlaytex.Width, 1f / overlaytex.Height, FSAA_FACTOR, layer.alpha, false, true);
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
break;
@ -280,7 +273,7 @@ namespace CodeImp.DoomBuilder.Rendering
case RendererLayer.Surface:
graphics.SetShader(aapass);
graphics.SetTexture(surfacetex);
SetDisplay2DSettings(1f / overlaysize.Width, 1f / overlaysize.Height, FSAA_FACTOR, layer.alpha, false, true);
SetDisplay2DSettings(1f / overlaytex.Width, 1f / overlaytex.Height, FSAA_FACTOR, layer.alpha, false, true);
graphics.Draw(PrimitiveType.TriangleStrip, 0, 2);
break;
}
@ -326,15 +319,14 @@ namespace CodeImp.DoomBuilder.Rendering
public void DestroyRendertargets()
{
// Trash rendertargets
if(plottertex != null) plottertex.Dispose();
if(plotter != null) plotter.Dispose();
if(thingstex != null) thingstex.Dispose();
if(overlaytex != null) overlaytex.Dispose();
if(surfacetex != null) surfacetex.Dispose();
if(backtex != null) backtex.Dispose();
if(gridplotter != null) gridplotter.Dispose();
if(screenverts != null) screenverts.Dispose();
plottertex = null;
thingstex = null;
backtex = null;
gridplotter = null;
screenverts = null;
overlaytex = null;
surfacetex = null;
@ -357,28 +349,13 @@ namespace CodeImp.DoomBuilder.Rendering
windowsize.Height = graphics.RenderTarget.ClientSize.Height;
// Create rendertargets textures
plottertex = new Texture(windowsize.Width, windowsize.Height);
thingstex = new Texture(windowsize.Width, windowsize.Height);
backtex = new Texture(windowsize.Width, windowsize.Height);
plotter = new Plotter(windowsize.Width, windowsize.Height);
gridplotter = new Plotter(windowsize.Width, windowsize.Height);
thingstex = new Texture(windowsize.Width, windowsize.Height);
overlaytex = new Texture(windowsize.Width, windowsize.Height);
surfacetex = new Texture(windowsize.Width, windowsize.Height);
// Get the real surface sizes
structsize.Width = plottertex.Width;
structsize.Height = plottertex.Height;
thingssize.Width = thingstex.Width;
thingssize.Height = thingstex.Height;
backsize.Width = backtex.Width;
backsize.Height = backtex.Height;
overlaysize.Width = overlaytex.Width;
overlaysize.Height = overlaytex.Height;
// Clear rendertargets
// This may cause a crash when resetting because it recursively
// calls Reset in the Start functions and doesn't get to Finish
//StartPlotter(true); Finish();
//StartThings(true); Finish();
//StartOverlay(true); Finish();
graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), thingstex);
graphics.ClearTexture(General.Colors.Background.WithAlpha(0).ToColorValue(), overlaytex);
@ -388,7 +365,7 @@ namespace CodeImp.DoomBuilder.Rendering
graphics.SetBufferData(thingsvertices, THING_BUFFER_SIZE * 12, VertexFormat.Flat);
// Make screen vertices
FlatVertex[] verts = CreateScreenVerts(structsize);
FlatVertex[] verts = CreateScreenVerts(new Size(plotter.Width, plotter.Height));
graphics.SetBufferData(screenverts, verts);
// Force update of view
@ -647,10 +624,9 @@ namespace CodeImp.DoomBuilder.Rendering
renderlayer = RenderLayers.Plotter;
// Rendertargets available?
if(plottertex != null)
if(plotter != null)
{
// Create structures plotter
plotter = graphics.LockPlotter(plottertex, structsize.Width, structsize.Height);
plotter.Begin(graphics);
// Redraw grid when structures image was cleared
if(clear)
@ -733,11 +709,10 @@ namespace CodeImp.DoomBuilder.Rendering
// This ends a drawing session
public void Finish()
{
// Clean up plotter
// Draw plotter contents
if(renderlayer == RenderLayers.Plotter)
{
if(plottertex != null) graphics.UnlockPlotter(plottertex);
plotter = null;
plotter.DrawContents(graphics);
}
// Clean up things / overlay
@ -804,8 +779,8 @@ namespace CodeImp.DoomBuilder.Rendering
if(lastgridsize != General.Map.Grid.GridSizeF || lastgridscale != scale ||
lastgridx != offsetx || lastgridy != offsety || drawmapcenter != lastdrawmapcenter)
{
// Create a plotter
Plotter gridplotter = graphics.LockPlotter(backtex, backsize.Width, backsize.Height);
// Create a plotter
gridplotter.Begin(graphics);
gridplotter.Clear();
if(General.Settings.RenderGrid) //mxd
@ -859,7 +834,7 @@ namespace CodeImp.DoomBuilder.Rendering
}
// Done
graphics.UnlockPlotter(backtex);
gridplotter.DrawContents(graphics);
lastgridscale = scale;
lastgridsize = General.Map.Grid.GridSizeF;
lastgridx = offsetx;