aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.zig2
-rw-r--r--src/render.zig139
2 files changed, 72 insertions, 69 deletions
diff --git a/src/main.zig b/src/main.zig
index c3647b4..01a021c 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -67,7 +67,7 @@ pub fn main() !void {
map.cells.items[16 * 7 + 7] = level.Cell{
.floor_height = 0.5,
- .ceiling_height = 2,
+ .ceiling_height = 2.2,
.lower_texture = 1,
.upper_texture = 1,
.floor_texture = 1,
diff --git a/src/render.zig b/src/render.zig
index 38cd26d..5879b31 100644
--- a/src/render.zig
+++ b/src/render.zig
@@ -227,30 +227,32 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
const start = std.math.max(0, left);
const end = @floatToInt(usize, std.math.min(left + width, PlaneWidth - 1));
- const inv_height = 1 / height;
+ const tex_y_step = constants.TextureDim / height;
+ const tex_x_step = constants.TextureDim / width;
+ const toff = obj.texture * @floatToInt(c_uint, constants.TextureDim);
- var tex_frac: f32 = std.math.clamp((start - left) / width, 0, 1);
+ const thresh = top - height;
+ const constrained_bottom = std.math.min(top, PlaneHeight);
+ const pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_bottom - 1, 0)));
+ var tex_x: f32 = std.math.clamp((start - left) / width, 0, 1) * constants.TextureDim;
var col: usize = @floatToInt(usize, start);
- const tex_frac_step = 1 / width;
+ var bottom: f32 = 0;
while (col < end) : ({
col += 1;
- tex_frac += tex_frac_step;
+ tex_x += tex_x_step;
+ bottom = constrained_bottom;
}) {
- var bottom = std.math.min(top, PlaneHeight);
- var pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - bottom - 1, 0)));
- var texel_y = (top - bottom) / height;
- while (pix_y < PlaneHeight and bottom >= top - height) : ({
+ const tx = @floatToInt(c_uint, tex_x);
+ var pix_index = @floatToInt(usize, PlaneWidth) * pix_y + col;
+ var texel_y = constants.TextureDim * (top - bottom) / height;
+ while (pix_index < PlanePixels and bottom > thresh) : ({
bottom -= 1;
- pix_y += 1;
- texel_y += inv_height;
+ texel_y += tex_y_step;
+ pix_index += @floatToInt(usize, PlaneWidth);
}) {
- const index = col * @floatToInt(usize, PlaneHeight) + @floatToInt(usize, bottom);
- if (self.z_buffer[index] > scaled_perp_distance) {
- const tx = @floatToInt(c_uint, tex_frac * constants.TextureDim);
- const toff = obj.texture * @floatToInt(c_uint, constants.TextureDim);
- const ty = @floatToInt(c_uint, texel_y * constants.TextureDim);
+ if (self.z_buffer[pix_index] > scaled_perp_distance) {
+ const ty = @floatToInt(c_uint, texel_y);
const texel = objects_image.getPixel(.{ .x = toff + tx, .y = ty });
- const pix_index = @floatToInt(usize, PlaneWidth) * pix_y + col;
// TODO: Decide whether being accurate is as important as being fast
pixels[pix_index] = fasterColourBlend(pixels[pix_index], texel);
}
@@ -370,71 +372,66 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
// we also want to be sure that we're consistently orienting
// textures, in this case clockwise
if ((horizontal_hit and sinra < 0) or (!horizontal_hit and cosra > 0)) texfrac = 1 - texfrac;
- const texstrip = @floatToInt(c_uint, (constants.TextureDim - 1) * texfrac);
+ const texstrip = @floatToInt(c_uint, constants.TextureDim * texfrac);
// height of a unit-height wall at this distance
const nominal_length = PlaneDist / distance;
- const inv_nom_len = distance / PlaneDist;
// used for texel indexing
+ const inv_nom_len = distance / PlaneDist;
const td = @floatToInt(c_uint, constants.TextureDim);
if (draw_lower) {
// which texture index?
const t_lower_off = cell.lower_texture * td;
// Note the bizarre rounding we have to do to avoid artifacts
- const constrained_top = std.math.min(std.math.floor(top_of_floor), std.math.ceil(lowest_drawn));
- const stop = @floatToInt(i32, highest_drawn);
- var zb_y = @floatToInt(i32, constrained_top);
- var pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_top - 1, 0)));
- var texel_y = (top_of_floor - constrained_top) / nominal_length;
+ const constrained_top = std.math.floor(std.math.min(top_of_floor, lowest_drawn));
+ const proj_height = cell.floor_height * nominal_length;
+ const constrained_bottom = std.math.max(highest_drawn, top_of_floor - proj_height);
+ const stop = @floatToInt(usize, PlaneWidth * (PlaneHeight - constrained_bottom)) + col;
+ const pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_top - 1, 0)));
+ var pix_index = pix_y * @floatToInt(usize, PlaneWidth) + col;
+ var texel_y: f32 = std.math.max((top_of_floor - constrained_top) / nominal_length, 0);
// now we have what we need to draw the face,
- // and update the z-buffer
- while (zb_y > stop) : ({
- zb_y -= 1;
- pix_y += 1;
+ // and update the z-buffer.
+ while (pix_index < stop) : ({
+ pix_index += @floatToInt(usize, PlaneWidth);
texel_y += inv_nom_len;
}) {
const ty = @floatToInt(c_uint, std.math.modf(texel_y).fpart * constants.TextureDim);
const texel = walls_image.getPixel(.{ .x = t_lower_off + texstrip, .y = ty });
- const pix_index = pix_y * @floatToInt(usize, PlaneWidth) + col;
pixels[pix_index] = texel;
-
- const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + zb_y);
- self.z_buffer[index] = distance;
+ self.z_buffer[pix_index] = distance;
}
- highest_drawn = top_of_floor;
+ highest_drawn = constrained_top;
}
if (draw_upper) {
const proj_default_end = PlaneHeight / 2 + PlaneDist * (level.Cell.DEFAULT_HEIGHT - pheight) / distance;
- const stop = @floatToInt(i32, std.math.min(lowest_drawn, proj_default_end));
+ const constrained_top = std.math.min(lowest_drawn, proj_default_end);
+ const constrained_bottom = std.math.ceil(std.math.max(bottom_of_ceiling, highest_drawn));
+ const stop = @floatToInt(usize, PlaneWidth * (PlaneHeight - constrained_bottom)) + col;
const t_upper_off = cell.upper_texture * td;
- const constrained_bottom = std.math.max(bottom_of_ceiling, highest_drawn);
- var zb_y = @floatToInt(i32, constrained_bottom);
- var pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_bottom - 1, 0)));
- var texel_y: f32 = 0;
- while (zb_y < stop) : ({
- zb_y += 1;
- pix_y -= 1;
+ const pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_top - 1, 0)));
+ var pix_index = pix_y * @floatToInt(usize, PlaneWidth) + col;
+ var texel_y: f32 = constants.TextureDim - (constrained_top - constrained_bottom) / nominal_length;
+ while (pix_index < stop) : ({
+ pix_index += @floatToInt(usize, PlaneWidth);
texel_y += inv_nom_len;
}) {
- const ty = @floatToInt(c_uint, (1 - std.math.modf(texel_y).fpart) * (constants.TextureDim - 1));
+ const ty = @floatToInt(c_uint, std.math.modf(texel_y).fpart * constants.TextureDim);
const texel = walls_image.getPixel(.{ .x = t_upper_off + texstrip, .y = ty });
- const pix_index = pix_y * @floatToInt(usize, PlaneWidth) + col;
pixels[pix_index] = texel;
-
- const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + zb_y);
- self.z_buffer[index] = distance;
+ self.z_buffer[pix_index] = distance;
}
- lowest_drawn = bottom_of_ceiling;
+ lowest_drawn = constrained_bottom;
}
}
}
- // do we potentially draw floor for this cell?
+ // do we potentially draw floor and or ceiling for this cell?
if (highest_drawn < PlaneHeight / 2 or (cell.draw_down and lowest_drawn > PlaneHeight / 2)) {
if (dist_y < dist_x) {
distance = dist_y;
@@ -453,52 +450,58 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
// draw floor?
if (next_top > highest_drawn) {
- top_of_floor = std.math.ceil(highest_drawn);
- const thresh = std.math.min(std.math.min(next_top, lowest_drawn), PlaneHeight / 2 - 1);
- while (top_of_floor < thresh) : (top_of_floor += 1) {
- const row_dist = (pheight - cell.floor_height) * PlaneDist / (PlaneHeight / 2 - top_of_floor);
- const ptop = @floatToInt(usize, top_of_floor);
- const itop = @floatToInt(usize, PlaneHeight) - ptop - 1;
+ const toff = cell.floor_texture * @floatToInt(c_uint, constants.TextureDim);
+
+ top_of_floor = std.math.ceil(std.math.min(std.math.min(next_top, lowest_drawn), PlaneHeight / 2 - 1));
+ const thresh = std.math.ceil(highest_drawn);
+ const itop = @floatToInt(usize, std.math.max(top_of_floor, 0));
+ const ptop = @floatToInt(usize, PlaneHeight) - itop - 1;
+ var pix_index = ptop * @floatToInt(usize, PlaneWidth) + col;
+ while (top_of_floor > thresh) : ({
+ top_of_floor -= 1;
+ pix_index += @floatToInt(usize, PlaneWidth);
+ }) {
+ const row_dist = (pheight - cell.floor_height) * PlaneDist / (PlaneHeight / 2 - top_of_floor);
// draw the correct pixel
const sx = std.math.modf(ppos_x + row_dist * cosra);
const sy = std.math.modf(ppos_y + row_dist * sinra);
- const toff = cell.floor_texture * @floatToInt(c_uint, constants.TextureDim);
const px = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sx.fpart));
const py = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sy.fpart));
const val = surfaces_image.getPixel(.{ .x = toff + px, .y = py });
- pixels[itop * @floatToInt(usize, PlaneWidth) + col] = val;
+ pixels[pix_index] = val;
// record in the z_buffer only if we're above the floor!
- if (cell.floor_height > 0) {
- const index = col * @floatToInt(usize, PlaneHeight) + ptop;
- self.z_buffer[index] = row_dist;
- }
+ if (cell.floor_height > 0) self.z_buffer[pix_index] = row_dist;
}
highest_drawn = next_top;
}
// draw ceiling?
if (cell.draw_down and next_bottom < lowest_drawn) {
+ const toff = cell.ceiling_texture * @floatToInt(c_uint, constants.TextureDim);
+
bottom_of_ceiling = std.math.ceil(lowest_drawn);
const thresh = std.math.max(std.math.max(next_bottom, highest_drawn), PlaneHeight / 2 - 1);
- while (bottom_of_ceiling > thresh) : (bottom_of_ceiling -= 1) {
+
+ const itop = @floatToInt(usize, bottom_of_ceiling);
+ const ptop = @floatToInt(usize, PlaneHeight) - itop - 1;
+ var pix_index = ptop * @floatToInt(usize, PlaneWidth) + col;
+
+ while (bottom_of_ceiling > thresh) : ({
+ bottom_of_ceiling -= 1;
+ pix_index += @floatToInt(usize, PlaneWidth);
+ }) {
const row_dist = (cell.ceiling_height - pheight) * PlaneDist / (bottom_of_ceiling - PlaneHeight / 2);
- const ptop = @floatToInt(usize, bottom_of_ceiling);
- const itop = @floatToInt(usize, PlaneHeight) - ptop;
const sx = std.math.modf(ppos_x + row_dist * cosra);
const sy = std.math.modf(ppos_y + row_dist * sinra);
- const toff = cell.ceiling_texture * @floatToInt(c_uint, constants.TextureDim);
const px = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sx.fpart));
const py = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sy.fpart));
const val = surfaces_image.getPixel(.{ .x = toff + px, .y = py });
- pixels[itop * @floatToInt(usize, PlaneWidth) + col] = val;
+ pixels[pix_index] = val;
- if (cell.draw_down) {
- const index = col * @floatToInt(usize, PlaneHeight) + ptop;
- self.z_buffer[index] = row_dist;
- }
+ if (cell.draw_down) self.z_buffer[pix_index] = row_dist;
}
lowest_drawn = next_bottom;
}