Skip to content

Commit c45987e

Browse files
committed
Tiny KABOOM first commit; the simplest possible ray marching
0 parents  commit c45987e

File tree

5 files changed

+159
-0
lines changed

5 files changed

+159
-0
lines changed

CMakeLists.txt

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
cmake_minimum_required (VERSION 2.8)
2+
project (tinykaboom)
3+
4+
include(CheckCXXCompilerFlag)
5+
6+
function(enable_cxx_compiler_flag_if_supported flag)
7+
string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_already_set)
8+
if(flag_already_set EQUAL -1)
9+
check_cxx_compiler_flag("${flag}" flag_supported)
10+
if(flag_supported)
11+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
12+
endif()
13+
unset(flag_supported CACHE)
14+
endif()
15+
endfunction()
16+
17+
enable_cxx_compiler_flag_if_supported("-Wall")
18+
enable_cxx_compiler_flag_if_supported("-Wextra")
19+
enable_cxx_compiler_flag_if_supported("-pedantic")
20+
enable_cxx_compiler_flag_if_supported("-std=c++11")
21+
enable_cxx_compiler_flag_if_supported("-O3")
22+
enable_cxx_compiler_flag_if_supported("-fopenmp")
23+
24+
file(GLOB SOURCES *.h *.cpp)
25+
26+
add_executable(${PROJECT_NAME} ${SOURCES})
27+

Readme.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Tiny KABOOM in less than 200 lines of bare C++
2+
3+
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).
4+
5+
**Check [the article](https://github.com/ssloy/tinykaboom/wiki) that accompanies the source code.
6+
If you are looking for a software rasterizer, check the [other part of the lectures](https://github.com/ssloy/tinyrenderer/wiki).**
7+
8+
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:
9+
![](https://raw.githubusercontent.com/ssloy/tinykaboom/master/out.jpg)
10+
11+
## compilation
12+
```sh
13+
git clone https://github.com/ssloy/tinykaboom.git
14+
cd tinykaboom
15+
mkdir build
16+
cd build
17+
cmake ..
18+
make
19+
```
20+
21+

geometry.h

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef __GEOMETRY_H__
2+
#define __GEOMETRY_H__
3+
#include <cmath>
4+
#include <cassert>
5+
6+
template <size_t DIM, typename T> struct vec {
7+
vec() { for (size_t i=DIM; i--; data_[i] = T()); }
8+
T& operator[](const size_t i) { assert(i<DIM); return data_[i]; }
9+
const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; }
10+
private:
11+
T data_[DIM];
12+
};
13+
14+
template <typename T> struct vec<3,T> {
15+
vec() : x(T()), y(T()), z(T()) {}
16+
vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
17+
T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
18+
const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
19+
float norm() const { return std::sqrt(x*x+y*y+z*z); }
20+
vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; }
21+
T x,y,z;
22+
};
23+
24+
template<size_t DIM,typename T> T operator*(const vec<DIM,T>& lhs, const vec<DIM,T>& rhs) {
25+
T ret = T();
26+
for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]);
27+
return ret;
28+
}
29+
30+
template<size_t DIM,typename T>vec<DIM,T> operator+(vec<DIM,T> lhs, const vec<DIM,T>& rhs) {
31+
for (size_t i=DIM; i--; lhs[i]+=rhs[i]);
32+
return lhs;
33+
}
34+
35+
template<size_t DIM,typename T>vec<DIM,T> operator-(vec<DIM,T> lhs, const vec<DIM,T>& rhs) {
36+
for (size_t i=DIM; i--; lhs[i]-=rhs[i]);
37+
return lhs;
38+
}
39+
40+
template<size_t DIM,typename T,typename U> vec<DIM,T> operator*(const vec<DIM,T> &lhs, const U& rhs) {
41+
vec<DIM,T> ret;
42+
for (size_t i=DIM; i--; ret[i]=lhs[i]*rhs);
43+
return ret;
44+
}
45+
46+
template<size_t DIM,typename T> vec<DIM,T> operator-(const vec<DIM,T> &lhs) {
47+
return lhs*T(-1);
48+
}
49+
50+
typedef vec<3, float> Vec3f;
51+
52+
#endif //__GEOMETRY_H__
53+

out.jpg

19.9 KB
Loading

tinykaboom.cpp

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#define _USE_MATH_DEFINES
2+
#include <cmath>
3+
#include <algorithm>
4+
#include <limits>
5+
#include <iostream>
6+
#include <fstream>
7+
#include <vector>
8+
#include "geometry.h"
9+
10+
const float sphere_radius = 1.5;
11+
12+
float signed_distance(const Vec3f &p) {
13+
return p.norm() - sphere_radius;
14+
}
15+
16+
bool sphere_trace(const Vec3f &orig, const Vec3f &dir, Vec3f &pos) {
17+
pos = orig;
18+
for (size_t i=0; i<128; i++) {
19+
float d = signed_distance(pos);
20+
if (d < 0) return true;
21+
pos = pos + dir*std::max(d*0.1f, .01f);
22+
}
23+
return false;
24+
}
25+
26+
int main() {
27+
const int width = 640;
28+
const int height = 480;
29+
const float fov = M_PI/3.;
30+
std::vector<Vec3f> framebuffer(width*height);
31+
32+
#pragma omp parallel for
33+
for (size_t j = 0; j<height; j++) { // actual rendering loop
34+
for (size_t i = 0; i<width; i++) {
35+
float dir_x = (i + 0.5) - width/2.;
36+
float dir_y = -(j + 0.5) + height/2.; // this flips the image at the same time
37+
float dir_z = -height/(2.*tan(fov/2.));
38+
Vec3f hit;
39+
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
40+
framebuffer[i+j*width] = Vec3f(1, 1, 1);
41+
} else {
42+
framebuffer[i+j*width] = Vec3f(0.2, 0.7, 0.8); // background color
43+
}
44+
}
45+
}
46+
47+
std::ofstream ofs("./out.ppm", std::ios::binary); // save the framebuffer to file
48+
ofs << "P6\n" << width << " " << height << "\n255\n";
49+
for (size_t i = 0; i < height*width; ++i) {
50+
for (size_t j = 0; j<3; j++) {
51+
ofs << (char)(std::max(0, std::min(255, static_cast<int>(255*framebuffer[i][j]))));
52+
}
53+
}
54+
ofs.close();
55+
56+
return 0;
57+
}
58+

0 commit comments

Comments
 (0)