dos - faster rasterization
This commit is contained in:
parent
44d2b8e350
commit
48819cf841
355
render_dos.c
355
render_dos.c
@ -15,6 +15,8 @@ struct Context
|
|||||||
uint8_t *backbuffer;
|
uint8_t *backbuffer;
|
||||||
uint8_t *colorbuffer;
|
uint8_t *colorbuffer;
|
||||||
float *depthbuffer;
|
float *depthbuffer;
|
||||||
|
uint8_t *texture;
|
||||||
|
float lightdir[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t *vga = (uint8_t *)0xA0000;
|
static uint8_t *vga = (uint8_t *)0xA0000;
|
||||||
@ -154,8 +156,8 @@ static void MapToRes(struct Context *ctx, float a[])
|
|||||||
a[1] = a[1] / a[3];
|
a[1] = a[1] / a[3];
|
||||||
a[2] = a[2] / a[3];
|
a[2] = a[2] / a[3];
|
||||||
|
|
||||||
a[0] = (a[0] + 1.0) * 0.5 * (ctx->width - 1);
|
a[0] = (a[0] + 1.0f) * 0.5f * (ctx->width - 1);
|
||||||
a[1] = (1.0 - a[1]) * 0.5 * (ctx->height - 1);
|
a[1] = (1.0f - a[1]) * 0.5f * (ctx->height - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Cross(float result[], float a[], float b[])
|
static void Cross(float result[], float a[], float b[])
|
||||||
@ -279,137 +281,248 @@ static void Perspective(float mat[], float fov, float aspectratio, float nearp,
|
|||||||
mat[15] = 0.0f;
|
mat[15] = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawTriangle(struct Context *ctx, float wp0[], float wp1[], float wp2[], uint8_t texture[], float c0[], float c1[], float c2[], float mvp[], float lightdir[], float n0[], float n1[], float n2[])
|
struct ScrVertex
|
||||||
{
|
{
|
||||||
float p0[4], p1[4], p2[4];
|
float x, y;
|
||||||
|
float t[2];
|
||||||
MatMultVec3(p0, mvp, wp0);
|
float n[3];
|
||||||
MatMultVec3(p1, mvp, wp1);
|
|
||||||
MatMultVec3(p2, mvp, wp2);
|
|
||||||
|
|
||||||
if (p0[3] != 0.0f && p1[3] != 0.0f && p2[3] != 0.0f)
|
|
||||||
{
|
|
||||||
int x, y, idx, tx, ty, ti;
|
|
||||||
float p[2];
|
|
||||||
float depth;
|
float depth;
|
||||||
float w0, w1, w2, dot00, dot01, dot11, dot20, dot21, denom, d0, d1, d2;
|
};
|
||||||
float v0[2], v1[2], v2[2];
|
|
||||||
float texcoord[2];
|
|
||||||
float normal[3];
|
|
||||||
float diff;
|
|
||||||
int aabbmin[2], aabbmax[2];
|
|
||||||
float c[3];
|
|
||||||
|
|
||||||
MapToRes(ctx, p0);
|
static void FillScanLine(struct Context *ctx, const struct ScrVertex *v0, const struct ScrVertex *v1)
|
||||||
MapToRes(ctx, p1);
|
{
|
||||||
MapToRes(ctx, p2);
|
int x, y, start, end, t0x, t0y, t1x, t1y, tx, ty;
|
||||||
|
float c[3], n[3], depth, *depthbuf, xdiff, depthdiff, tdiff[2], ndiff[3], diffuse;
|
||||||
|
uint8_t *texel;
|
||||||
|
|
||||||
aabbmin[0] = Max(Min3(p0[0], p1[0], p2[0]), 0.0f);
|
|
||||||
aabbmin[1] = Max(Min3(p0[1], p1[1], p2[1]), 0.0f);
|
|
||||||
aabbmax[0] = Min(Max3(p0[0], p1[0], p2[0]), ctx->width - 1);
|
|
||||||
aabbmax[1] = Min(Max3(p0[1], p1[1], p2[1]), ctx->height - 1);
|
|
||||||
|
|
||||||
for (y = aabbmin[1]; y <= aabbmax[1]; ++y)
|
start = v0->x;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
end = v1->x;
|
||||||
|
if (end > ctx->width)
|
||||||
|
end = ctx->width;
|
||||||
|
|
||||||
|
y = v0->y;
|
||||||
|
|
||||||
|
xdiff = v1->x - v0->x;
|
||||||
|
depthdiff = v1->depth - v0->depth;
|
||||||
|
tdiff[0] = v1->t[0] - v0->t[0];
|
||||||
|
tdiff[1] = v1->t[1] - v0->t[1];
|
||||||
|
|
||||||
|
ndiff[0] = v1->n[0] - v0->n[0];
|
||||||
|
ndiff[1] = v1->n[1] - v0->n[1];
|
||||||
|
ndiff[2] = v1->n[2] - v0->n[2];
|
||||||
|
|
||||||
|
|
||||||
|
for (x = start; x < end; ++x)
|
||||||
{
|
{
|
||||||
for (x = aabbmin[0]; x <= aabbmax[0]; ++x)
|
float t = ((float)x - v0->x) / xdiff;
|
||||||
{
|
depth = v0->depth + t * depthdiff;
|
||||||
p[0] = x;
|
|
||||||
p[1] = y;
|
|
||||||
|
|
||||||
if (!IsOnRight(p0, p1, p) || !IsOnRight(p1, p2, p) || !IsOnRight(p2, p0, p))
|
depthbuf = &ctx->depthbuffer[x + y * ctx->width];
|
||||||
|
if (*depthbuf < depth)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
idx = x + ctx->width * y;
|
*depthbuf = depth;
|
||||||
|
|
||||||
v0[0] = p1[0] - p0[0];
|
tx = (v0->t[0] + t * tdiff[0]) * ctx->tex_w;
|
||||||
v0[1] = p1[1] - p0[1];
|
ty = (1.0f - (v0->t[1] + t * tdiff[1])) * ctx->tex_h;
|
||||||
v1[0] = p2[0] - p0[0];
|
|
||||||
v1[1] = p2[1] - p0[1];
|
|
||||||
v2[0] = p[0] - p0[0];
|
|
||||||
v2[1] = p[1] - p0[1];
|
|
||||||
|
|
||||||
dot00 = Dot2(v0, v0);
|
if (tx < 0)
|
||||||
dot01 = Dot2(v0, v1);
|
tx = 0;
|
||||||
dot11 = Dot2(v1, v1);
|
else if (tx >= ctx->width)
|
||||||
dot20 = Dot2(v2, v0);
|
tx = ctx->width - 1;
|
||||||
dot21 = Dot2(v2, v1);
|
|
||||||
|
|
||||||
denom = dot00 * dot11 - dot01 * dot01;
|
if (ty < 0)
|
||||||
w1 = (dot11 * dot20 - dot01 * dot21) / denom;
|
ty = 0;
|
||||||
w2 = (dot00 * dot21 - dot01 * dot20) / denom;
|
else if (ty >= ctx->height)
|
||||||
w0 = 1.0f - w1 - w2;
|
ty = ctx->height - 1;
|
||||||
|
|
||||||
depth = p0[2] * w0 + p1[2] * w1 + p2[2] * w2;
|
n[0] = v0->n[0] + t * ndiff[0];
|
||||||
|
n[1] = v0->n[1] + t * ndiff[1];
|
||||||
|
n[2] = v0->n[2] + t * ndiff[2];
|
||||||
|
|
||||||
if (depth > 0.0 && ctx->depthbuffer[idx] > depth)
|
Normalize(n);
|
||||||
{
|
diffuse = Max(0.5, Dot(n, ctx->lightdir));
|
||||||
ctx->depthbuffer[idx] = depth;
|
|
||||||
idx = idx * 3;
|
|
||||||
|
|
||||||
texcoord[0] = w0 * c0[0] + w1 * c1[0] + w2 * c2[0];
|
texel = &ctx->texture[(tx + ty * ctx->tex_w) * 3];
|
||||||
texcoord[1] = w0 * c0[1] + w1 * c1[1] + w2 * c2[1];
|
c[0] = texel[0] / 255.0f * diffuse;
|
||||||
|
c[1] = texel[1] / 255.0f * diffuse;
|
||||||
normal[0] = w0 * n0[0] + w1 * n1[0] + w2 * n2[0];
|
c[2] = texel[2] / 255.0f * diffuse;
|
||||||
normal[1] = w0 * n0[1] + w1 * n1[1] + w2 * n2[1];
|
|
||||||
normal[2] = w0 * n0[2] + w1 * n1[2] + w2 * n2[2];
|
|
||||||
|
|
||||||
Normalize(normal);
|
|
||||||
diff = Max(0.5, Dot(normal, lightdir));
|
|
||||||
|
|
||||||
tx = texcoord[0] * ctx->tex_w;
|
|
||||||
ty = (1 - texcoord[1]) * ctx->tex_h;
|
|
||||||
ti = (tx + ty * ctx->tex_w) * 3;
|
|
||||||
|
|
||||||
c[0] = texture[ti] / 255.0f * diff;
|
|
||||||
c[1] = texture[ti + 1] / 255.0f * diff;
|
|
||||||
c[2] = texture[ti + 2] / 255.0f * diff;
|
|
||||||
|
|
||||||
SetPixel(ctx, x, y, c);
|
SetPixel(ctx, x, y, c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SortByY(struct ScrVertex** s)
|
||||||
|
{
|
||||||
|
struct ScrVertex* temp;
|
||||||
|
|
||||||
|
if (s[0]->y > s[1]->y)
|
||||||
|
{
|
||||||
|
temp = s[0];
|
||||||
|
s[0] = s[1];
|
||||||
|
s[1] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s[1]->y > s[2]->y)
|
||||||
|
{
|
||||||
|
temp = s[1];
|
||||||
|
s[1] = s[2];
|
||||||
|
s[2] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s[0]->y > s[1]->y)
|
||||||
|
{
|
||||||
|
temp = s[0];
|
||||||
|
s[0] = s[1];
|
||||||
|
s[1] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static void OutputPPM(FILE *file, struct Context *ctx)
|
static void DebugDrawPoint(struct Context *ctx, int x, int y)
|
||||||
// {
|
{
|
||||||
// int i, numpixels;
|
float c[] = { 1.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
// fprintf(file, "P3\n%d\n%d\n255\n", ctx->width, ctx->height);
|
if (x < 0 || x >= ctx->width || y < 0 || y >= ctx->height)
|
||||||
|
return;
|
||||||
|
|
||||||
// numpixels = ctx->width * ctx->height;
|
SetPixel(ctx, x, y, c);
|
||||||
|
}
|
||||||
|
|
||||||
// for (i = 0; i < numpixels * 3; ++i)
|
static void LerpScrVertex(const struct ScrVertex *a, const struct ScrVertex *b, struct ScrVertex *res, float t)
|
||||||
// {
|
{
|
||||||
// fprintf(file, "%d ", (int)(ctx->colorbuffer[i] * 255.0f));
|
res->x = a->x + (b->x - a->x) * t;
|
||||||
// }
|
res->y = a->y + (b->y - a->y) * t;
|
||||||
|
res->t[0] = a->t[0] + (b->t[0] - a->t[0]) * t;
|
||||||
|
res->t[1] = a->t[1] + (b->t[1] - a->t[1]) * t;
|
||||||
|
res->n[0] = a->n[0] + (b->n[0] - a->n[0]) * t;
|
||||||
|
res->n[1] = a->n[1] + (b->n[1] - a->n[1]) * t;
|
||||||
|
res->n[2] = a->n[2] + (b->n[2] - a->n[2]) * t;
|
||||||
|
res->depth = a->depth + (b->depth - a->depth) * t;
|
||||||
|
}
|
||||||
|
|
||||||
// fprintf(file, "\n");
|
static void DrawTriangle(struct Context *ctx, float wp0[], float wp1[], float wp2[], float c0[], float c1[], float c2[], float mvp[], float n0[], float n1[], float n2[])
|
||||||
// }
|
{
|
||||||
|
float p[3][4];
|
||||||
|
struct ScrVertex v[3], nv, *s[4], *tempv;
|
||||||
|
int i;
|
||||||
|
float nf;
|
||||||
|
|
||||||
// static void OutputVT100(FILE* out, const struct Context *ctx)
|
MatMultVec3(p[0], mvp, wp0);
|
||||||
// {
|
MatMultVec3(p[1], mvp, wp1);
|
||||||
// int r1, g1, b1, r2, b2, g2, x, y, idx, rowoffset;
|
MatMultVec3(p[2], mvp, wp2);
|
||||||
// fprintf(out, "\x1b[1;1H\n");
|
|
||||||
|
|
||||||
// for (y = 0; y <= ctx->height - 2; y += 2)
|
for (i = 0; i < 3; ++i)
|
||||||
// {
|
{
|
||||||
// fprintf(out, "\n");
|
if (p[i][3] == 0.0f)
|
||||||
// for (x = 0; x < ctx->width; ++x)
|
return;
|
||||||
// {
|
|
||||||
// idx = (x + y * ctx->width) * 3;
|
|
||||||
// rowoffset = ctx->width * 3;
|
|
||||||
// r1 = ctx->colorbuffer[idx] * 255;
|
|
||||||
// g1 = ctx->colorbuffer[idx + 1] * 255;
|
|
||||||
// b1 = ctx->colorbuffer[idx + 2] * 255;
|
|
||||||
// r2 = ctx->colorbuffer[idx + rowoffset] * 255;
|
|
||||||
// g2 = ctx->colorbuffer[idx + 1 + rowoffset] * 255;
|
|
||||||
// b2 = ctx->colorbuffer[idx + 2 + rowoffset] * 255;
|
|
||||||
|
|
||||||
// fprintf(out, "\x1b[38;2;%d;%d;%dm\x1b[48;2;%d;%d;%dm▀", r1, g1, b1, r2, g2, b2);
|
MapToRes(ctx, p[i]);
|
||||||
// }
|
|
||||||
// }
|
v[i].x = p[i][0];
|
||||||
// }
|
v[i].y = p[i][1];
|
||||||
|
v[i].depth = p[i][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
v[0].t[0] = c0[0];
|
||||||
|
v[0].t[1] = c0[1];
|
||||||
|
|
||||||
|
v[1].t[0] = c1[0];
|
||||||
|
v[1].t[1] = c1[1];
|
||||||
|
|
||||||
|
v[2].t[0] = c2[0];
|
||||||
|
v[2].t[1] = c2[1];
|
||||||
|
|
||||||
|
v[0].n[0] = n0[0];
|
||||||
|
v[0].n[1] = n0[1];
|
||||||
|
v[0].n[2] = n0[2];
|
||||||
|
|
||||||
|
v[1].n[0] = n1[0];
|
||||||
|
v[1].n[1] = n1[1];
|
||||||
|
v[1].n[2] = n1[2];
|
||||||
|
|
||||||
|
v[2].n[0] = n2[0];
|
||||||
|
v[2].n[1] = n2[1];
|
||||||
|
v[2].n[2] = n2[2];
|
||||||
|
|
||||||
|
if (IsOnRight(p[0], p[2], p[1]))
|
||||||
|
return; /* backface cull */
|
||||||
|
|
||||||
|
s[0] = &v[0];
|
||||||
|
s[1] = &v[1];
|
||||||
|
s[2] = &v[2];
|
||||||
|
s[3] = &nv;
|
||||||
|
SortByY(s);
|
||||||
|
|
||||||
|
nf = (s[1]->y - s[0]->y) / (s[2]->y - s[0]->y);
|
||||||
|
LerpScrVertex(s[0], s[2], &nv, nf);
|
||||||
|
nv.y = s[1]->y;
|
||||||
|
|
||||||
|
if (s[3]->x < s[1]->x)
|
||||||
|
{
|
||||||
|
tempv = s[1];
|
||||||
|
s[1] = s[3];
|
||||||
|
s[3] = tempv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (i = 0; i < 4; ++i)
|
||||||
|
// {
|
||||||
|
// DebugDrawPoint(ctx, s[i]->x, s[i]->y);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (s[0]->y != s[1]->y)
|
||||||
|
{
|
||||||
|
int start, end, sc_y;
|
||||||
|
|
||||||
|
start = s[0]->y;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
end = s[1]->y + 1;
|
||||||
|
if (end > ctx->height)
|
||||||
|
end = ctx->height;
|
||||||
|
|
||||||
|
for (sc_y = start; sc_y < end; sc_y++)
|
||||||
|
{
|
||||||
|
struct ScrVertex scv[2];
|
||||||
|
float t = ((float)sc_y - s[0]->y) / (s[1]->y - s[0]->y);
|
||||||
|
|
||||||
|
LerpScrVertex(s[0], s[1], &scv[0], t);
|
||||||
|
LerpScrVertex(s[0], s[3], &scv[1], t);
|
||||||
|
|
||||||
|
scv[0].y = sc_y;
|
||||||
|
FillScanLine(ctx, &scv[0], &scv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s[1]->y != s[2]->y)
|
||||||
|
{
|
||||||
|
int start, end, sc_y;
|
||||||
|
|
||||||
|
start = s[3]->y + 1;
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
end = s[2]->y + 1;
|
||||||
|
if (end > ctx->height)
|
||||||
|
end = ctx->height;
|
||||||
|
|
||||||
|
for (sc_y = start; sc_y < end; sc_y++)
|
||||||
|
{
|
||||||
|
struct ScrVertex scv[2];
|
||||||
|
float t = ((float)sc_y - s[3]->y) / (s[2]->y - s[3]->y);
|
||||||
|
|
||||||
|
LerpScrVertex(s[1], s[2], &scv[0], t);
|
||||||
|
LerpScrVertex(s[3], s[2], &scv[1], t);
|
||||||
|
|
||||||
|
scv[0].y = sc_y;
|
||||||
|
FillScanLine(ctx, &scv[0], &scv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void OutputVGA(const struct Context *ctx)
|
static void OutputVGA(const struct Context *ctx)
|
||||||
{
|
{
|
||||||
@ -417,16 +530,6 @@ static void OutputVGA(const struct Context *ctx)
|
|||||||
memcpy(vga, ctx->colorbuffer, 320 * 200);
|
memcpy(vga, ctx->colorbuffer, 320 * 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function DumpMat(Real Array mat)
|
|
||||||
// Declare Integer i
|
|
||||||
// For i = 0 to 15
|
|
||||||
// Output mat[i] & " "
|
|
||||||
// If i % 4 == 3
|
|
||||||
// Output ""
|
|
||||||
// End
|
|
||||||
// End
|
|
||||||
// End
|
|
||||||
|
|
||||||
static void *MyMalloc(size_t n)
|
static void *MyMalloc(size_t n)
|
||||||
{
|
{
|
||||||
void *mem = malloc(n);
|
void *mem = malloc(n);
|
||||||
@ -443,9 +546,6 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct Context ctx;
|
struct Context ctx;
|
||||||
|
|
||||||
// float bg[] = { 0.25f, 0.25f, 0.25f };
|
|
||||||
float lightdir[] = { 0.3f, 1.0f, 0.4f };
|
|
||||||
|
|
||||||
float view[16];
|
float view[16];
|
||||||
float proj[16];
|
float proj[16];
|
||||||
float mvp[16];
|
float mvp[16];
|
||||||
@ -454,7 +554,7 @@ int main(int argc, char **argv)
|
|||||||
float targetpos[] = { 0.0f, 0.0f, 0.0f };
|
float targetpos[] = { 0.0f, 0.0f, 0.0f };
|
||||||
float upvector[] = { 0.0f, 1.0f, 0.0f };
|
float upvector[] = { 0.0f, 1.0f, 0.0f };
|
||||||
|
|
||||||
float aspectratio = 1.46;
|
float aspectratio = 1.3f;
|
||||||
|
|
||||||
float p0[3], p1[3], p2[3];
|
float p0[3], p1[3], p2[3];
|
||||||
float c0[3], c1[3], c2[3];
|
float c0[3], c1[3], c2[3];
|
||||||
@ -462,7 +562,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
int datasize, i, vertices, tp;
|
int datasize, i, vertices, tp;
|
||||||
float *data;
|
float *data;
|
||||||
uint8_t *texture;
|
|
||||||
|
|
||||||
int temp, i0, i1, i2;
|
int temp, i0, i1, i2;
|
||||||
float camangle;
|
float camangle;
|
||||||
@ -470,11 +569,6 @@ int main(int argc, char **argv)
|
|||||||
FILE *in = stdin;
|
FILE *in = stdin;
|
||||||
FILE *out = stdout;
|
FILE *out = stdout;
|
||||||
|
|
||||||
// getch();
|
|
||||||
|
|
||||||
// SetMode(0x3);
|
|
||||||
// return 0;
|
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
in = fopen(argv[1], "r");
|
in = fopen(argv[1], "r");
|
||||||
@ -503,7 +597,10 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
ctx.colorbuffer = ctx.backbuffer;
|
ctx.colorbuffer = ctx.backbuffer;
|
||||||
|
|
||||||
Normalize(lightdir);
|
ctx.lightdir[0] = 0.3f;
|
||||||
|
ctx.lightdir[1] = 1.0f;
|
||||||
|
ctx.lightdir[2] = 0.4f;
|
||||||
|
Normalize(ctx.lightdir);
|
||||||
|
|
||||||
Perspective(proj, DegToRad(90.0f) / aspectratio, aspectratio, 0.1f, 50.0f);
|
Perspective(proj, DegToRad(90.0f) / aspectratio, aspectratio, 0.1f, 50.0f);
|
||||||
|
|
||||||
@ -520,13 +617,13 @@ int main(int argc, char **argv)
|
|||||||
fscanf(in, "%d\n%d\n", &ctx.tex_w, &ctx.tex_h);
|
fscanf(in, "%d\n%d\n", &ctx.tex_w, &ctx.tex_h);
|
||||||
tp = ctx.tex_w * ctx.tex_h * 3;
|
tp = ctx.tex_w * ctx.tex_h * 3;
|
||||||
|
|
||||||
texture = MyMalloc(tp);
|
ctx.texture = MyMalloc(tp);
|
||||||
|
|
||||||
for (i = 0; i < tp; ++i)
|
for (i = 0; i < tp; ++i)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
fscanf(in, "%d\n", &v);
|
fscanf(in, "%d\n", &v);
|
||||||
texture[i] = v;
|
ctx.texture[i] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "textura rdy\n");
|
fprintf(stderr, "textura rdy\n");
|
||||||
@ -592,16 +689,12 @@ int main(int argc, char **argv)
|
|||||||
n2[1] = data[i2 + 6];
|
n2[1] = data[i2 + 6];
|
||||||
n2[2] = data[i2 + 7];
|
n2[2] = data[i2 + 7];
|
||||||
|
|
||||||
DrawTriangle(&ctx, p0, p1, p2, texture, c0, c1, c2, mvp, lightdir, n0, n1, n2);
|
DrawTriangle(&ctx, p0, p1, p2, c0, c1, c2, mvp, n0, n1, n2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// OutputPPM(out, &ctx);
|
|
||||||
// OutputVT100(out, &ctx);
|
|
||||||
OutputVGA(&ctx);
|
OutputVGA(&ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user