aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.zig4
-rw-r--r--src/render.zig127
2 files changed, 70 insertions, 61 deletions
diff --git a/src/main.zig b/src/main.zig
index c3647b4..1211529 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -67,11 +67,11 @@ 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,
- .ceiling_texture = 2,
+ .ceiling_texture = 1,
.draw_down = true,
};
diff --git a/src/render.zig b/src/render.zig
index 12af775..ae9983c 100644
--- a/src/render.zig
+++ b/src/render.zig
@@ -174,28 +174,30 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
const inv_height = 1 / height;
- var tex_frac: f32 = std.math.clamp((start - left) / width, 0, 1);
+ const tex_x_step = constants.TextureDim / width;
+ const toff = obj.texture * @floatToInt(c_uint, constants.TextureDim);
+ 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)));
+ const tx = @floatToInt(c_uint, tex_x);
+ var pix_index = @floatToInt(usize, PlaneWidth) * pix_y + col;
var texel_y = (top - bottom) / height;
- while (pix_y < PlaneHeight and bottom >= top - height) : ({
+ while (pix_index < PlanePixels and bottom > thresh) : ({
bottom -= 1;
- pix_y += 1;
texel_y += inv_height;
+ 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);
+ if (self.z_buffer[pix_index] > scaled_perp_distance) {
const ty = @floatToInt(c_uint, texel_y * constants.TextureDim);
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);
}
@@ -312,7 +314,7 @@ 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;
@@ -324,16 +326,18 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
// 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);
+ 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, PlaneHeight - constrained_bottom);
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;
+ 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;
+ // and update the z-buffer. Note that it doesn't
+ // matter which way we write to the z_buffer
+ // here, walls are vertical!
+ while (pix_y < stop) : ({
pix_y += 1;
texel_y += inv_nom_len;
}) {
@@ -342,41 +346,40 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type {
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 t_upper_off = cell.upper_texture * td;
+ const constrained_top = std.math.min(lowest_drawn, proj_default_end);
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 stop = @floatToInt(i32, PlaneHeight - constrained_bottom);
+ const t_upper_off = cell.upper_texture * td;
+ var pix_y = @floatToInt(usize, std.math.ceil(std.math.max(PlaneHeight - constrained_top - 1, 0)));
+ // TODO: Decide if textures should be pinned at
+ // the top or bottom. Currently they are pinned
+ // at the top. For bottom this would read:
+ // constants.TextureDim - (constrained_top - constrained_bottom) / nominal_length
+ var texel_y: f32 = (proj_default_end - constrained_top) / nominal_length;
+ while (pix_y < stop) : ({
+ pix_y += 1;
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;
@@ -395,52 +398,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.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;
}