Brought in Amit's latest and tweaked a few more build options for enabling some safety checks in GCC.

master
Zed A. Shaw 2 months ago
parent eef13bd325
commit 308fe4bed2
  1. 3
      amt/main.cpp
  2. 78
      amt/raycaster.cpp
  3. 7
      amt/raycaster.hpp
  4. 1
      constants.hpp
  5. 2
      main.cpp
  6. 4
      meson.build

@ -57,6 +57,9 @@ int main() {
Stats stats; Stats stats;
// NOTE: Enable this to lock frames at 60
window.setFramerateLimit(60);
while(window.isOpen()) { while(window.isOpen()) {
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
rayview.render(); rayview.render();

@ -2,6 +2,7 @@
#include "amt/texture.hpp" #include "amt/texture.hpp"
#include "amt/pixel.hpp" #include "amt/pixel.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "thread.hpp"
#define AMT_LIGHT #define AMT_LIGHT
@ -11,14 +12,14 @@ using namespace fmt;
#ifdef AMT_LIGHT #ifdef AMT_LIGHT
static constexpr auto room_brightness = 0.3f; // increse this to increase the room brightness. Higher value means brighter room. static constexpr auto room_brightness = 0.3f; // increse this to increase the room brightness. Higher value means brighter room.
inline static constexpr amt::RGBA dumb_lighting(amt::RGBA pixel, double distance, double distance_from_center) { inline static constexpr amt::RGBA dumb_lighting(amt::RGBA pixel, float distance, float distance_from_center) {
auto const dim_pixel = pixel * room_brightness; auto const dim_pixel = pixel * room_brightness;
if (distance_from_center >= 0) { if (distance_from_center >= 0) {
auto const min_brightness = 1. / std::max(distance_from_center, 0.5); // farther away from the center darker it gets auto const min_brightness = 1.f / std::max(distance_from_center, 0.5f); // farther away from the center darker it gets
auto const max_brightness = 1.; // brighness should not exceed 1 auto const max_brightness = 1.f; // brighness should not exceed 1
auto const pixel_brightness = std::max(min_brightness, std::min(max_brightness, distance)); auto const pixel_brightness = std::max(min_brightness, std::min(max_brightness, distance));
auto const yellow_brightness = float(distance_from_center * 60);
auto const yellow_brightness = float(distance_from_center * 60);
amt::RGBA const yellow = amt::HSLA(40, 20, yellow_brightness); amt::RGBA const yellow = amt::HSLA(40, 20, yellow_brightness);
auto temp = (pixel / pixel_brightness).blend<amt::BlendMode::softLight>(yellow); auto temp = (pixel / pixel_brightness).blend<amt::BlendMode::softLight>(yellow);
@ -29,6 +30,7 @@ inline static constexpr amt::RGBA dumb_lighting(amt::RGBA pixel, double distance
} }
#else #else
inline static constexpr amt::RGBA dumb_lighting(amt::RGBA pixel, double distance, double distance_from_center) { inline static constexpr amt::RGBA dumb_lighting(amt::RGBA pixel, double distance, double distance_from_center) {
(void)distance_from_center;
if(distance < 0.9) return pixel; if(distance < 0.9) return pixel;
return pixel / distance; return pixel / distance;
} }
@ -45,7 +47,9 @@ Raycaster::Raycaster(sf::RenderWindow& window, Matrix &map, unsigned width, unsi
$map(map), $map(map),
spriteOrder(textures.NUM_SPRITES), spriteOrder(textures.NUM_SPRITES),
spriteDistance(textures.NUM_SPRITES), spriteDistance(textures.NUM_SPRITES),
ZBuffer(width) ZBuffer(width),
$radius(std::min($height, $width) / 2),
$r_sq($radius * $radius)
{ {
$window.setVerticalSyncEnabled(VSYNC); $window.setVerticalSyncEnabled(VSYNC);
view_sprite.setPosition({0, 0}); view_sprite.setPosition({0, 0});
@ -74,9 +78,6 @@ void Raycaster::clear() {
} }
void Raycaster::sprite_casting() { void Raycaster::sprite_casting() {
const int textureWidth = textures.TEXTURE_WIDTH;
const int textureHeight = textures.TEXTURE_HEIGHT;
// sort sprites from far to close // sort sprites from far to close
for(int i = 0; i < textures.NUM_SPRITES; i++) { for(int i = 0; i < textures.NUM_SPRITES; i++) {
auto& sprite = textures.get_sprite(i); auto& sprite = textures.get_sprite(i);
@ -90,8 +91,10 @@ void Raycaster::sprite_casting() {
sort_sprites(spriteOrder, spriteDistance, textures.NUM_SPRITES); sort_sprites(spriteOrder, spriteDistance, textures.NUM_SPRITES);
/*for(int i = 0; i < textures.NUM_SPRITES; i++) {*/
// after sorting the sprites, do the projection // after sorting the sprites, do the projection
for(int i = 0; i < textures.NUM_SPRITES; i++) { // Be careful about capturing stack variables.
amt::parallel_for<1>(pool, 0, textures.NUM_SPRITES, [this, textureWidth = textures.TEXTURE_WIDTH, textureHeight = textures.TEXTURE_HEIGHT](size_t i){
int sprite_index = spriteOrder[i]; int sprite_index = spriteOrder[i];
Sprite& sprite_rec = textures.get_sprite(sprite_index); Sprite& sprite_rec = textures.get_sprite(sprite_index);
auto& sprite_texture = textures.get_texture(sprite_rec.texture); auto& sprite_texture = textures.get_texture(sprite_rec.texture);
@ -139,33 +142,39 @@ void Raycaster::sprite_casting() {
// the conditions in the if are: // the conditions in the if are:
// 1) it's in front of the camera plane so you don't see things behind you // 1) it's in front of the camera plane so you don't see things behind you
// 2) ZBuffer, with perpendicular distance // 2) ZBuffer, with perpendicular distance
if (texX < 0) continue;
if(transformY > 0 && transformY < ZBuffer[stripe]) { if(transformY > 0 && transformY < ZBuffer[stripe]) {
for(int y = drawStartY; y < drawEndY; y++) { for(int y = drawStartY; y < drawEndY; y++) {
//256 and 128 factors to avoid floats //256 and 128 factors to avoid floats
int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128; int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128;
int texY = ((d * textureHeight) / spriteHeight) / 256; int texY = ((d * textureHeight) / spriteHeight) / 256;
if ((size_t)texY >= sprite_texture.rows()) continue;
//get current color from the texture //get current color from the texture
// BUG: this crashes sometimes when the math goes out of bounds
if(texY < 0 || texY >= (int)sprite_texture.rows()) continue;
auto color = sprite_texture[texY][texX]; auto color = sprite_texture[texY][texX];
// poor person's transparency, get current color from the texture // poor person's transparency, get current color from the texture
pixels[y][stripe] = (color.to_hex() & 0xffffff00) ? color: pixels[y][stripe]; if (!(color.to_hex() & 0xffffff00)) continue;
auto dist = get_distance_from_center(stripe, y);
pixels[y][stripe] = dumb_lighting(color, d, dist);
} }
} }
} }
} });
} }
void Raycaster::cast_rays() { float Raycaster::get_distance_from_center(int x, int y) const noexcept {
double perpWallDist = 0; float cx = $width / 2;
float cy = $height / 2;
auto dx = cx - x;
auto dy = cy - y;
return ($r_sq - dx * dx - dy * dy) / $r_sq;
}
auto const cx = $width / 2; void Raycaster::cast_rays() {
auto const cy = $height / 2;
double const radius = std::min($height, $width) / 2;
double const r_sq = radius * radius;
// WALL CASTING // WALL CASTING
for(int x = 0; x < $width; x++) { /*for(int x = 0; x < $width; x++) {*/
amt::parallel_for<32>(pool, 0, static_cast<std::size_t>($width), [this](size_t x){
double perpWallDist = 0;
// calculate ray position and direction // calculate ray position and direction
double cameraX = 2 * x / double($width) - 1; // x-coord in camera space double cameraX = 2 * x / double($width) - 1; // x-coord in camera space
double rayDirX = dirX + planeX * cameraX; double rayDirX = dirX + planeX * cameraX;
@ -260,23 +269,24 @@ void Raycaster::cast_rays() {
for(int y = drawStart; y < drawEnd; y++) { for(int y = drawStart; y < drawEnd; y++) {
int texY = (int)texPos & (textures.TEXTURE_HEIGHT - 1); int texY = (int)texPos & (textures.TEXTURE_HEIGHT - 1);
texPos += step; texPos += step;
auto const dx = cx - x; auto dist = get_distance_from_center(x, y);
auto const dy = cy - y; auto color = dumb_lighting(texture[texY][texX], perpWallDist, dist);
double const dist = dx * dx + dy * dy;
auto color = dumb_lighting(texture[texY][texX], perpWallDist, (r_sq - dist) / r_sq);
pixels[y][x] = color; pixels[y][x] = color;
} }
// SET THE ZBUFFER FOR THE SPRITE CASTING // SET THE ZBUFFER FOR THE SPRITE CASTING
ZBuffer[x] = perpWallDist; ZBuffer[x] = perpWallDist;
} });
} }
void Raycaster::draw_ceiling_floor() { void Raycaster::draw_ceiling_floor() {
const size_t textureWidth = textures.TEXTURE_WIDTH;
const size_t textureHeight = textures.TEXTURE_HEIGHT;
for(int y = $height / 2 + 1; y < $height; ++y) { /*for(int y = $height / 2 + 1; y < $height; ++y) {*/
auto const h = static_cast<size_t>($height);
amt::parallel_for<32>(pool, h / 2, h, [this, $height=h](size_t y){
const size_t textureWidth = textures.TEXTURE_WIDTH;
const size_t textureHeight = textures.TEXTURE_HEIGHT;
// rayDir for leftmost ray (x=0) and rightmost (x = w) // rayDir for leftmost ray (x=0) and rightmost (x = w)
float rayDirX0 = dirX - planeX; float rayDirX0 = dirX - planeX;
float rayDirY0 = dirY - planeY; float rayDirY0 = dirY - planeY;
@ -327,10 +337,12 @@ void Raycaster::draw_ceiling_floor() {
#ifdef AMT_LIGHT #ifdef AMT_LIGHT
// FLOOR // FLOOR
pixels[y][x] = textures.floor[ty][tx] * room_brightness; auto dist_floor = get_distance_from_center(x, y);
pixels[y][x] = dumb_lighting(textures.floor[ty][tx], p, dist_floor);
// CEILING // CEILING
pixels[$height - y - 1][x] = textures.ceiling[ty][tx] * room_brightness; auto dist_ceiling = get_distance_from_center(x, $height - y - 1);
pixels[$height - y - 1][x] = dumb_lighting(textures.ceiling[ty][tx], p, dist_ceiling);
#else #else
// FLOOR // FLOOR
pixels[y][x] = textures.floor[ty][tx]; pixels[y][x] = textures.floor[ty][tx];
@ -340,14 +352,18 @@ void Raycaster::draw_ceiling_floor() {
#endif #endif
} }
} });
} }
void Raycaster::render() { void Raycaster::render() {
draw_ceiling_floor(); draw_ceiling_floor();
// This wait to prevent data-race
pool.wait(); // Try to remove this to see unbelievable performance
cast_rays(); cast_rays();
pool.wait(); // Try to remove this too
sprite_casting(); sprite_casting();
pool.wait();
draw_pixel_buffer(); draw_pixel_buffer();
} }

@ -13,6 +13,7 @@
#include "amt/pixel.hpp" #include "amt/pixel.hpp"
#include "amt/texture.hpp" #include "amt/texture.hpp"
#include <memory> #include <memory>
#include "thread.hpp"
using Matrix = amt::Matrix<int>; using Matrix = amt::Matrix<int>;
@ -43,6 +44,9 @@ struct Raycaster {
std::vector<int> spriteOrder; std::vector<int> spriteOrder;
std::vector<double> spriteDistance; std::vector<double> spriteDistance;
std::vector<double> ZBuffer; // width std::vector<double> ZBuffer; // width
float $radius; // std::min($height, $width) / 2;
float $r_sq; // = radius * radius;
amt::thread_pool_t pool;
Raycaster(sf::RenderWindow& window, Matrix &map, unsigned width, unsigned height); Raycaster(sf::RenderWindow& window, Matrix &map, unsigned width, unsigned height);
@ -59,10 +63,11 @@ struct Raycaster {
void run(double speed, int dir); void run(double speed, int dir);
void rotate(double speed, int dir); void rotate(double speed, int dir);
void position_camera(float player_x, float player_y); void position_camera(float player_x, float player_y);
float get_distance_from_center(int x, int y) const noexcept;
void set_position(int x, int y); void set_position(int x, int y);
inline size_t pixcoord(int x, int y) { inline size_t pixcoord(int x, int y) {
return ((y) * $width) + (x); return ((y) * $width) + (x);
} }
}; };

@ -7,6 +7,7 @@ constexpr const int RAY_VIEW_Y=0;
constexpr const int SCREEN_HEIGHT=720; constexpr const int SCREEN_HEIGHT=720;
constexpr const int SCREEN_WIDTH=1280; constexpr const int SCREEN_WIDTH=1280;
constexpr const bool VSYNC=false; constexpr const bool VSYNC=false;
constexpr const int FRAME_LIMIT=30;
#ifdef NDEBUG #ifdef NDEBUG
constexpr const bool DEBUG_BUILD=false; constexpr const bool DEBUG_BUILD=false;
#else #else

@ -57,6 +57,8 @@ int main() {
Stats stats; Stats stats;
window.setFramerateLimit(FRAME_LIMIT);
while(window.isOpen()) { while(window.isOpen()) {
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
rayview.render(); rayview.render();

@ -63,5 +63,7 @@ executable('amtcaster', [
'amt/texture.cpp', 'amt/texture.cpp',
'amt/raycaster.cpp', 'amt/raycaster.cpp',
'amt/main.cpp' 'amt/main.cpp'
], override_options: exe_defaults, ],
cpp_args: ['-std=c++23'],
override_options: exe_defaults,
dependencies: dependencies) dependencies: dependencies)

Loading…
Cancel
Save