aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortslil clingman <>2021-09-03 21:09:07 -0400
committertslil clingman <>2021-09-04 11:36:32 -0400
commite4baa0810748bd3de93d1eaf216288ad67a86295 (patch)
tree7f1117a7dd5299cffbeb98a3bfea28073c7d83a2 /src
parentde255063b234871021da004d32964e25d549d3e4 (diff)
Working on floor casting, but it's not quite right
The way floors are currently rendered the textures will always appear ``under'' the walls. This is not intended for shorter walls, the floor should be atop them. I might be able to fix this by switching to vertical scan-line rendering of floors -- although i understand that that is less efficient -- and doing this at the same time as wall rendering.
Diffstat (limited to 'src')
-rw-r--r--src/main.zig105
-rw-r--r--src/raycast.zig323
-rw-r--r--src/renderConstants.zig17
3 files changed, 265 insertions, 180 deletions
diff --git a/src/main.zig b/src/main.zig
index aef559f..2d12975 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -39,21 +39,19 @@ fn renderWall(
texfrac: f32, // how far along the texture
texture: u8, // which texture index
) void {
- const hFact = screenWidth / planeWidth;
- const vFact = screenHeight / planeHeight;
// we need ceil here so that we draw always to or past the edge of the screen
- const draw_height = @floatToInt(c_int, std.math.ceil(draw_frac * wallTextureDim));
- const total_length = total_height * vFact;
+ const draw_height = @floatToInt(c_int, std.math.ceil(draw_frac * TextureDim));
+ const total_length = total_height * VFact;
- const xpos = @intToFloat(f32, col) * hFact;
- const ypos = (screenHeight + vFact * planeHeight) / 2 - top * vFact;
+ const xpos = @intToFloat(f32, col) * HFact;
+ const ypos = ScreenHeight / 2 + (PlaneHeight / 2 - top) * VFact;
- const tind = @as(c_int, texture) * @floatToInt(c_int, 1 + wallTextureDim);
- const left = tind + @floatToInt(c_int, texfrac * wallTextureDim);
+ const tind = @as(c_int, texture) * @floatToInt(c_int, 1 + TextureDim);
+ const left = tind + @floatToInt(c_int, texfrac * TextureDim);
sprite.setPosition(.{ .x = xpos, .y = ypos });
- sprite.setScale(.{ .x = hFact, .y = total_length / wallTextureDim });
+ sprite.setScale(.{ .x = HFact, .y = total_length / TextureDim });
sprite.setTextureRect(.{ .top = 0, .left = left, .width = 1, .height = draw_height });
window.draw(sprite, null);
}
@@ -64,9 +62,11 @@ pub fn main() !void {
// Setup player and map
//--------------------------------------------------------------------------
- var player = Player.new(15.75, 1.5, // pos
- PI / 2.0, // ang
- @intToFloat(f32, planeWidth), @intToFloat(f32, planeHeight));
+ var player = try Player(PlaneWidth, PlaneHeight).new(
+ 15, // x coord
+ 1.5, // y coord
+ PI / 2.0, // angle
+ );
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
@@ -83,45 +83,53 @@ pub fn main() !void {
}
map.cells.items[y * 15 + 15] = Cell{ .height = MAX_HEIGHT, .wall_texture = 1 };
- map.cells.items[y * 15 + 14] = Cell{ .height = MAX_HEIGHT / 1.5, .wall_texture = 1 };
+ map.cells.items[y * 15 + 14] = Cell{ .height = MAX_HEIGHT / 3, .wall_texture = 1, .floor_texture = 1 };
// Initialise SFML
//--------------------------------------------------------------------------
- var window = try sf.RenderWindow.create(.{ .x = screenWidth, .y = screenHeight }, 32, "zirc", sf.window.Style.none);
+ var window = try sf.RenderWindow.create(.{ .x = ScreenWidth, .y = ScreenHeight }, 32, "zirc", sf.window.Style.none);
defer window.destroy();
- window.setFramerateLimit(30);
-
- var backRect = try sf.RectangleShape.create(.{ .x = screenWidth, .y = screenHeight / 2 });
- defer backRect.destroy();
-
- backRect.setPosition(.{ .x = 0, .y = screenHeight / 2 });
- backRect.setFillColor(sf.Color.fromRGB(50, 50, 50));
+ window.setFramerateLimit(60);
// Load the background skybox, really `skycylinder', and assign it to a
// sprite -- it's set to repeating so that it goes on forever. We need to
- // scale the sprite so that drawing 1/4 of backTextureWidth fills the screen
- // horizontally, and drawing backTextureHeight fills half of the screen
+ // scale the sprite so that drawing 1/4 of backTextureWidth fills the Screen
+ // horizontally, and drawing backTextureHeight fills half of the Screen
// vertically.
- var backTexture = try sf.Texture.createFromFile("back.png");
- defer backTexture.destroy();
+ var back_texture = try sf.Texture.createFromFile("back.png");
+ defer back_texture.destroy();
+
+ back_texture.setSmooth(false); // looks worse => better!
+ back_texture.setRepeated(true);
+
+ var back_sprite = try sf.Sprite.createFromTexture(back_texture);
+ defer back_sprite.destroy();
- backTexture.setSmooth(false); // looks worse => better!
- backTexture.setRepeated(true);
+ back_sprite.setScale(.{ .x = 4.0 * ScreenWidth / BackTextureWidth, .y = ScreenHeight / (2 * BackTextureHeight) });
- var backSprite = try sf.Sprite.createFromTexture(backTexture);
- defer backSprite.destroy();
+ // Load wall textures
+ var wall_textures = try sf.Texture.createFromFile("walls.png");
+ defer wall_textures.destroy();
+ wall_textures.setSmooth(false); // looks worse => better!
- backSprite.setScale(.{ .x = 4.0 * screenWidth / backTextureWidth, .y = screenHeight / (2 * backTextureHeight) });
+ var walls_sprite = try sf.Sprite.createFromTexture(wall_textures);
+ defer walls_sprite.destroy();
- // Load brick texture!
- var wallTexture = try sf.Texture.createFromFile("walls.png");
- defer wallTexture.destroy();
- wallTexture.setSmooth(false); // looks worse => better!
+ // Load floor textures
+ var floors_image = try sf.Image.createFromFile("floors.png");
+ defer floors_image.destroy();
- var wallSprite = try sf.Sprite.createFromTexture(wallTexture);
- defer wallSprite.destroy();
+ var rendered_floors_texture = try sf.Texture.create(.{ .x = PlaneWidth, .y = PlaneHeight / 2 });
+ defer rendered_floors_texture.destroy();
+ rendered_floors_texture.setSmooth(false);
+
+ var rendered_floors_sprite = try sf.Sprite.createFromTexture(rendered_floors_texture);
+ defer rendered_floors_sprite.destroy();
+
+ rendered_floors_sprite.setPosition(.{ .x = 0, .y = ScreenHeight / 2 });
+ rendered_floors_sprite.setScale(.{ .x = HFact, .y = VFact });
// Start your engines!
//--------------------------------------------------------------------------
@@ -133,6 +141,9 @@ pub fn main() !void {
if (isKeyPressed(.Escape)) window.close();
+ if (isKeyPressed(.C)) player.height -= 0.1;
+ if (isKeyPressed(.V)) player.height += 0.1;
+
const rotation = 2.0 * PI / 100.0;
if (isKeyPressed(.R)) player.ang += rotation;
if (isKeyPressed(.T)) player.ang -= rotation;
@@ -159,18 +170,24 @@ pub fn main() !void {
window.clear(sf.Color.fromRGB(100, 100, 100));
- const back_scroll = @floatToInt(i32, -backTextureWidth * player.ang / (2 * PI));
- backSprite.setTextureRect(sf.IntRect{
+ // First the background
+ const back_scroll = @floatToInt(i32, -BackTextureWidth * player.ang / (2 * PI));
+ back_sprite.setTextureRect(sf.IntRect{
.left = back_scroll, // fix location of texture in the sky
.top = 0,
- // scaling ensures that the next two paint it across the width of
- // the screen, and for half the height of the screen
- .width = backTextureWidth / 4.0, // 1/4 of texture per screen
- .height = backTextureHeight, // full height of texture visible
+ // scaling ensures that the next two dimensions paint it across the
+ // width of the Screen, and for half the height of the screen
+ .width = BackTextureWidth / 4.0, // 1/4 of texture per screen
+ .height = BackTextureHeight, // full height of texture visible
});
- window.draw(backSprite, null);
+ window.draw(back_sprite, null);
+
+ // Then render the walls
+ try player.renderFloorsToTexture(floors_image, rendered_floors_texture, map);
+ window.draw(rendered_floors_sprite, null);
- player.renderMapUsing(window, wallSprite, map, renderWall);
+ // Finally the world
+ player.renderWorld(window, walls_sprite, map, renderWall);
window.display();
diff --git a/src/raycast.zig b/src/raycast.zig
index 608bb10..aca7db0 100644
--- a/src/raycast.zig
+++ b/src/raycast.zig
@@ -19,8 +19,12 @@ const std = @import("std");
const RenderWindow = @import("sfml").graphics.RenderWindow;
const Sprite = @import("sfml").graphics.Sprite;
+const Texture = @import("sfml").graphics.Texture;
+const Image = @import("sfml").graphics.Image;
+const Colour = @import("sfml").graphics.Color;
usingnamespace @import("map.zig");
+usingnamespace @import("renderConstants.zig");
pub const RenderWallFunction: type = fn (
window: RenderWindow,
@@ -33,165 +37,226 @@ pub const RenderWallFunction: type = fn (
texture: u8, // which texture index
) void;
-pub const Player = struct {
- pos_x: f32,
- pos_y: f32,
- ang: f32,
- vel_x: f32 = 0,
- vel_y: f32 = 0,
- acc_x: f32 = 0,
- acc_y: f32 = 0,
- fov: f32 = std.math.pi / 3.0,
- height: f32 = 1.7, // TODO
+pub fn Player(PlaneWidth: f32, PlaneHeight: f32) type {
+ return struct {
+ pos_x: f32,
+ pos_y: f32,
+ ang: f32,
+ vel_x: f32 = 0,
+ vel_y: f32 = 0,
+ acc_x: f32 = 0,
+ acc_y: f32 = 0,
+ fov: f32 = std.math.pi / 3.0,
+ height: f32 = 1.8, // TODO
+ // z_buffer: std.BoundedArray(f32, PlaneWidth * PlaneHeight),
- plane_height: f32,
- plane_width: i32,
- plane_dist: f32,
+ const FOV: f32 = std.math.pi / 3.0;
+ const PlanePixels = PlaneWidth * PlaneHeight;
+ // given the desired width of the image, how far away must
+ // the projection plane be from the camera?
+ const PlaneDist = PlaneWidth / (2 * std.math.tan(FOV / 2));
- pub fn new(pos_x: f32, pos_y: f32, ang: f32, plane_width: i32, plane_height: i32) Player {
- const fov: f32 = std.math.pi / 3.0;
- return Player{
- // standing still at the given location, looking in direction ang,
- .pos_x = pos_x,
- .pos_y = pos_y,
- .ang = ang,
- // plane of projection
- .plane_width = plane_width,
- .plane_height = @intToFloat(f32, plane_height),
- // given the desired width of the image, how far away must
- // the projection plane be from the camera?
- .plane_dist = @intToFloat(f32, plane_width) / (2 * std.math.tan(fov / 2)),
- };
- }
+ // standing still at the given location, looking in direction ang,
+ pub fn new(pos_x: f32, pos_y: f32, ang: f32) !@This() {
+ // const infs = [_]f32{std.math.inf(f32)} ** PlanePixels;
+ return Player(PlaneWidth, PlaneHeight){
+ .pos_x = pos_x,
+ .pos_y = pos_y,
+ .ang = ang,
+ // TODO: is there some clever way to avoid this long name?
+ // .z_buffer = try std.BoundedArray(f32, PlanePixels).fromSlice(&infs),
+ };
+ }
- pub fn tick(self: *Player) void {
- const dt = 1 / 30.0;
- const v_min = 0.8;
- const v_decay = 1.25;
+ pub fn tick(self: *@This()) void {
+ const dt = 1 / 30.0;
+ const v_min = 0.8;
+ const v_decay = 1.25;
- self.pos_x += self.vel_x * dt;
- self.pos_y += self.vel_y * dt;
+ self.pos_x += self.vel_x * dt;
+ self.pos_y += self.vel_y * dt;
- self.vel_x /= v_decay;
- if (std.math.fabs(self.vel_x) < v_min) self.vel_x = 0;
- self.vel_y /= v_decay;
- if (std.math.fabs(self.vel_y) < v_min) self.vel_y = 0;
+ self.vel_x /= v_decay;
+ if (std.math.fabs(self.vel_x) < v_min) self.vel_x = 0;
+ self.vel_y /= v_decay;
+ if (std.math.fabs(self.vel_y) < v_min) self.vel_y = 0;
- self.vel_x += self.acc_x * dt;
- self.vel_y += self.acc_y * dt;
- }
+ self.vel_x += self.acc_x * dt;
+ self.vel_y += self.acc_y * dt;
+ }
- pub fn renderMapUsing(
- self: Player,
- window: RenderWindow,
- wallSprite: Sprite,
- map: Map,
- // the abstract the rendering call
- renderWall: RenderWallFunction,
- ) void {
- self.renderWalls(window, wallSprite, map, renderWall);
- }
+ pub fn renderWorld(
+ self: *@This(),
+ window: RenderWindow,
+ walls_sprite: Sprite,
+ map: Map,
+ // the abstract the rendering call
+ renderWall: RenderWallFunction,
+ ) void {
+ // var i: usize = 0;
+ // while (i < self.z_buffer.len) : (i += 1) {
+ // self.z_buffer.set(i, std.math.inf(f32));
+ // }
+ self.renderWalls(window, walls_sprite, map, renderWall);
+ }
- fn renderWalls(self: Player, window: RenderWindow, wallSprite: Sprite, map: Map, renderWall: RenderWallFunction) void {
- const floor = std.math.floor;
+ fn renderWalls(
+ self: *@This(),
+ window: RenderWindow,
+ walls_sprite: Sprite,
+ map: Map,
+ renderWall: RenderWallFunction,
+ ) void {
+ const floor = std.math.floor;
- var col: i32 = 0;
- while (col < self.plane_width) : (col += 1) {
- const horiz_frac = @intToFloat(f32, col) / (@intToFloat(f32, self.plane_width) - 1);
+ var col: i32 = 0;
+ var ra: f32 = 0.5 * FOV + self.ang;
+ const ra_step = FOV / PlaneWidth;
+ while (col < PlaneWidth) : ({
+ col += 1;
+ ra -= ra_step;
+ }) {
+ const cosra = std.math.cos(ra);
+ const sinra = std.math.sin(ra);
- const ra = (0.5 - horiz_frac) * self.fov + self.ang;
+ // Observe that sqrt(1+tan^2) = abs(1/cos) sqrt(cos^2+sin^2) =
+ // abs(1/cos). Similarly so for cot, hence we obtain the following
+ // lengths for the hypotenuses assuming that x (respectively y) are
+ // unit length and the angle is ra.
+ const dy_for_x_step = std.math.fabs(1 / cosra);
+ const dx_for_y_step = std.math.fabs(1 / sinra);
- const cosra = std.math.cos(ra);
- const sinra = std.math.sin(ra);
+ var step_x: i32 = -1;
+ var step_y: i32 = -1;
- // Observe that sqrt(1+tan^2) = abs(1/cos) sqrt(cos^2+sin^2) =
- // abs(1/cos). Similarly so for cot, hence we obtain the following
- // lengths for the hypotenuses assuming that x (respectively y) are
- // unit length and the angle is ra.
- const dy_for_x_step = std.math.fabs(1 / cosra);
- const dx_for_y_step = std.math.fabs(1 / sinra);
+ var dist_x: f32 = undefined;
+ var dist_y: f32 = undefined;
- var step_x: i32 = -1;
- var step_y: i32 = -1;
+ var ipos_x: i32 = @floatToInt(i32, floor(self.pos_x));
+ var ipos_y: i32 = @floatToInt(i32, floor(self.pos_y));
- var dist_x: f32 = undefined;
- var dist_y: f32 = undefined;
+ // looking right
+ if (cosra >= 0) {
+ step_x = 1;
+ // assuming unit size grid cells
+ dist_y = (@intToFloat(f32, ipos_x) + 1 - self.pos_x) * dy_for_x_step;
+ } else {
+ dist_y = (self.pos_x - @intToFloat(f32, ipos_x)) * dy_for_x_step;
+ }
- var ipos_x: i32 = @floatToInt(i32, floor(self.pos_x));
- var ipos_y: i32 = @floatToInt(i32, floor(self.pos_y));
+ if (sinra >= 0) {
+ step_y = 1;
+ dist_x = (@intToFloat(f32, ipos_y) + 1 - self.pos_y) * dx_for_y_step;
+ } else {
+ dist_x = (self.pos_y - @intToFloat(f32, ipos_y)) * dx_for_y_step;
+ }
- // looking right
- if (cosra >= 0) {
- step_x = 1;
- // assuming unit size grid cells
- dist_y = (@intToFloat(f32, ipos_x) + 1 - self.pos_x) * dy_for_x_step;
- } else {
- dist_y = (self.pos_x - @intToFloat(f32, ipos_x)) * dy_for_x_step;
- }
+ var distance: f32 = 0;
+ var still_drawing = true;
+ var highest_point: f32 = 0;
+ var horizontal_hit: bool = undefined;
+ while (still_drawing and map.inBounds(ipos_x, ipos_y)) : ({
+ // Find the next cell on our path
+ if (dist_y < dist_x) {
+ horizontal_hit = false;
+ distance = dist_y;
+ dist_y += dy_for_x_step;
+ ipos_x += step_x;
+ } else {
+ horizontal_hit = true;
+ distance = dist_x;
+ dist_x += dx_for_y_step;
+ ipos_y += step_y;
+ }
+ }) {
+ var cell = map.lookup(ipos_x, ipos_y);
- if (sinra >= 0) {
- step_y = 1;
- dist_x = (@intToFloat(f32, ipos_y) + 1 - self.pos_y) * dx_for_y_step;
- } else {
- dist_x = (self.pos_y - @intToFloat(f32, ipos_y)) * dx_for_y_step;
- }
+ // the correct distance is the shortest distance from the plane
+ // of projection to the point, that is, perpendicular distance
+ const perp_distance = distance * std.math.cos(self.ang - ra);
- var distance: f32 = 0;
- var still_drawing = true;
- var highest_point: f32 = 0;
- var horizontal_hit: bool = undefined;
- while (still_drawing) {
+ // project the top of the wall
+ const top = PlaneHeight / 2 + PlaneDist * (cell.height - self.height) / perp_distance;
- // Find the next cell on our path
- if (dist_y < dist_x) {
- horizontal_hit = false;
- distance = dist_y;
- dist_y += dy_for_x_step;
- ipos_x += step_x;
- } else {
- horizontal_hit = true;
- distance = dist_x;
- dist_x += dx_for_y_step;
- ipos_y += step_y;
- }
+ // We have a wall to draw if it protrudes above what we have so far drawn
+ if (top > highest_point) {
+
+ // did we extend beyond the top of the plane?
+ if (top > PlaneHeight) still_drawing = false;
+
+ // compute the height of this wall
+ const total_length = PlaneDist * cell.height / perp_distance;
+
+ // as well as the fraction we'll be drawing
+ const draw_length = top - highest_point;
+ const draw_frac = std.math.clamp(draw_length / total_length, 0, 1);
+
+ // we need the raw Euclidean distance to calculate the
+ // fractional part of the relevant coordinate for texture
+ // mapping of the walls
+ const hit_coordinate = if (horizontal_hit) distance * cosra + self.pos_x else distance * sinra + self.pos_y;
+ var texfrac = std.math.modf(hit_coordinate).fpart;
+ // 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;
- if (!map.inBounds(ipos_x, ipos_y)) break;
+ // draw the wall
+ renderWall(window, walls_sprite, col, top, total_length, draw_frac, texfrac, cell.wall_texture);
- var cell = map.lookup(ipos_x, ipos_y);
+ // record that there's a wall here in the z_buffer
+ // var y = @floatToInt(i32, top);
+ // while (y > @floatToInt(i32, highest_point)) : (y -= 1) {
+ // const index = @intCast(usize, col * @floatToInt(i32, PlaneHeight) + y);
+ // self.z_buffer.set(index, perp_distance);
+ // }
- // the correct distance is the shortest distance from the plane
- // of projection to the point, that is, perpendicular distance
- const perp_distance = distance * std.math.cos(self.ang - ra);
+ highest_point = top;
+ }
+ }
+ }
+ }
- // project the top of the wall
- const top = self.plane_height / 2 + self.plane_dist * (cell.height - self.height) / perp_distance;
+ pub fn renderFloorsToTexture(self: @This(), floors_image: Image, rendered_floors_texture: Texture, map: Map) !void {
+ var pixels = [_]Colour{Colour.Black} ** (PlaneWidth * PlaneHeight / 2);
- // We have a wall to draw if it protrudes above what we have so far drawn
- if (top > highest_point) {
+ const ang_step = FOV / PlaneWidth;
+ var row: usize = 0;
+ while (row < PlaneHeight / 2) : (row += 1) {
+ const row_dist = self.height * PlaneDist / @intToFloat(f32, row + 1);
- // did we extend beyond the top of the plane?
- if (top > self.plane_height) still_drawing = false;
+ var col: usize = 0;
+ var ang = 0.5 * FOV + self.ang;
+ var ang_diff: f32 = 0.5 * FOV;
- // compute the height of this wall
- const total_length = self.plane_dist * cell.height / perp_distance;
+ while (col < PlaneWidth) : ({
+ col += 1;
+ ang -= ang_step;
+ ang_diff -= ang_step;
+ }) {
+ const perp_dist = row_dist / std.math.cos(ang_diff);
+ const x = self.pos_x + perp_dist * std.math.cos(ang);
+ const y = self.pos_y + perp_dist * std.math.sin(ang);
- // as well as the fraction we'll be drawing
- const draw_frac = std.math.min(1, (top - highest_point) / total_length);
+ const sx = std.math.modf(x);
+ const sy = std.math.modf(y);
- // we need the raw Euclidean distance to calculate the
- // fractional part of the relevant coordinate for texture
- // mapping of the walls
- const hit_coordinate = if (horizontal_hit) distance * cosra + self.pos_x else distance * sinra + self.pos_y;
- var texfrac = std.math.modf(hit_coordinate).fpart;
- // 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 ix = @floatToInt(i32, sx.ipart);
+ const iy = @floatToInt(i32, sy.ipart);
- renderWall(window, wallSprite, col, top, total_length, draw_frac, texfrac, cell.wall_texture);
+ if (map.inBounds(ix, iy)) {
+ const tex = @as(c_uint, map.lookup(ix, iy).floor_texture);
+ const toff = tex * @floatToInt(c_uint, 1 + TextureDim);
+ const px = @floatToInt(c_uint, TextureDim * std.math.fabs(sx.fpart));
+ const py = @floatToInt(c_uint, TextureDim * std.math.fabs(sy.fpart));
- highest_point = top;
+ const val = floors_image.getPixel(.{ .x = toff + px, .y = py });
+
+ pixels[row * @floatToInt(usize, PlaneWidth) + col] = val;
+ }
}
}
+
+ try rendered_floors_texture.updateFromPixels(&pixels, null);
}
- }
-};
+ };
+}
diff --git a/src/renderConstants.zig b/src/renderConstants.zig
index 2dbadee..7c193a7 100644
--- a/src/renderConstants.zig
+++ b/src/renderConstants.zig
@@ -14,13 +14,16 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
-pub const screenWidth: f32 = 1024;
-pub const screenHeight: f32 = 768;
+pub const ScreenWidth: f32 = 1024;
+pub const ScreenHeight: f32 = 768;
-pub const planeWidth = 320;
-pub const planeHeight = 240;
+pub const PlaneWidth = 320;
+pub const PlaneHeight = 240;
-pub const backTextureWidth: f32 = 1280;
-pub const backTextureHeight: f32 = 240;
+pub const HFact = ScreenWidth / PlaneWidth;
+pub const VFact = ScreenHeight / PlaneHeight;
-pub const wallTextureDim: f32 = 32.0;
+pub const BackTextureWidth: f32 = 1280;
+pub const BackTextureHeight: f32 = 240;
+
+pub const TextureDim: f32 = 32.0;