Skip to content

Instantly share code, notes, and snippets.

@TyGrze
Created December 30, 2018 14:10
Show Gist options
  • Save TyGrze/597f11123dc53c0081794d1f0f5b0be8 to your computer and use it in GitHub Desktop.
Save TyGrze/597f11123dc53c0081794d1f0f5b0be8 to your computer and use it in GitHub Desktop.
// RayTracing3D.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#define OLC_PGE_APPLICATION
#include <iostream>
#include <ctime>
#include <cmath>
#include "olcPixelGameEngine.h"
int screenRatio = 4;
int screenWidth = 1280 / screenRatio;
int screenHeight = 720 / screenRatio;
int mapSize = 32;
float playerX = 8;
float playerY = 8;
float playerAngle = 0;
float FOV = 3.14159 / 5.0f;
float farPlane = std::sqrtf(std::powf(mapSize, 2.0f));
float movementSpeed = 5;
float distanceQuility = 0.01f;
int map[32][32] =
{
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
auto start = std::chrono::system_clock::now();
// Some computation here
auto end = std::chrono::system_clock::now();
olc::Sprite sprite;
// Override base class with your custom functionality
class Example : public olc::PixelGameEngine
{
public:
Example()
{
sAppName = "Example";
}
private:
olc::Sprite *wallTexture;
public:
bool OnUserCreate() override
{
wallTexture = new olc::Sprite();
// Called once at the start, so create things here
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
start = std::chrono::system_clock::now();
std::chrono::duration<float> elapsedTimeClock = end - start;
end = start;
float elapsedTime = -elapsedTimeClock.count();
float tempX = playerX, tempY = playerY;
if (GetKey(olc::Key::E).bHeld)
playerAngle += 1.1f * elapsedTime;
if (GetKey(olc::Key::Q).bHeld)
playerAngle -= 1.1f * elapsedTime;
if (GetKey(olc::Key::W).bHeld)
{
tempX += sinf(playerAngle) * movementSpeed * elapsedTime;
tempY += cosf(playerAngle) * movementSpeed * elapsedTime;
}
if (GetKey(olc::Key::D).bHeld)
{
tempX += sinf(playerAngle + (90 * 3.14159 / 180)) * movementSpeed * elapsedTime;
tempY += cosf(playerAngle + (90 * 3.14159 / 180)) * movementSpeed * elapsedTime;
}
if (GetKey(olc::Key::A).bHeld)
{
tempX += sinf(playerAngle - (90 * 3.14159 / 180)) * movementSpeed * elapsedTime;
tempY += cosf(playerAngle - (90 * 3.14159 / 180)) * movementSpeed * elapsedTime;
}
if (GetKey(olc::Key::S).bHeld)
{
tempX -= sinf(playerAngle) * movementSpeed * elapsedTime;
tempY -= cosf(playerAngle) * movementSpeed * elapsedTime;
}
if (!map[(int)tempX][(int)tempY])
{
playerX = tempX;
playerY = tempY;
}
for (int x = 0; x < screenWidth; x++)
{
float rayAngle = (playerAngle - FOV / 2) + ((float)x / (float)screenWidth) * FOV;
float distanceToWall = 0.0f;
bool hitWall = false;
float unitVectorX = sinf(rayAngle);
float unitVectorY = cosf(rayAngle);
while (!hitWall && distanceToWall < farPlane)
{
distanceToWall += distanceQuility;
hitWall = RayHitWall(unitVectorX, unitVectorY, distanceToWall);
}
if (distanceToWall >= farPlane)
distanceToWall = screenHeight / 2;
int ceilingSize = (float)(screenHeight / 1.8) - screenWidth / distanceToWall;
int floorSize = screenHeight - ceilingSize;
float shading = 255 - ((distanceToWall / farPlane) * 255);
for (int y = 0; y < screenHeight; y++)
{
if (y <= ceilingSize)
Draw(x, y, olc::BLUE);
else if (y > ceilingSize && y <= floorSize)
Draw(x, y, olc::Pixel(shading, shading, shading));
else
{
Draw(x, y, olc::YELLOW);
}
}
}
return true;
}
bool RayHitWall(float unitVectorX, float unitVectorY, float distanceToWall)
{
bool hitWall = false;
int testRayX = (int)(playerX + unitVectorX * distanceToWall);
int testRayY = (int)(playerY + unitVectorY * distanceToWall);
if (testRayX < 0 || testRayX >= mapSize || testRayY < 0 || testRayY >= mapSize)
{
hitWall = true;
distanceToWall = farPlane;
}
else if (map[(int)testRayX][(int)testRayY] == 1)
{
hitWall = true;
}
return hitWall;
}
};
int main()
{
Example demo;
if (demo.Construct(screenWidth, screenHeight, screenRatio, screenRatio))
demo.Start();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment