├── Entity.cpp ├── Entity.h ├── PhongShader.cpp ├── PhongShader.h ├── README.md ├── Ray.cpp ├── Ray.h ├── RayTracing.cpp ├── RayTracing.h ├── Shader ├── Fragment ├── Shader.cpp ├── Shader.h └── Vertex └── main.cpp /Entity.cpp: -------------------------------------------------------------------------------- 1 | #include "Entity.h" 2 | 3 | namespace RayTracing 4 | { 5 | // Plane 6 | Plane::Plane(const glm::vec3& aPoint, const glm::vec3& normal) : _normal(glm::normalize(normal)), _aPoint(aPoint) 7 | { 8 | 9 | } 10 | bool Plane::onPlane(const glm::vec3& p) const 11 | { 12 | return glm::dot(p - _aPoint, _normal) == 0; 13 | } 14 | 15 | float Plane::rayCollision(const Ray& ray) const 16 | { 17 | float v1 = glm::dot(ray.getVertex() - _aPoint, _normal); 18 | float v2 = glm::dot(_normal, ray.getDirection()); 19 | if (abs(v2) < FLOAT_EPS) // v2 == 0 20 | { 21 | return -1; 22 | } 23 | else 24 | { 25 | return -v1 / v2; 26 | } 27 | } 28 | glm::vec3 Plane::calNormal(const glm::vec3& p) const 29 | { 30 | return _normal; 31 | } 32 | // Triangle 33 | 34 | Triangle::Triangle(const glm::vec3& A, const glm::vec3& B, const glm::vec3& C) : 35 | _vertice{ A, B, C } 36 | { 37 | 38 | } 39 | 40 | bool Triangle::inTriangle(const glm::vec3& p) const 41 | { 42 | auto plane = getPlane(); 43 | 44 | if (!plane.onPlane(p)) 45 | { 46 | return false; 47 | } 48 | 49 | glm::vec3 vectorToP[3]; 50 | glm::vec3 crosses[3]; 51 | for (int i = 0; i < 3; i++) 52 | { 53 | vectorToP[3] = p - _vertice[i]; 54 | } 55 | for (int i = 0; i < 3; i++) 56 | { 57 | crosses[i] = glm::normalize(glm::cross(vectorToP[i], vectorToP[(i + 1) % 3])); 58 | } 59 | 60 | // Three cross vectors are in same direction 61 | if (glm::distance(crosses[0], crosses[1]) < FLOAT_EPS && 62 | glm::distance(crosses[1], crosses[2]) < FLOAT_EPS) 63 | { 64 | return true; 65 | } 66 | else 67 | { 68 | return false; 69 | } 70 | } 71 | 72 | Plane Triangle::getPlane() const 73 | { 74 | return Plane(_vertice[0], getNormal()); 75 | } 76 | 77 | glm::vec3 Triangle::getNormal() const 78 | { 79 | auto AB = _vertice[1] - _vertice[0]; 80 | auto AC = _vertice[2] - _vertice[0]; 81 | return glm::normalize(glm::cross(AB, AC)); 82 | } 83 | 84 | void Triangle::getVertice(glm::vec3& A, glm::vec3& B, glm::vec3 C) const 85 | { 86 | A = _vertice[0]; 87 | B = _vertice[1]; 88 | C = _vertice[2]; 89 | } 90 | 91 | float Triangle::rayCollision(const Ray& ray) const 92 | { 93 | auto plane = getPlane(); 94 | 95 | float t = plane.rayCollision(ray); 96 | if (t < -FLOAT_EPS) // no collision 97 | { 98 | return -1; 99 | } 100 | return inTriangle(ray.pointAtT(t)); 101 | } 102 | 103 | glm::vec3 Triangle::calNormal(const glm::vec3& p) const 104 | { 105 | return getNormal(); 106 | } 107 | 108 | // Sphere 109 | Sphere::Sphere(const glm::vec3& center, float radius) : _center(center), _radius(radius) 110 | { 111 | 112 | } 113 | 114 | bool Sphere::inSphere(const glm::vec3& p) const 115 | { 116 | return glm::distance(p, _center) < _radius + FLOAT_EPS; 117 | } 118 | 119 | float Sphere::rayCollision(const Ray& ray) const 120 | { 121 | glm::vec3 vc = ray.getVertex() - _center; 122 | 123 | float A = glm::dot(ray.getDirection(), ray.getDirection()); 124 | float B = 2 * glm::dot(vc, ray.getDirection()); 125 | float C = glm::dot(vc, vc) - _radius * _radius; 126 | if (abs(C) < FLOAT_EPS) 127 | { 128 | C = 0; 129 | } 130 | 131 | float delta = B * B - 4 * A * C; 132 | if (delta < FLOAT_EPS) 133 | { 134 | return -1; 135 | } 136 | delta = sqrt(delta); 137 | float t1 = (-B + delta) / 2 / A; 138 | float t2 = (-B - delta) / 2 / A; 139 | if (t1 < FLOAT_EPS && t2 < FLOAT_EPS) 140 | { 141 | return -1; 142 | } 143 | if (t2 > FLOAT_EPS) 144 | { 145 | return t2; 146 | } 147 | else 148 | { 149 | return t1; 150 | } 151 | } 152 | glm::vec3 Sphere::calNormal(const glm::vec3& p) const 153 | { 154 | return glm::normalize(p - _center); 155 | } 156 | bool Sphere::rayInEntity(const Ray& ray) const 157 | { 158 | return inSphere(ray.getVertex()) && rayCollision(ray) > FLOAT_EPS; 159 | } 160 | } -------------------------------------------------------------------------------- /Entity.h: -------------------------------------------------------------------------------- 1 | #ifndef RAY_TRACING_ENTITY_H 2 | #define RAY_TRACING_ENTITY_H 3 | 4 | #include "PhongShader.h" 5 | #include "Ray.h" 6 | 7 | namespace RayTracing 8 | { 9 | class Entity 10 | { 11 | public: 12 | virtual float rayCollision(const Ray& ray) const = 0; // return parameter t 13 | virtual glm::vec3 calNormal(const glm::vec3& p) const = 0; 14 | virtual bool rayInEntity(const Ray& ray) const = 0; 15 | void setMaterial(const Material& m) { _material = m; } 16 | const Material& getMaterial() const { return _material; } 17 | protected: 18 | Material _material; 19 | }; 20 | 21 | class Plane : public Entity 22 | { 23 | public: 24 | Plane(const glm::vec3& aPoint, const glm::vec3& normal); 25 | bool onPlane(const glm::vec3& p) const; 26 | glm::vec3 getNormal() const { return _normal; } 27 | glm::vec3 getAPoint() const { return _aPoint; } 28 | 29 | float rayCollision(const Ray& ray) const; 30 | glm::vec3 calNormal(const glm::vec3& p) const; 31 | bool rayInEntity(const Ray& ray) const { return false; } 32 | private: 33 | glm::vec3 _normal; 34 | glm::vec3 _aPoint; 35 | }; 36 | 37 | class Triangle : public Entity 38 | { 39 | public: 40 | Triangle(const glm::vec3& A, const glm::vec3& B, const glm::vec3& C); 41 | bool inTriangle(const glm::vec3& p) const; 42 | Plane getPlane() const; 43 | glm::vec3 getNormal() const; 44 | void getVertice(glm::vec3& A, glm::vec3& B, glm::vec3 C) const; 45 | 46 | float rayCollision(const Ray& ray) const; 47 | glm::vec3 calNormal(const glm::vec3& p) const; 48 | bool rayInEntity(const Ray& ray) const { return false; } 49 | private: 50 | glm::vec3 _vertice[3]; 51 | }; 52 | 53 | class Sphere : public Entity 54 | { 55 | public: 56 | Sphere(const glm::vec3& center, float radius); 57 | bool inSphere(const glm::vec3& p) const; 58 | glm::vec3 getCenter() const { return _center; } 59 | float getRadius() const { return _radius; } 60 | 61 | float rayCollision(const Ray& ray) const; 62 | glm::vec3 calNormal(const glm::vec3& p) const; 63 | bool rayInEntity(const Ray& ray) const; 64 | private: 65 | glm::vec3 _center; 66 | float _radius; 67 | }; 68 | } 69 | 70 | #endif -------------------------------------------------------------------------------- /PhongShader.cpp: -------------------------------------------------------------------------------- 1 | #include "PhongShader.h" 2 | 3 | DirLight::DirLight( 4 | glm::vec3 ambient, 5 | glm::vec3 diffuse, 6 | glm::vec3 specular, 7 | glm::vec3 direction) 8 | : _ambient(ambient), 9 | _diffuse(diffuse), 10 | _specular(specular), 11 | _direction(direction) 12 | { 13 | 14 | } 15 | 16 | glm::vec3 DirLight::calLight( 17 | const Material& material, 18 | const glm::vec3& fragPos, 19 | const glm::vec3& norm, 20 | const glm::vec3& viewDir) const 21 | { 22 | glm::vec3 ambient = _ambient * material.ambient(fragPos); 23 | 24 | glm::vec3 lightDir = normalize(-_direction); 25 | float diff = std::max(dot(norm, lightDir), 0.0f); 26 | glm::vec3 diffuse = diff * _diffuse * material.diffuse(fragPos); 27 | 28 | glm::vec3 middle = glm::normalize(-viewDir + lightDir); 29 | float spec = glm::pow(std::max(glm::dot(middle, norm), 0.0f), material.shininess(fragPos)); 30 | glm::vec3 specular = _specular * spec * material.specular(fragPos); 31 | 32 | return (ambient + diffuse + specular); 33 | } -------------------------------------------------------------------------------- /PhongShader.h: -------------------------------------------------------------------------------- 1 | #ifndef PHONG_SHADER_H 2 | #define PHONG_SHADER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | struct Material 11 | { 12 | std::function ambient; 13 | std::function diffuse; 14 | std::function specular; 15 | std::function shininess; 16 | 17 | float kShade; 18 | float kReflect; 19 | float kRefract; 20 | float refractiveIndex; 21 | }; 22 | 23 | class Light 24 | { 25 | public: 26 | virtual glm::vec3 calLight( 27 | const Material& material, 28 | const glm::vec3& fragPos, 29 | const glm::vec3& norm, 30 | const glm::vec3& viewDir) const = 0; 31 | private: 32 | }; 33 | 34 | class DirLight : public Light 35 | { 36 | public: 37 | DirLight( 38 | glm::vec3 ambient, 39 | glm::vec3 diffuse, 40 | glm::vec3 specular, 41 | glm::vec3 direction); 42 | glm::vec3 calLight( 43 | const Material& material, 44 | const glm::vec3& fragPos, 45 | const glm::vec3& norm, 46 | const glm::vec3& viewDir) const; 47 | private: 48 | glm::vec3 _ambient; 49 | glm::vec3 _diffuse; 50 | glm::vec3 _specular; 51 | glm::vec3 _direction; 52 | 53 | 54 | }; 55 | 56 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ray-Tracing-OpenGL 2 | A OpenGL implement of ray tracing running on GPU. 3 | 4 | To compile the project, you need to add some extra files: 5 | 6 | * Add `glad.c` to your project. 7 | * Add `glad`, `glfw`, `glm` to include path. 8 | * Add `opengl32.lib` , `glfw3.lib` to additional dependency. 9 | 10 | To learn more details about how to build the compiling environment, you can visit https://learnopengl.com/. -------------------------------------------------------------------------------- /Ray.cpp: -------------------------------------------------------------------------------- 1 | #include "Ray.h" 2 | 3 | namespace RayTracing 4 | { 5 | Ray::Ray(glm::vec3 src, glm::vec3 dest) : _vertex(src), _direction(glm::normalize(dest - src)) 6 | { 7 | 8 | } 9 | 10 | glm::vec3 Ray::pointAtT(float t) const 11 | { 12 | return _vertex + t * _direction; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Ray.h: -------------------------------------------------------------------------------- 1 | #ifndef RAY_TRACING_RAY_H 2 | #define RAY_TRACING_RAY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace RayTracing 9 | { 10 | static const float FLOAT_INF = 100000000.0f; 11 | static const float FLOAT_EPS = 1e-5; 12 | static const glm::vec3 NULL_POINT(FLOAT_INF, FLOAT_INF, FLOAT_INF); 13 | class Ray 14 | { 15 | public: 16 | Ray(glm::vec3 src, glm::vec3 dest); 17 | glm::vec3 pointAtT(float t) const; 18 | glm::vec3 getVertex() const { return _vertex; } 19 | glm::vec3 getDirection() const { return _direction; } 20 | private: 21 | glm::vec3 _vertex; 22 | glm::vec3 _direction; 23 | }; 24 | } 25 | 26 | #endif -------------------------------------------------------------------------------- /RayTracing.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SingleZombie/Ray-Tracing-OpenGL/8ab3745391c8c9dd9db3a262a59ab6c1bfd35164/RayTracing.cpp -------------------------------------------------------------------------------- /RayTracing.h: -------------------------------------------------------------------------------- 1 | #ifndef RAYTRACING_H 2 | #define RAYTRACING_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Entity.h" 8 | #include 9 | 10 | namespace RayTracing 11 | { 12 | class Scene 13 | { 14 | public: 15 | Scene(); 16 | ~Scene(); 17 | void addEntity(Entity* entity); 18 | void addLight(Light* light); 19 | glm::vec3 traceRay(const Ray& ray, unsigned int recursionTime = 0); 20 | std::pair getIntersection(const Ray& ray); 21 | glm::vec3 shade(const Entity& entity, glm::vec3 fragPos, const Ray& ray); 22 | 23 | static const unsigned int MAX_RECURSION_TIME; 24 | private: 25 | std::vector _entitys; 26 | std::vector _lights; 27 | }; 28 | } 29 | 30 | 31 | 32 | #endif -------------------------------------------------------------------------------- /Shader/Fragment: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | out vec4 FragColor; 4 | uniform vec3 vertexColor; 5 | 6 | void main() 7 | { 8 | FragColor = vec4(vertexColor, 1.0); 9 | } -------------------------------------------------------------------------------- /Shader/Shader.cpp: -------------------------------------------------------------------------------- 1 | #include "Shader.h" 2 | 3 | Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 4 | { 5 | std::string vertexCode; 6 | std::string fragmentCode; 7 | std::ifstream vShaderFile; 8 | std::ifstream fShaderFile; 9 | vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 10 | fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 11 | try 12 | { 13 | vShaderFile.open(vertexPath); 14 | fShaderFile.open(fragmentPath); 15 | std::stringstream vShaderStream, fShaderStream; 16 | vShaderStream << vShaderFile.rdbuf(); 17 | fShaderStream << fShaderFile.rdbuf(); 18 | vShaderFile.close(); 19 | fShaderFile.close(); 20 | vertexCode = vShaderStream.str(); 21 | fragmentCode = fShaderStream.str(); 22 | } 23 | catch (std::ifstream::failure e) 24 | { 25 | std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl; 26 | } 27 | const char* vShaderCode = vertexCode.c_str(); 28 | const char* fShaderCode = fragmentCode.c_str(); 29 | 30 | unsigned int vertex, fragment; 31 | int success; 32 | char infoLog[512]; 33 | 34 | vertex = glCreateShader(GL_VERTEX_SHADER); 35 | glShaderSource(vertex, 1, &vShaderCode, NULL); 36 | glCompileShader(vertex); 37 | glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 38 | if (!success) 39 | { 40 | glGetShaderInfoLog(vertex, 512, NULL, infoLog); 41 | std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; 42 | }; 43 | 44 | fragment = glCreateShader(GL_FRAGMENT_SHADER); 45 | glShaderSource(fragment, 1, &fShaderCode, NULL); 46 | glCompileShader(fragment); 47 | if (!success) 48 | { 49 | glGetShaderInfoLog(vertex, 512, NULL, infoLog); 50 | std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; 51 | }; 52 | _ID = glCreateProgram(); 53 | glAttachShader(_ID, vertex); 54 | glAttachShader(_ID, fragment); 55 | glLinkProgram(_ID); 56 | glGetProgramiv(_ID, GL_LINK_STATUS, &success); 57 | if (!success) { 58 | glGetProgramInfoLog(_ID, 512, NULL, infoLog); 59 | std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; 60 | } 61 | 62 | glDeleteShader(vertex); 63 | glDeleteShader(fragment); 64 | } 65 | 66 | void Shader::use() 67 | { 68 | glUseProgram(_ID); 69 | } 70 | 71 | void Shader::setBool(const std::string &name, bool value) const 72 | { 73 | glUniform1i(glGetUniformLocation(_ID, name.c_str()), (int)value); 74 | } 75 | void Shader::setInt(const std::string &name, int value) const 76 | { 77 | glUniform1i(glGetUniformLocation(_ID, name.c_str()), value); 78 | } 79 | void Shader::setFloat(const std::string &name, float value) const 80 | { 81 | glUniform1f(glGetUniformLocation(_ID, name.c_str()), value); 82 | } 83 | void Shader::setVec2(const std::string& name, const glm::vec2& value) const 84 | { 85 | glUniform2fv(glGetUniformLocation(_ID, name.c_str()), 1, glm::value_ptr(value)); 86 | } 87 | void Shader::setVec2(const std::string& name, float x, float y) const 88 | { 89 | glUniform2f(glGetUniformLocation(_ID, name.c_str()), x, y); 90 | } 91 | void Shader::setVec3(const std::string& name, const glm::vec3& value ) const 92 | { 93 | glUniform3fv(glGetUniformLocation(_ID, name.c_str()), 1, glm::value_ptr(value)); 94 | } 95 | void Shader::setVec3(const std::string& name, float x, float y, float z) const 96 | { 97 | glUniform3f(glGetUniformLocation(_ID, name.c_str()), x, y, z); 98 | } 99 | void Shader::setMatrix4(const std::string& name, const glm::mat4& value) const 100 | { 101 | glUniformMatrix4fv(glGetUniformLocation(_ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(value)); 102 | } -------------------------------------------------------------------------------- /Shader/Shader.h: -------------------------------------------------------------------------------- 1 | #ifndef SHADER_H 2 | #define SHADER_H 3 | 4 | #include "glad/glad.h" 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class Shader 15 | { 16 | public: 17 | unsigned int getID() { return _ID; } 18 | Shader(const GLchar* vertexPath, const GLchar* fragmentPath); 19 | void use(); 20 | void setBool(const std::string& name, bool value) const; 21 | void setInt(const std::string& name, int value) const; 22 | void setFloat(const std::string& name, float value) const; 23 | void setVec2(const std::string& name, const glm::vec2& value) const; 24 | void setVec2(const std::string& name, float x, float y) const; 25 | void setVec3(const std::string& name, const glm::vec3& value) const; 26 | void setVec3(const std::string& name, float x, float y, float z) const; 27 | void setMatrix4(const std::string& name, const glm::mat4& value) const; 28 | private: 29 | unsigned int _ID; 30 | }; 31 | 32 | #endif -------------------------------------------------------------------------------- /Shader/Vertex: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | uniform vec2 screenPos; 4 | 5 | void main() 6 | { 7 | gl_Position = vec4(screenPos, -1.0, 1.0); 8 | } 9 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SingleZombie/Ray-Tracing-OpenGL/8ab3745391c8c9dd9db3a262a59ab6c1bfd35164/main.cpp --------------------------------------------------------------------------------