diff options
| author | tslil clingman <> | 2021-10-17 15:30:14 -0400 |
|---|---|---|
| committer | tslil clingman <> | 2021-10-17 15:30:14 -0400 |
| commit | c376543f5b2c9593bee3664b7c1cb67f8802f79c (patch) | |
| tree | f71e44bdd7e3a755d744a3e1246f6a7197062732 /src/render.zig | |
| parent | 61856ed5407a227aab35d7b800daad883c265dd9 (diff) | |
Texture scaling
Diffstat (limited to 'src/render.zig')
| -rw-r--r-- | src/render.zig | 108 |
1 files changed, 51 insertions, 57 deletions
diff --git a/src/render.zig b/src/render.zig index 27bd0cc..f81ce4f 100644 --- a/src/render.zig +++ b/src/render.zig @@ -71,7 +71,7 @@ fn fasterColourBlend(onto: Colour, from: Colour) Colour { const LocalCoordHit = struct { local_dist: f32, - frac: f32, + texture_frac: f32, }; // The primary observation is: if a line segment AB disconnects the unit square, @@ -132,11 +132,14 @@ fn hitDistLocalCoords( // indexes it along vp->v which we use for texture mapping. const denom = (rdx * vdy - vdx * rdy); const t = (vdx * (ray0_y - vp[1]) - vdy * (ray0_x - vp[0])) / denom; - const frac = crossp / denom; + const side_frac = crossp / denom; const new_distance = rdist * t; if (ret_val == null or (new_distance < ret_val.?.local_dist)) { - ret_val = LocalCoordHit{ .local_dist = new_distance, .frac = frac }; + ret_val = LocalCoordHit{ + .local_dist = new_distance, + .texture_frac = (side_frac + @intToFloat(f32, i - 1)) / @intToFloat(f32, vertices.len), + }; } } } @@ -434,10 +437,11 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { ray1_y = std.math.modf(next_distance * sinra + ppos_y).fpart; } + var previous_layer_height: f32 = 0; for (cell.lower_layers.constSlice()) |layer| { - if (hitDistLocalCoords(ray0_x, ray0_y, ray1_x, ray1_y, layer.vertices.constSlice())) |dist_frac| { + if (hitDistLocalCoords(ray0_x, ray0_y, ray1_x, ray1_y, layer.vertices.constSlice())) |hit| { // TODO: Correct for fisheye? - const adj_distance = distance + dist_frac.local_dist; + const adj_distance = distance + hit.local_dist; // project the top of the bottom and the bottom of the top top_of_floor = PlaneHeight / 2 + PlaneDist * (layer.height - pheight) / adj_distance; @@ -448,7 +452,8 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { // Are we able to see any vertical faces? if (draw_lower) { - const texstrip = @floatToInt(c_uint, constants.TextureDim * dist_frac.frac); + const tex_strip = std.math.modf(layer.vertical_texture_scale * hit.texture_frac).fpart; + const texcol = @floatToInt(c_uint, constants.TextureDim * tex_strip); // height of a unit-height wall at this distance const nominal_length = PlaneDist / adj_distance; @@ -461,7 +466,7 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { const t_lower_off = layer.vertical_texture * td; // Note the bizarre rounding we have to do to avoid artifacts const constrained_top = std.math.floor(std.math.min(top_of_floor, lowest_drawn)); - const proj_height = layer.height * nominal_length; + const proj_height = (layer.height - previous_layer_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))); @@ -475,7 +480,7 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { 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 texel = walls_image.getPixel(.{ .x = t_lower_off + texcol, .y = ty }); pixels[pix_index] = texel; self.z_buffer[pix_index] = adj_distance; @@ -483,28 +488,46 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { highest_drawn = constrained_top; } } + previous_layer_height = layer.height; + } + + // do we potentially draw horizontal surfaces? + if (highest_drawn < PlaneHeight / 2) { + // Note: next_top can never exceed PlaneHeight / 2 in + // the body of the next block. If the wall is taller + // than us the back edge is lower than the front one so + // this check will fail as we just drew it (or higher + // than it). If the wall is shorter then the back edge + // is at most the horizon. Similarly so for next_bottom + const next_top = PlaneHeight / 2 + PlaneDist * (layer.height - pheight) / next_distance; + if (false and next_top > highest_drawn) { + 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); - // if (draw_upper) { - // const proj_default_end = PlaneHeight / 2 + PlaneDist * (level.Cell.DEFAULT_HEIGHT - pheight) / adj_distance; - // 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 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, std.math.modf(texel_y).fpart * constants.TextureDim); - // const texel = walls_image.getPixel(.{ .x = t_upper_off + texstrip, .y = ty }); + 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).fpart; + const sy = std.math.modf(ppos_y + row_dist * sinra).fpart; + const px = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sx)); + const py = @floatToInt(c_uint, constants.TextureDim * std.math.fabs(sy)); + const val = surfaces_image.getPixel(.{ .x = toff + px, .y = py }); + pixels[pix_index] = val; - // pixels[pix_index] = texel; - // self.z_buffer[pix_index] = adj_distance; - // } - // lowest_drawn = constrained_bottom; - // } + // record in the z_buffer only if we're above the floor! + if (cell.floor_height > 0) self.z_buffer[pix_index] = row_dist; + } + // OVERDRAW + // highest_drawn = next_top; + } } } } @@ -520,35 +543,6 @@ pub fn Renderer(PlaneWidth: f32, PlaneHeight: f32) type { // const next_top = PlaneHeight / 2 + PlaneDist * (cell.floor_height - pheight) / next_distance; // const next_bottom = PlaneHeight / 2 + PlaneDist * (cell.ceiling_height - pheight) / next_distance; - // // draw floor? - // if (false and next_top > highest_drawn) { - // 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 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[pix_index] = val; - - // // record in the z_buffer only if we're above the floor! - // if (cell.floor_height > 0) self.z_buffer[pix_index] = row_dist; - // } - // highest_drawn = next_top; - // } - // // draw ceiling? // if (false and cell.draw_down and next_bottom < lowest_drawn) { // const toff = cell.ceiling_texture * @floatToInt(c_uint, constants.TextureDim); |
