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;
// NOTE: Enable this to lock frames at 60
window.setFramerateLimit(60);
while(window.isOpen()) {
auto start = std::chrono::high_resolution_clock::now();
rayview.render();

@ -2,6 +2,7 @@
#include "amt/texture.hpp"
#include "amt/pixel.hpp"
#include "constants.hpp"
#include "thread.hpp"
#define AMT_LIGHT
@ -11,14 +12,14 @@ using namespace fmt;
#ifdef AMT_LIGHT
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;
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 max_brightness = 1.; // brighness should not exceed 1
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.f; // brighness should not exceed 1
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);
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
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;
return pixel / distance;
}
@ -45,7 +47,9 @@ Raycaster::Raycaster(sf::RenderWindow& window, Matrix &map, unsigned width, unsi
$map(map),
spriteOrder(textures.NUM_SPRITES),
spriteDistance(textures.NUM_SPRITES),
ZBuffer(width)
ZBuffer(width),
$radius(std::min($height, $width) / 2),
$r_sq($radius * $radius)
{
$window.setVerticalSyncEnabled(VSYNC);
view_sprite.setPosition({0, 0});
@ -74,9 +78,6 @@ void Raycaster::clear() {
}
void Raycaster::sprite_casting() {
const int textureWidth = textures.TEXTURE_WIDTH;
const int textureHeight = textures.TEXTURE_HEIGHT;
// sort sprites from far to close
for(int i = 0; i < textures.NUM_SPRITES; i++) {
auto& sprite = textures.get_sprite(i);
@ -90,8 +91,10 @@ void Raycaster::sprite_casting() {
sort_sprites(spriteOrder, spriteDistance, textures.NUM_SPRITES);
/*for(int i = 0; i < textures.NUM_SPRITES; i++) {*/
// 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];
Sprite& sprite_rec = textures.get_sprite(sprite_index);
auto& sprite_texture = textures.get_texture(sprite_rec.texture);
@ -139,33 +142,39 @@ void Raycaster::sprite_casting() {
// the conditions in the if are:
// 1) it's in front of the camera plane so you don't see things behind you
// 2) ZBuffer, with perpendicular distance
if (texX < 0) continue;
if(transformY > 0 && transformY < ZBuffer[stripe]) {
for(int y = drawStartY; y < drawEndY; y++) {
//256 and 128 factors to avoid floats
int d = (y - vMoveScreen) * 256 - $height * 128 + spriteHeight * 128;
int texY = ((d * textureHeight) / spriteHeight) / 256;
if ((size_t)texY >= sprite_texture.rows()) continue;
//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];
// 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() {
double perpWallDist = 0;
float Raycaster::get_distance_from_center(int x, int y) const noexcept {
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;
auto const cy = $height / 2;
double const radius = std::min($height, $width) / 2;
double const r_sq = radius * radius;
void Raycaster::cast_rays() {
// 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
double cameraX = 2 * x / double($width) - 1; // x-coord in camera space
double rayDirX = dirX + planeX * cameraX;
@ -260,23 +269,24 @@ void Raycaster::cast_rays() {
for(int y = drawStart; y < drawEnd; y++) {
int texY = (int)texPos & (textures.TEXTURE_HEIGHT - 1);
texPos += step;
auto const dx = cx - x;
auto const dy = cy - y;
double const dist = dx * dx + dy * dy;
auto color = dumb_lighting(texture[texY][texX], perpWallDist, (r_sq - dist) / r_sq);
auto dist = get_distance_from_center(x, y);
auto color = dumb_lighting(texture[texY][texX], perpWallDist, dist);
pixels[y][x] = color;
}
// SET THE ZBUFFER FOR THE SPRITE CASTING
ZBuffer[x] = perpWallDist;
}
});
}
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)
float rayDirX0 = dirX - planeX;
float rayDirY0 = dirY - planeY;
@ -327,10 +337,12 @@ void Raycaster::draw_ceiling_floor() {
#ifdef AMT_LIGHT
// 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
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
// FLOOR
pixels[y][x] = textures.floor[ty][tx];
@ -340,14 +352,18 @@ void Raycaster::draw_ceiling_floor() {
#endif
}
}
});
}
void Raycaster::render() {
draw_ceiling_floor();
// This wait to prevent data-race
pool.wait(); // Try to remove this to see unbelievable performance
cast_rays();
pool.wait(); // Try to remove this too
sprite_casting();
pool.wait();
draw_pixel_buffer();
}

@ -13,6 +13,7 @@
#include "amt/pixel.hpp"
#include "amt/texture.hpp"
#include <memory>
#include "thread.hpp"
using Matrix = amt::Matrix<int>;
@ -43,6 +44,9 @@ struct Raycaster {
std::vector<int> spriteOrder;
std::vector<double> spriteDistance;
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);
@ -59,10 +63,11 @@ struct Raycaster {
void run(double speed, int dir);
void rotate(double speed, int dir);
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);
inline size_t pixcoord(int x, int y) {
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_WIDTH=1280;
constexpr const bool VSYNC=false;
constexpr const int FRAME_LIMIT=30;
#ifdef NDEBUG
constexpr const bool DEBUG_BUILD=false;
#else

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

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

Loading…
Cancel
Save