- Simulator rasterizer working

- Beginning hardware rasterizer implementation
This commit is contained in:
2013-03-22 20:12:20 +01:00
parent 922e103f41
commit 1d71dfc308
4 changed files with 403 additions and 85 deletions

View File

@@ -1,6 +1,7 @@
#include <algorithm>
#include <iostream>
#include <stdint.h>
#include <assert.h>
#include "Memory.hh"
#include "Rasterizer.hh"
@@ -19,16 +20,57 @@ typedef union {
uint16_t u16[4];
} pd;
void Rasterizer::pixel(int x, int y) {
cout << "(" << x << "," << y << ")" << endl;
void Rasterizer::pixel(unsigned x, unsigned y, uint16_t val) {
//cout << "(" << x << "," << y << ")" << endl;
unsigned adr = ((y*640)+x)/4;
unsigned ofs = ((y*640)+x)%4;
pd data;
data.u64 = mem_.read(adr);
data.u16[ofs] = 0x0fffu;
data.u16[ofs] = val;
mem_.write(adr, data.u64);
}
void Rasterizer::line(unsigned y, unsigned l, unsigned r, unsigned lu, unsigned ru, unsigned lv, unsigned rv) {
cout << "line " << y << ": " << l << "->" << r << "(" << lu << "," << ru << "," << lv << "," << rv << ")" << endl;
pixel(l,y,((lu/16)<<4)|(lv/16));
pixel(r,y,((ru/16)<<4)|(rv/16));
unsigned u = lu, v = lv;
int dx = r-l;
unsigned du = abs(lu-ru);
unsigned dv = abs(lv-rv);
int su, sv;
if(lu<ru)
su = 1;
else
su = -1;
if(lv<rv)
sv = 1;
else
sv = -1;
int uerr = du-dx;
int verr = dv-dx;
cout << "\t" << dx << "," << du << "," << dv << "," << uerr << "," << verr << endl;
for(unsigned x = l+1;x < r;++x) {
//cout << "\t\t@" << x << "," << uerr << endl;
while(dx && (2*uerr>-dx) && !(2*uerr<du)) {
uerr-=dx;
u += su;
}
while(dx && (2*verr>-dx) && !(2*verr<dv)) {
verr-=dx;
v += sv;
}
cout << "@("<<x<<","<<y<<"):"<<u<<","<<v<<endl;
pixel(x, y, (u&0xf0)|(v>>4));
uerr+=du;
verr+=dv;
}
}
void Rasterizer::rasterize(triangle t) {
// sort vertices by y inc, x inc
std::sort(t.begin(), t.end(),
@@ -36,99 +78,207 @@ void Rasterizer::rasterize(triangle t) {
// compute bounding box
vertex2 ul, lr;
ul.x = std::min_element(t.begin(), t.end(),
[](vertex2 const& a, vertex2 const& b)->bool{return a.x<b.x;})->x;
lr.x = std::max_element(t.begin(), t.end(),
[](vertex2 const& a, vertex2 const& b)->bool{return a.x<b.x;})->x;
ul.y = std::min_element(t.begin(), t.end(),
[](vertex2 const& a, vertex2 const& b)->bool{return a.y<b.y;})->y;
lr.y = std::max_element(t.begin(), t.end(),
[](vertex2 const& a, vertex2 const& b)->bool{return a.y<b.y;})->y;
// ul.x = std::min_element(t.begin(), t.end(),
// [](vertex2 const& a, vertex2 const& b)->bool{return a.x<b.x;})->x;
// lr.x = std::max_element(t.begin(), t.end(),
// [](vertex2 const& a, vertex2 const& b)->bool{return a.x<b.x;})->x;
ul.y = t[0].y;
lr.y = t[2].y;
// ul.y = std::min_element(t.begin(), t.end(),
// [](vertex2 const& a, vertex2 const& b)->bool{return a.y<b.y;})->y;
// lr.y = std::max_element(t.begin(), t.end(),
// [](vertex2 const& a, vertex2 const& b)->bool{return a.y<b.y;})->y;
cout << "Bounding box ("<<ul.x<<","<<ul.y<<")->("<<lr.x<<","<<lr.y<<")"<<endl;
//cout << "Bounding box ("<<ul.x<<","<<ul.y<<")->("<<lr.x<<","<<lr.y<<")"<<endl;
// Draw bounding box
// for(unsigned x=ul.x;x <=lr.x;++x) {
// pixel(x, ul.y, 0x00f0u);
// pixel(x, lr.y, 0x00f0u);
// }
// for(unsigned y=ul.y;y<=lr.y;++y) {
// pixel(ul.x, y, 0x00f0u);
// pixel(lr.x, y, 0x00f0u);
// }
// Draw vertices
// pixel(t[0].x, t[0].y, 0x0f00u);
// pixel(t[1].x, t[1].y, 0x0f00u);
// pixel(t[2].x, t[2].y, 0x0f00u);
// TODO: special case 2 vertices on first line
int leftfrom = 0, rightfrom = 0;
int leftto, rightto;
if(t[1].x>t[2].x) {
unsigned left = t[0].x, right = t[0].x;
unsigned leftu = t[0].u, rightu = t[0].u;
unsigned leftv = t[0].v, rightv = t[0].v;
if(t[0].y == t[1].y) {
// special case: 2 vertices on first line
//line(t[0].y, t[0].x, t[1].x, t[0].u, t[1].u, t[0].v, t[1].v);
rightfrom = 1;
leftto = 2;
rightto = 1;
} else {
leftto = 1;
rightto = 2;
right = t[1].x;
rightu = t[1].u;
rightv = t[1].v;
} else {
if(t[1].x>t[2].x) {
leftto = 2;
rightto = 1;
} else {
leftto = 1;
rightto = 2;
}
}
pixel(t[0].x,t[0].y);
int left = t[0].x, right = t[0].x;
int leftdx = abs(t[leftto].x-t[leftfrom].x);
int leftdy = t[leftto].y-t[leftfrom].y;
int leftdu = abs(t[leftto].u-t[leftfrom].u);
int leftdv = abs(t[leftto].v-t[leftfrom].v);
int rightdx = abs(t[rightto].x-t[rightfrom].x);
int rightdy = t[rightto].y-t[rightfrom].y;
int rightdu = abs(t[rightto].u-t[rightfrom].u);
int rightdv = abs(t[rightto].v-t[rightfrom].v);
int leftsx, rightsx;
int leftsx, leftsu, leftsv, rightsx, rightsu, rightsv;
if(t[leftfrom].x < t[leftto].x)
leftsx = 1;
else
leftsx = -1;
if(t[leftfrom].u < t[leftto].u)
leftsu = 1;
else
leftsu = -1;
if(t[leftfrom].v < t[leftto].v)
leftsv = 1;
else
leftsv = -1;
if(t[rightfrom].x < t[rightto].x)
rightsx = 1;
else
rightsx = -1;
int lefterr = leftdx-leftdy;
int righterr = rightdx-rightdy;
if(t[rightfrom].u < t[rightto].u)
rightsu = 1;
else
rightsu = -1;
if(t[rightfrom].v < t[rightto].v)
rightsv = 1;
else
rightsv = -1;
for(int line = ul.y;line < lr.y;++line) {
if((leftto == rightto) && (line == t[leftto].y)) {
for(int x = left;x <= right;++x)
pixel(x, line);
} else {
if(line == t[leftto].y) {
leftfrom = leftto;
leftto = (leftto==1)?2:1;
pixel(t[leftfrom].x, t[leftfrom].y);
left = t[leftfrom].x;
// reinit
leftdx = abs(t[leftto].x-t[leftfrom].x);
leftdy = abs(t[leftto].y-t[leftfrom].y);
if(t[leftfrom].x < t[leftto].x)
leftsx = 1;
else
leftsx = -1;
lefterr = leftdx-leftdy;
}
if(line == t[rightto].y) {
rightfrom = rightto;
rightto = (rightto==1)?2:1;
pixel(t[rightfrom].x, t[rightfrom].y);
right = t[rightfrom].x;
// reinit
rightdx = abs(t[rightto].x-t[rightfrom].x);
rightdy = abs(t[rightto].y-t[rightfrom].y);
if(t[rightfrom].x < t[rightto].x)
rightsx = 1;
else
rightsx = -1;
righterr = rightdx-rightdy;
}
while(2*lefterr>-leftdy) {
lefterr-=leftdy;
left += leftsx;
}
while(2*righterr>-rightdy) {
righterr-=rightdy;
right += rightsx;
}
for(int x = left;x <= right;++x)
pixel(x, line);
lefterr += leftdx;
righterr += rightdx;
}
}
int lefterr = leftdx-leftdy, lefterru = leftdu-leftdy, lefterrv = leftdv-leftdy;
int righterr = rightdx-rightdy, righterru = rightdu-rightdy, righterrv = rightdv-rightdy;
line(t[leftfrom].y, t[leftfrom].x, t[rightfrom].x, t[leftfrom].u, t[rightfrom].u, t[leftfrom].v, t[rightfrom].v);
for(int l = ul.y+1;l <= lr.y;++l) {
if((l == t[leftto].y) && (l == t[rightto].y) && (leftto != rightto)) {
assert(l == lr.y);
// special case: 2 vertices on last line
line(l, t[leftto].x, t[rightto].x, t[leftto].u, t[rightto].u, t[leftto].v, t[rightto].v);
break;
}
while((2*lefterr>-leftdy) && !(2*lefterr<leftdx)) {
lefterr-=leftdy;
left += leftsx;
}
while((2*lefterru>-leftdy) && !(2*lefterru<leftdu)) {
lefterru-=leftdy;
leftu += leftsu;
}
while((2*lefterrv>-leftdy) && !(2*lefterrv<leftdv)) {
lefterrv-=leftdy;
leftv += leftsv;
}
while((2*righterr>-rightdy) && !(2*righterr<rightdx)) {
righterr-=rightdy;
right += rightsx;
}
while((2*righterru>-rightdy) && !(2*righterru<rightdu)) {
righterru-=rightdy;
rightu += rightsu;
}
while((2*righterrv>-rightdy) && !(2*righterrv<rightdv)) {
righterrv-=rightdy;
rightv += rightsv;
}
// if(left < ul.x)
// left = ul.x;
// if(right > lr.x)
// right = lr.x;
//line(l, left, right, leftu, rightu, leftv, rightv);
lefterr += leftdx;
lefterru += leftdu;
lefterrv += leftdv;
righterr += rightdx;
righterru += rightdu;
righterrv += rightdv;
if(l == t[leftto].y) {
leftfrom = leftto;
leftto = (leftto==1)?2:1;
//pixel(t[leftfrom].x, t[leftfrom].y);
left = t[leftfrom].x;
leftu = t[leftfrom].u;
leftv = t[leftfrom].v;
// reinit
leftdx = abs(t[leftto].x-t[leftfrom].x);
leftdy = t[leftto].y-t[leftfrom].y;
leftdu = abs(t[leftto].u-t[leftfrom].u);
leftdv = abs(t[leftto].v-t[leftfrom].v);
if(t[leftfrom].x < t[leftto].x)
leftsx = 1;
else
leftsx = -1;
if(t[leftfrom].u < t[leftto].u)
leftsu = 1;
else
leftsu = -1;
if(t[leftfrom].v < t[leftto].v)
leftsv = 1;
else
leftsv = -1;
lefterr = leftdx-leftdy;
lefterru = leftdu-leftdy;
lefterrv = leftdv-leftdy;
} else if(l == t[rightto].y) {
rightfrom = rightto;
rightto = (rightto==1)?2:1;
//pixel(t[rightfrom].x, t[rightfrom].y);
right = t[rightfrom].x;
rightu = t[rightfrom].u;
rightv = t[rightfrom].v;
// reinit
rightdx = abs(t[rightto].x-t[rightfrom].x);
rightdy = t[rightto].y-t[rightfrom].y;
rightdu = abs(t[rightto].u-t[rightfrom].u);
rightdv = abs(t[rightto].v-t[rightfrom].v);
if(t[rightfrom].x < t[rightto].x)
rightsx = 1;
else
rightsx = -1;
if(t[rightfrom].u < t[rightto].u)
rightsu = 1;
else
rightsu = -1;
if(t[rightfrom].v < t[rightto].v)
rightsv = 1;
else
rightsv = -1;
righterr = rightdx-rightdy;
righterru = rightdu-rightdy;
righterrv = rightdv-rightdy;
}
line(l, left, right, leftu, rightu, leftv, rightv);
}
}

View File

@@ -2,26 +2,29 @@
#define _SIM_RASTERIZER_HH_
#include <array>
#include <stdint.h>
class Memory;
typedef struct {
unsigned x, y;
unsigned u,v;
} vertex2;
typedef std::array<vertex2, 3> triangle;
class Rasterizer {
public:
Rasterizer(Memory& mem);
~Rasterizer();
Rasterizer(Memory& mem);
~Rasterizer();
void rasterize(triangle t);
void rasterize(triangle t);
private:
Memory& mem_;
Memory& mem_;
void pixel(int x, int y);
void pixel(unsigned x, unsigned y, uint16_t val = 0x0fffu);
void line(unsigned y, unsigned l, unsigned r, unsigned lu, unsigned ru, unsigned lv, unsigned rv);
};
#endif

View File

@@ -37,7 +37,7 @@ int main(int argc, char *argv[]) {
cout << "Unable to create surface: " << SDL_GetError() << endl;
return -1;
}
SDL_FillRect(framebuffer, NULL, SDL_MapRGB(framebuffer->format, 0, 255, 255));
SDL_FillRect(framebuffer, NULL, SDL_MapRGB(framebuffer->format, 0, 0, 0));
// Load a bitmap and copy it into simulated DDRRAM
@@ -65,9 +65,9 @@ int main(int argc, char *argv[]) {
Rasterizer r(mem);
cout << "Running..." << endl;
triangle t{{{100, 100},
{150, 200},
{50, 250}}};
triangle t{{{100, 100, 0, 0},
{150, 200, 255, 0},
{50, 250, 0, 255}}};
r.rasterize(t);
// return 0;

165
src/bresenham_dp.vhd Normal file
View File

@@ -0,0 +1,165 @@
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 03/22/2013 05:49:49 PM
-- Design Name:
-- Module Name: bresenham_dp - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity bresenham_dp is
port(
clk : in STD_LOGIC;
x0, x1 : in unsigned(15 downto 0);
i0, i1 : in unsigned(15 downto 0);
load_dx : in std_logic;
load_di : in std_logic;
init : in std_logic;
next_x : out std_logic;
done : out std_logic;
i : out unsigned(15 downto 0);
x : out unsigned(15 downto 0));
end bresenham_dp;
architecture Behavioral of bresenham_dp is
signal neg_dx : signed(15 downto 0) := to_signed(0, 16);
signal x1_int : unsigned(15 downto 0) := to_unsigned(0, 16);
signal di : signed(15 downto 0) := to_signed(0, 16);
signal si : std_logic := '0';
signal d_sub_1, d_sub_2 : unsigned(15 downto 0) := to_unsigned(0, 16);
signal d_sub, d_sub_abs : signed(15 downto 0) := to_signed(0, 16);
signal err, err_next : signed(15 downto 0) := to_signed(0, 16);
signal err_add_1, err_add_2 : signed(15 downto 0) := to_signed(0, 16);
signal looping : std_logic := '0';
signal err_gt_negdx, err_ge_di : std_logic := '0';
signal i_int, i_next, i_add : unsigned(15 downto 0) := to_unsigned(0, 16);
signal x_int : unsigned(15 downto 0) := to_unsigned(0, 16);
begin
x_reg : process(clk)
begin
if rising_edge(clk) then
if load_dx = '1' then
neg_dx <= d_sub;
x1_int <= x1;
end if;
end if;
end process x_reg;
di_reg : process(clk)
begin
if rising_edge(clk) then
if load_di = '1' then
di <= d_sub_abs;
end if;
end if;
end process di_reg;
si_reg : process(clk)
begin
if rising_edge(clk) then
if load_di = '1' then
si <= d_sub(d_sub'left);
end if;
end if;
end process si_reg;
d_sub_1 <= x1 when load_dx = '1' else
i0;
d_sub_2 <= x0 when load_dx = '1' else
i1;
d_sub <= signed(d_sub_1) - signed(d_sub_2);
d_sub_abs <= d_sub when d_sub(d_sub'left) = '0' else
-d_sub;
err_reg : process(clk)
begin
if rising_edge(clk) then
err <= err_next;
end if;
end process err_reg;
err_add_1 <= neg_dx when looping = '1' or init = '1' else
di;
err_add_2 <= di when init = '1' else
err;
err_next <= err_add_1 + err_add_2;
err_gt_negdx <= '1' when (err & "0") > neg_dx else
'0';
err_ge_di <= '1' when (err & "0") >= di else
'0';
looping <= err_gt_negdx and err_ge_di;
i_reg : process(clk)
begin
if rising_edge(clk) then
if init = '1' or looping = '1' then
i_int <= i_next;
end if;
end if;
end process i_reg;
i_add <= i_int + 1 when si = '0' else
i_int - 1;
i_next <= i0 when init = '1' else
i_add;
x_ctr : process(clk)
begin
if rising_edge(clk) then
done <= '0';
if load_di = '1' then
x_int <= x0;
elsif looping = '0' or init = '1' then
if x_int = x1_int then
done <= '1';
end if;
x_int <= x_int+1;
end if;
end if;
end process x_ctr;
i <= i_int;
x <= x_int;
next_x <= not looping;
end Behavioral;