-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tiny KABOOM first commit; the simplest possible ray marching
- Loading branch information
0 parents
commit c45987e
Showing
5 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
cmake_minimum_required (VERSION 2.8) | ||
project (tinykaboom) | ||
|
||
include(CheckCXXCompilerFlag) | ||
|
||
function(enable_cxx_compiler_flag_if_supported flag) | ||
string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set) | ||
if(flag_already_set EQUAL -1) | ||
check_cxx_compiler_flag("${flag}" flag_supported) | ||
if(flag_supported) | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) | ||
endif() | ||
unset(flag_supported CACHE) | ||
endif() | ||
endfunction() | ||
|
||
enable_cxx_compiler_flag_if_supported("-Wall") | ||
enable_cxx_compiler_flag_if_supported("-Wextra") | ||
enable_cxx_compiler_flag_if_supported("-pedantic") | ||
enable_cxx_compiler_flag_if_supported("-std=c++11") | ||
enable_cxx_compiler_flag_if_supported("-O3") | ||
enable_cxx_compiler_flag_if_supported("-fopenmp") | ||
|
||
file(GLOB SOURCES *.h *.cpp) | ||
|
||
add_executable(${PROJECT_NAME} ${SOURCES}) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Tiny KABOOM in less than 200 lines of bare C++ | ||
|
||
This repository is a support code for my computer graphics lectures. It is not meant to be the ultimate rendering code or even physically realistic. It is meant to be **simple**. This project is distributed under the [DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE](https://en.wikipedia.org/wiki/WTFPL). | ||
|
||
**Check [the article](https://github.com/ssloy/tinykaboom/wiki) that accompanies the source code. | ||
If you are looking for a software rasterizer, check the [other part of the lectures](https://github.com/ssloy/tinyrenderer/wiki).** | ||
|
||
In my lectures I tend to avoid third party libraries as long as it is reasonable, because it forces to understand what is happening under the hood. So, the raytracing 256 lines of plain C++ give us this result: | ||
![](https://raw.githubusercontent.com/ssloy/tinykaboom/master/out.jpg) | ||
|
||
## compilation | ||
```sh | ||
git clone https://github.com/ssloy/tinykaboom.git | ||
cd tinykaboom | ||
mkdir build | ||
cd build | ||
cmake .. | ||
make | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#ifndef __GEOMETRY_H__ | ||
#define __GEOMETRY_H__ | ||
#include <cmath> | ||
#include <cassert> | ||
|
||
template <size_t DIM, typename T> struct vec { | ||
vec() { for (size_t i=DIM; i--; data_[i] = T()); } | ||
T& operator[](const size_t i) { assert(i<DIM); return data_[i]; } | ||
const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; } | ||
private: | ||
T data_[DIM]; | ||
}; | ||
|
||
template <typename T> struct vec<3,T> { | ||
vec() : x(T()), y(T()), z(T()) {} | ||
vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {} | ||
T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); } | ||
const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); } | ||
float norm() const { return std::sqrt(x*x+y*y+z*z); } | ||
vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; } | ||
T x,y,z; | ||
}; | ||
|
||
template<size_t DIM,typename T> T operator*(const vec<DIM,T>& lhs, const vec<DIM,T>& rhs) { | ||
T ret = T(); | ||
for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]); | ||
return ret; | ||
} | ||
|
||
template<size_t DIM,typename T>vec<DIM,T> operator+(vec<DIM,T> lhs, const vec<DIM,T>& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]+=rhs[i]); | ||
return lhs; | ||
} | ||
|
||
template<size_t DIM,typename T>vec<DIM,T> operator-(vec<DIM,T> lhs, const vec<DIM,T>& rhs) { | ||
for (size_t i=DIM; i--; lhs[i]-=rhs[i]); | ||
return lhs; | ||
} | ||
|
||
template<size_t DIM,typename T,typename U> vec<DIM,T> operator*(const vec<DIM,T> &lhs, const U& rhs) { | ||
vec<DIM,T> ret; | ||
for (size_t i=DIM; i--; ret[i]=lhs[i]*rhs); | ||
return ret; | ||
} | ||
|
||
template<size_t DIM,typename T> vec<DIM,T> operator-(const vec<DIM,T> &lhs) { | ||
return lhs*T(-1); | ||
} | ||
|
||
typedef vec<3, float> Vec3f; | ||
|
||
#endif //__GEOMETRY_H__ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#define _USE_MATH_DEFINES | ||
#include <cmath> | ||
#include <algorithm> | ||
#include <limits> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <vector> | ||
#include "geometry.h" | ||
|
||
const float sphere_radius = 1.5; | ||
|
||
float signed_distance(const Vec3f &p) { | ||
return p.norm() - sphere_radius; | ||
} | ||
|
||
bool sphere_trace(const Vec3f &orig, const Vec3f &dir, Vec3f &pos) { | ||
pos = orig; | ||
for (size_t i=0; i<128; i++) { | ||
float d = signed_distance(pos); | ||
if (d < 0) return true; | ||
pos = pos + dir*std::max(d*0.1f, .01f); | ||
} | ||
return false; | ||
} | ||
|
||
int main() { | ||
const int width = 640; | ||
const int height = 480; | ||
const float fov = M_PI/3.; | ||
std::vector<Vec3f> framebuffer(width*height); | ||
|
||
#pragma omp parallel for | ||
for (size_t j = 0; j<height; j++) { // actual rendering loop | ||
for (size_t i = 0; i<width; i++) { | ||
float dir_x = (i + 0.5) - width/2.; | ||
float dir_y = -(j + 0.5) + height/2.; // this flips the image at the same time | ||
float dir_z = -height/(2.*tan(fov/2.)); | ||
Vec3f hit; | ||
if (sphere_trace(Vec3f(0, 0, 3), Vec3f(dir_x, dir_y, dir_z).normalize(), hit)) { // the camera is placed to (0,0,3) and it looks along the -z axis | ||
framebuffer[i+j*width] = Vec3f(1, 1, 1); | ||
} else { | ||
framebuffer[i+j*width] = Vec3f(0.2, 0.7, 0.8); // background color | ||
} | ||
} | ||
} | ||
|
||
std::ofstream ofs("./out.ppm", std::ios::binary); // save the framebuffer to file | ||
ofs << "P6\n" << width << " " << height << "\n255\n"; | ||
for (size_t i = 0; i < height*width; ++i) { | ||
for (size_t j = 0; j<3; j++) { | ||
ofs << (char)(std::max(0, std::min(255, static_cast<int>(255*framebuffer[i][j])))); | ||
} | ||
} | ||
ofs.close(); | ||
|
||
return 0; | ||
} | ||
|