// ------------------------------------------------------------------------------------- // Render a texture map. // Linear in outer loop, linear in inner loop. // ------------------------------------------------------------------------------------- void texture_map_flat(g3ds_tmap *t, int color) { int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom int topy,boty,y, dy; fix dx_dy_left,dx_dy_right; int max_y_vertex; fix xleft,xright; fix recip_dy; g3ds_vertex *v3d; v3d = t->verts; tmap_flat_color = color; // Determine top and bottom y coords. compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex); // Set top and bottom (of entire texture map) y coordinates. topy = f2i(v3d[vlt].y2d); boty = f2i(v3d[max_y_vertex].y2d); // Set amount to change x coordinate for each advance to next scanline. dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy); dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy); // Set initial values for x, u, v xleft = v3d[vlt].x2d; xright = v3d[vrt].x2d; // scan all rows in texture map from top through first break. // @mk: Should we render the scanline for y==boty? This violates Matt's spec. for (y = topy; y < boty; y++) { // See if we have reached the end of the current left edge, and if so, set // new values for dx_dy and x,u,v if (y == f2i(v3d[vlb].y2d)) { // Handle problem of double points. Search until y coord is different. Cannot get // hung in an infinite loop because we know there is a vertex with a lower y coordinate // because in the for loop, we don't scan all spanlines. while (y == f2i(v3d[vlb].y2d)) { vlt = vlb; vlb = prevmod(vlb,t->nv); } dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy); xleft = v3d[vlt].x2d; } // See if we have reached the end of the current left edge, and if so, set // new values for dx_dy and x. Not necessary to set new values for u,v. if (y == f2i(v3d[vrb].y2d)) { while (y == f2i(v3d[vrb].y2d)) { vrt = vrb; vrb = succmod(vrb,t->nv); } dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy); xright = v3d[vrt].x2d; } //tmap_scanline_flat(y, xleft, xright); (*scanline_func)(y, xleft, xright); xleft += dx_dy_left; xright += dx_dy_right; } //tmap_scanline_flat(y, xleft, xright); (*scanline_func)(y, xleft, xright); }
// ------------------------------------------------------------------------------------- // Render a texture map with lighting using perspective interpolation in inner and outer loops. // ------------------------------------------------------------------------------------- void ntexture_map_lighted_linear(grs_bitmap *srcb, g3ds_tmap *t) { int vlt,vrt,vlb,vrb; // vertex left top, vertex right top, vertex left bottom, vertex right bottom int topy,boty,y, dy; fix dx_dy_left,dx_dy_right; fix du_dy_left,du_dy_right; fix dv_dy_left,dv_dy_right; fix dl_dy_left,dl_dy_right; int max_y_vertex; fix xleft,xright,uleft,vleft,uright,vright,lleft,lright; int next_break_left, next_break_right; fix recip_dyl, recip_dyr; g3ds_vertex *v3d; //remove stupid warnings in compile dl_dy_left = F1_0; dl_dy_right = F1_0; lleft = F1_0; lright = F1_0; v3d = t->verts; // Determine top and bottom y coords. compute_y_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_y_vertex); // Set top and bottom (of entire texture map) y coordinates. topy = f2i(v3d[vlt].y2d); boty = f2i(v3d[max_y_vertex].y2d); if (topy > Window_clip_bot) return; if (boty > Window_clip_bot) boty = Window_clip_bot; dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dyl = fix_recip[dy]; else recip_dyl = F1_0/dy; dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dyr = fix_recip[dy]; else recip_dyr = F1_0/dy; // Set amount to change x coordinate for each advance to next scanline. dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dyl); dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dyr); du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dyl); du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dyr); dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dyl); dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dyr); if (Lighting_enabled) { dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dyl); dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dyr); lleft = v3d[vlt].l; lright = v3d[vrt].l; } // Set initial values for x, u, v xleft = v3d[vlt].x2d; xright = v3d[vrt].x2d; uleft = v3d[vlt].u; uright = v3d[vrt].u; vleft = v3d[vlt].v; vright = v3d[vrt].v; // scan all rows in texture map from top through first break. next_break_left = f2i(v3d[vlb].y2d); next_break_right = f2i(v3d[vrb].y2d); for (y = topy; y < boty; y++) { // See if we have reached the end of the current left edge, and if so, set // new values for dx_dy and x,u,v if (y == next_break_left) { fix recip_dy; // Handle problem of double points. Search until y coord is different. Cannot get // hung in an infinite loop because we know there is a vertex with a lower y coordinate // because in the for loop, we don't scan all spanlines. while (y == f2i(v3d[vlb].y2d)) { vlt = vlb; vlb = prevmod(vlb,t->nv); } next_break_left = f2i(v3d[vlb].y2d); dy = f2i(t->verts[vlb].y2d) - f2i(t->verts[vlt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy); xleft = v3d[vlt].x2d; uleft = v3d[vlt].u; vleft = v3d[vlt].v; lleft = v3d[vlt].l; du_dy_left = compute_du_dy_lin(t,vlt,vlb, recip_dy); dv_dy_left = compute_dv_dy_lin(t,vlt,vlb, recip_dy); if (Lighting_enabled) { dl_dy_left = compute_dl_dy_lin(t,vlt,vlb, recip_dy); lleft = v3d[vlt].l; } } // See if we have reached the end of the current left edge, and if so, set // new values for dx_dy and x. Not necessary to set new values for u,v. if (y == next_break_right) { fix recip_dy; while (y == f2i(v3d[vrb].y2d)) { vrt = vrb; vrb = succmod(vrb,t->nv); } dy = f2i(t->verts[vrb].y2d) - f2i(t->verts[vrt].y2d); if (dy < FIX_RECIP_TABLE_SIZE) recip_dy = fix_recip[dy]; else recip_dy = F1_0/dy; next_break_right = f2i(v3d[vrb].y2d); dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy); xright = v3d[vrt].x2d; uright = v3d[vrt].u; vright = v3d[vrt].v; du_dy_right = compute_du_dy_lin(t,vrt,vrb, recip_dy); dv_dy_right = compute_dv_dy_lin(t,vrt,vrb, recip_dy); if (Lighting_enabled) { dl_dy_right = compute_dl_dy_lin(t,vrt,vrb, recip_dy); lright = v3d[vrt].l; } } if (Lighting_enabled) { ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright); lleft += dl_dy_left; lright += dl_dy_right; } else ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright); uleft += du_dy_left; vleft += dv_dy_left; uright += du_dy_right; vright += dv_dy_right; xleft += dx_dy_left; xright += dx_dy_right; } // We can get lleft or lright out of bounds here because we compute dl_dy using fixed point values, // but we plot an integer number of scanlines, therefore doing an integer number of additions of the delta. ntmap_scanline_lighted_linear(srcb,y,xleft,xright,uleft,uright,vleft,vright,lleft,lright); }