diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.zig | 2 | ||||
| -rw-r--r-- | src/render.zig | 139 |
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; } |
