Advertisement
Guest User

Untitled

a guest
Aug 29th, 2014
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 10.31 KB | None | 0 0
  1. module game.renderer.rasterizer;
  2.  
  3. import std.traits;
  4. import std.algorithm;
  5.  
  6. import gamelib.util;
  7.  
  8. import game.units;
  9.  
  10. struct Rasterizer(BitmapT,TextureT)
  11. {
  12. private:
  13.     BitmapT mBitmap;
  14.     TextureT mTexture;
  15.     Rect mClipRect;
  16.     enum AffineLength = 16;
  17.     struct Edge(PosT, bool Affine)
  18.     {
  19.     private:
  20.         PosT factor;
  21.         immutable PosT factorStep;
  22.         immutable PosT xStart;
  23.         immutable PosT xDiff;
  24.  
  25.         static if(Affine)
  26.         {
  27.             immutable PosT uStart;
  28.             immutable PosT uDiff;
  29.  
  30.             immutable PosT vStart;
  31.             immutable PosT vDiff;
  32.         }
  33.         else
  34.         {
  35.             immutable PosT suStart;
  36.             immutable PosT suDiff;
  37.  
  38.             immutable PosT svStart;
  39.             immutable PosT svDiff;
  40.  
  41.             immutable PosT swStart;
  42.             immutable PosT swDiff;
  43.         }
  44.     public:
  45.         this(VT)(in VT v1, in VT v2, int inc) pure nothrow
  46.         {
  47.             const ydiff = v1.pos.y - v2.pos.y;
  48.             factorStep = cast(PosT)1 / ydiff;
  49.             factor = factorStep * inc;
  50.             xStart = v1.pos.x;
  51.             xDiff  = v1.pos.x  - v2.pos.x;
  52.             static if(Affine)
  53.             {
  54.                 uStart = v1.tpos.u;
  55.                 uDiff  = v1.tpos.u - v2.tpos.u;
  56.                 vStart = v1.tpos.v;
  57.                 vDiff  = v1.tpos.v - v2.tpos.v;
  58.             }
  59.             else
  60.             {
  61.                 const w1 = cast(PosT)1 / v1.pos.w;
  62.                 const w2 = cast(PosT)1 / v2.pos.w;
  63.                 suStart = v1.tpos.u * w1;
  64.                 suDiff  = suStart - v2.tpos.u * w2;
  65.                 svStart = v1.tpos.v * w1;
  66.                 svDiff  = svStart - v2.tpos.v * w2;
  67.                 swStart = w1;
  68.                 swDiff  = (w1 - w2);
  69.             }
  70.         }
  71.  
  72.         @property auto x() const pure nothrow { return xStart + xDiff * factor; }
  73.         static if(Affine)
  74.         {
  75.             @property auto u() const pure nothrow { return uStart + uDiff * factor; }
  76.             @property auto v() const pure nothrow { return vStart + vDiff * factor; }
  77.         }
  78.         else
  79.         {
  80.             @property auto su() const pure nothrow { return suStart + suDiff * factor; }
  81.             @property auto sv() const pure nothrow { return svStart + svDiff * factor; }
  82.             @property auto sw() const pure nothrow { return swStart + swDiff * factor; }
  83.         }
  84.         ref auto opUnary(string op: "++")() pure nothrow { factor += factorStep; return this; }
  85.     }
  86.     struct Span(PosT, bool Affine)
  87.     {
  88.         PosT x1, x2;
  89.         static if(Affine)
  90.         {
  91.             PosT u, u2;
  92.             PosT v, v2;
  93.             immutable PosT du, dv;
  94.         }
  95.         else
  96.         {
  97.             PosT su1, su2;
  98.             PosT sv1, sv2;
  99.             PosT sw1, sw2;
  100.             immutable PosT dsu, dsv, dsw;
  101.             PosT nu, nv;
  102.             PosT pu, pv;
  103.             PosT du, dv;
  104.         }
  105.  
  106.         this(EdgeT)(in EdgeT e1, in EdgeT e2) pure nothrow
  107.         {
  108.             x1 = e1.x;
  109.             x2 = e2.x;
  110.             const dx = x2 - x1;
  111.             static if(Affine)
  112.             {
  113.                 u = e1.u;
  114.                 u2 = e2.u;
  115.                 v = e1.v;
  116.                 v2 = e2.v;
  117.                 du = (u2 - u) / dx;
  118.                 dv = (v2 - v) / dx;
  119.             }
  120.             else
  121.             {
  122.                 su1 = e1.su;
  123.                 su2 = e2.su;
  124.                 sv1 = e1.sv;
  125.                 sv2 = e2.sv;
  126.                 sw1 = e1.sw;
  127.                 sw2 = e2.sw;
  128.                 dsu = (su2 - su1) / dx;
  129.                 dsv = (sv2 - sv1) / dx;
  130.                 dsw = (sw2 - sw1) / dx;
  131.                 nu = su1 / sw1;
  132.                 nv = sv1 / sw1;
  133.             }
  134.         }
  135.         @property bool valid() const pure nothrow { return x2 > x1; }
  136.         void clip(PosT minX, PosT maxX) pure nothrow
  137.         {
  138.             const x1inc = max(cast(PosT)0, minX - x1);
  139.             x1 += x1inc;
  140.             x2 = min(x2, maxX);
  141.             inc(x1inc);
  142.         }
  143.         void inc(PosT val) pure nothrow
  144.         {
  145.             static if(Affine)
  146.             {
  147.                 u += du * val;
  148.                 v += dv * val;
  149.             }
  150.             else
  151.             {
  152.                 pu = nu;
  153.                 pv = nv;
  154.                 su1 += dsu * val;
  155.                 sv1 += dsv * val;
  156.                 sw1 += dsw * val;
  157.                 nu = su1 / sw1;
  158.                 nv = sv1 / sw1;
  159.                 du = (nu - pu) / val;
  160.                 dv = (nv - pv) / val;
  161.             }
  162.         }
  163.         static if(!Affine)
  164.         {
  165.             @property PosT u() const pure nothrow { return pu; }
  166.             @property PosT v() const pure nothrow { return pv; }
  167.         }
  168.     }
  169. public:
  170.     this(BitmapT b)
  171.     {
  172.         assert(b !is null);
  173.         b.lock();
  174.         mBitmap = b;
  175.         mClipRect = Rect(0, 0, mBitmap.width, mBitmap.height);
  176.     }
  177.  
  178.     ~this()
  179.     {
  180.         mBitmap.unlock();
  181.     }
  182.  
  183.     @property auto texture() inout pure nothrow { return mTexture; }
  184.     @property void texture(TextureT tex) pure nothrow { mTexture = tex; }
  185.  
  186.     @property void clipRect(in Rect rc) pure nothrow
  187.     {
  188.         const srcLeft   = rc.x;
  189.         const srcTop    = rc.y;
  190.         const srcRight  = rc.x + rc.w;
  191.         const srcBottom = rc.y + rc.h;
  192.         const dstLeft   = max(0, srcLeft);
  193.         const dstTop    = max(0, srcTop);
  194.         const dstRight  = min(srcRight,  mBitmap.width);
  195.         const dstBottom = min(srcBottom, mBitmap.height);
  196.         mClipRect = Rect(dstLeft, dstTop, dstRight - dstLeft, dstBottom - dstTop);
  197.     }
  198.  
  199.     void drawIndexedTriangle(VertT,IndT)(in VertT[] verts, in IndT[3] indices) if(isIntegral!IndT)
  200.     {
  201.         const(VertT)*[3] pverts;
  202.         foreach(i,ind; indices) pverts[i] = verts.ptr + ind;
  203.         sort!("a.pos.y < b.pos.y")(pverts[0..$]);
  204.  
  205.         const e1xdiff = pverts[0].pos.x - pverts[2].pos.x;
  206.         const e2xdiff = pverts[0].pos.x - pverts[1].pos.x;
  207.  
  208.         const e1ydiff = pverts[0].pos.y - pverts[2].pos.y;
  209.         const e2ydiff = pverts[0].pos.y - pverts[1].pos.y;
  210.  
  211.         const cxdiff = ((e1xdiff / e1ydiff) * e2ydiff) - e2xdiff;
  212.         const reverseSpans = (cxdiff < 0);
  213.         const affine = false;//(abs(cxdiff) > AffineLength * 25);
  214.  
  215.         if(reverseSpans)
  216.         {
  217.             if(affine) drawTriangle!(true,true)(pverts);
  218.             else       drawTriangle!(false,true)(pverts);
  219.         }
  220.         else
  221.         {
  222.             if(affine) drawTriangle!(true,false)(pverts);
  223.             else       drawTriangle!(false,false)(pverts);
  224.         }
  225.     }
  226.     private void drawTriangle(bool Affine,bool ReverseSpans,VertT)(in VertT[3] pverts)
  227.     {
  228.         assert(isSorted!("a.pos.y < b.pos.y")(pverts[0..$]));
  229.         alias PosT = Unqual!(typeof(VertT.pos.x));
  230.         auto minY = cast(int)pverts[0].pos.y;
  231.         auto midY = cast(int)pverts[1].pos.y;
  232.         auto maxY = cast(int)pverts[2].pos.y;
  233.  
  234.         const minYinc = max(0, mClipRect.y - minY);
  235.         const midYinc = max(0, mClipRect.y - midY);
  236.         minY += minYinc;
  237.         midY += midYinc;
  238.         maxY = min(maxY, mClipRect.y + mClipRect.h);
  239.         if(minY >= maxY) return;
  240.         midY = min(midY, maxY);
  241.  
  242.         auto edge1 = Edge!(PosT,Affine)(pverts[0], pverts[2], minYinc);
  243.  
  244.         auto line = mBitmap[minY];
  245.  
  246.         const minX = cast(PosT)(mClipRect.x);
  247.         const maxX = cast(PosT)(mClipRect.x + mClipRect.w);
  248.  
  249.         Color[4] colors;
  250.         colors[0] = pverts[0].color;
  251.         colors[1] = pverts[2].color;
  252.  
  253.         const tw = mTexture.width - 1;
  254.         const th = mTexture.height - 1;
  255.         const tview = mTexture.view();
  256.         void drawSpan(SpanT)(int y,
  257.                       int x1, int x2,
  258.                       in SpanT span)
  259.         {
  260.             if(x1 >= x2) return;
  261.  
  262.             Unqual!(typeof(span.u)) u = span.u;
  263.             Unqual!(typeof(span.v)) v = span.v;
  264.             foreach(x;x1..x2)
  265.             {
  266.                 const tx = cast(int)(u * tw) & tw;
  267.                 const ty = cast(int)(v * th) & th;
  268.                 line[x] = tview[ty][tx];
  269.                 u += span.du;
  270.                 v += span.dv;
  271.             }
  272.             //line[x1..x2] = ColorRed;
  273.         }
  274.  
  275.         foreach(i;TupleRange!(0,2))
  276.         {
  277.             static if(0 == i)
  278.             {
  279.                 const yStart  = minY;
  280.                 const yEnd    = midY;
  281.                 auto edge2 = Edge!(PosT,Affine)(pverts[0], pverts[1], minYinc);
  282.                 colors[2] = pverts[0].color;
  283.                 colors[3] = pverts[1].color;
  284.             }
  285.             else
  286.             {
  287.                 const yStart  = midY;
  288.                 const yEnd    = maxY;
  289.                 auto edge2 = Edge!(PosT,Affine)(pverts[1], pverts[2], midYinc);
  290.                 colors[2] = pverts[1].color;
  291.                 colors[3] = pverts[2].color;
  292.             }
  293.  
  294.             foreach(y;yStart..yEnd)
  295.             {
  296.                 static if(ReverseSpans)
  297.                 {
  298.                     auto span = Span!(PosT,Affine)(edge2, edge1);
  299.                 }
  300.                 else
  301.                 {
  302.                     auto span = Span!(PosT,Affine)(edge1, edge2);
  303.                 }
  304.                 span.clip(minX, maxX);
  305.                 //if(!span.valid) continue;
  306.                 const ix1 = cast(int)span.x1;
  307.                 const ix2 = cast(int)span.x2;
  308.                 static if(Affine)
  309.                 {
  310.                     drawSpan(y, ix1, ix2, span);
  311.                 }
  312.                 else
  313.                 {
  314.                     int x = ix1;
  315.                     while(true)
  316.                     {
  317.                         const nx = (x + AffineLength);
  318.                         if(nx < ix2)
  319.                         {
  320.                             span.inc(AffineLength);
  321.                             drawSpan(y, x, nx, span);
  322.                         }
  323.                         else
  324.                         {
  325.                             const rem =  cast(PosT)(ix2 - x);
  326.                             span.inc(rem);
  327.                             drawSpan(y, x, ix2, span);
  328.                             break;
  329.                         }
  330.                         x = nx;
  331.                     }
  332.                 }
  333.                 ++edge1;
  334.                 ++edge2;
  335.                 ++line;
  336.             }
  337.         }
  338.     }
  339. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement