Brought in Amit's latest and tweaked a few more build options for enabling some safety checks in GCC.
This commit is contained in:
parent
eef13bd325
commit
308fe4bed2
6 changed files with 62 additions and 33 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raycaster::cast_rays() {
|
void Raycaster::cast_rays() {
|
||||||
double perpWallDist = 0;
|
|
||||||
|
|
||||||
auto const cx = $width / 2;
|
|
||||||
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
|
||||||
|
|
2
main.cpp
2
main.cpp
|
@ -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…
Add table
Add a link
Reference in a new issue