├── ConsoleRayTracing.cpp ├── LICENSE ├── README.md ├── Vec2.h ├── Vec3.h ├── VecFunctions.h └── console3d.png /ConsoleRayTracing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "VecFunctions.h" 6 | 7 | void SetWindow(int Width, int Height) 8 | { 9 | _COORD coord; 10 | coord.X = Width; 11 | coord.Y = Height; 12 | _SMALL_RECT Rect; 13 | Rect.Top = 0; 14 | Rect.Left = 0; 15 | Rect.Bottom = Height - 1; 16 | Rect.Right = Width - 1; 17 | HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); 18 | SetConsoleScreenBufferSize(Handle, coord); 19 | SetConsoleWindowInfo(Handle, TRUE, &Rect); 20 | } 21 | 22 | int main() { 23 | int width = 120 * 2; 24 | int height = 30 * 2; 25 | SetWindow(width, height); 26 | float aspect = (float)width / height; 27 | float pixelAspect = 11.0f / 24.0f; 28 | char gradient[] = " .:!/r(l1Z4H9W8$@"; 29 | int gradientSize = std::size(gradient) - 2; 30 | 31 | wchar_t* screen = new wchar_t[width * height]; 32 | HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL); 33 | SetConsoleActiveScreenBuffer(hConsole); 34 | DWORD dwBytesWritten = 0; 35 | 36 | for (int t = 0; t < 10000; t++) { 37 | vec3 light = norm(vec3(-0.5, 0.5, -1.0)); 38 | vec3 spherePos = vec3(0, 3, 0); 39 | for (int i = 0; i < width; i++) { 40 | for (int j = 0; j < height; j++) { 41 | vec2 uv = vec2(i, j) / vec2(width, height) * 2.0f - 1.0f; 42 | uv.x *= aspect * pixelAspect; 43 | vec3 ro = vec3(-6, 0, 0); 44 | vec3 rd = norm(vec3(2, uv)); 45 | ro = rotateY(ro, 0.25); 46 | rd = rotateY(rd, 0.25); 47 | ro = rotateZ(ro, t * 0.01); 48 | rd = rotateZ(rd, t * 0.01); 49 | float diff = 1; 50 | for (int k = 0; k < 5; k++) { 51 | float minIt = 99999; 52 | vec2 intersection = sphere(ro - spherePos, rd, 1); 53 | vec3 n = 0; 54 | float albedo = 1; 55 | if (intersection.x > 0) { 56 | vec3 itPoint = ro - spherePos + rd * intersection.x; 57 | minIt = intersection.x; 58 | n = norm(itPoint); 59 | } 60 | vec3 boxN = 0; 61 | intersection = box(ro, rd, 1, boxN); 62 | if (intersection.x > 0 && intersection.x < minIt) { 63 | minIt = intersection.x; 64 | n = boxN; 65 | } 66 | intersection = plane(ro, rd, vec3(0, 0, -1), 1); 67 | if (intersection.x > 0 && intersection.x < minIt) { 68 | minIt = intersection.x; 69 | n = vec3(0, 0, -1); 70 | albedo = 0.5; 71 | } 72 | if (minIt < 99999) { 73 | diff *= (dot(n, light) * 0.5 + 0.5) * albedo; 74 | ro = ro + rd * (minIt - 0.01); 75 | rd = reflect(rd, n); 76 | } 77 | else break; 78 | } 79 | int color = (int)(diff * 20); 80 | color = clamp(color, 0, gradientSize); 81 | char pixel = gradient[color]; 82 | screen[i + j * width] = pixel; 83 | } 84 | } 85 | screen[width * height - 1] = '\0'; 86 | WriteConsoleOutputCharacter(hConsole, screen, width * height, { 0, 0 }, &dwBytesWritten); 87 | } 88 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Artem Yashin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Console3D 2 | 3 | ![](https://raw.githubusercontent.com/ArtemOnigiri/Console3D/main/console3d.png) 4 | -------------------------------------------------------------------------------- /Vec2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct vec2 4 | { 5 | float x, y; 6 | 7 | vec2(float value) : x(value), y(value) {} 8 | vec2(float _x, float _y) : x(_x), y(_y) {} 9 | 10 | vec2 operator+(vec2 const& other) { return vec2(x + other.x, y + other.y); } 11 | vec2 operator-(vec2 const& other) { return vec2(x - other.x, y - other.y); } 12 | vec2 operator*(vec2 const& other) { return vec2(x * other.x, y * other.y); } 13 | vec2 operator/(vec2 const& other) { return vec2(x / other.x, y / other.y); } 14 | }; -------------------------------------------------------------------------------- /Vec3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Vec2.h" 3 | 4 | struct vec3 5 | { 6 | float x, y, z; 7 | 8 | vec3(float _value) : x(_value), y(_value), z(_value) {}; 9 | vec3(float _x, vec2 const& v) : x(_x), y(v.x), z(v.y) {}; 10 | vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; 11 | 12 | vec3 operator+(vec3 const& other) { return vec3(x + other.x, y + other.y, z + other.z); } 13 | vec3 operator-(vec3 const& other) { return vec3(x - other.x, y - other.y, z - other.z); } 14 | vec3 operator*(vec3 const& other) { return vec3(x * other.x, y * other.y, z * other.z); } 15 | vec3 operator/(vec3 const& other) { return vec3(x / other.x, y / other.y, z / other.z); } 16 | vec3 operator-() { return vec3(-x, -y, -z); } 17 | 18 | }; -------------------------------------------------------------------------------- /VecFunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Vec2.h" 4 | #include "Vec3.h" 5 | 6 | float clamp(float value, float min, float max) { return fmax(fmin(value, max), min); } 7 | double sign(double a) { return (0 < a) - (a < 0); } 8 | double step(double edge, double x) { return x > edge; } 9 | 10 | float length(vec2 const& v) { return sqrt(v.x * v.x + v.y * v.y); } 11 | 12 | float length(vec3 const& v) { return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } 13 | vec3 norm(vec3 v) { return v / length(v); } 14 | float dot(vec3 const& a, vec3 const& b) { return a.x * b.x + a.y * b.y + a.z * b.z; } 15 | vec3 abs(vec3 const& v) { return vec3(fabs(v.x), fabs(v.y), fabs(v.z)); } 16 | vec3 sign(vec3 const& v) { return vec3(sign(v.x), sign(v.y), sign(v.z)); } 17 | vec3 step(vec3 const& edge, vec3 v) { return vec3(step(edge.x, v.x), step(edge.y, v.y), step(edge.z, v.z)); } 18 | vec3 reflect(vec3 rd, vec3 n) { return rd - n * (2 * dot(n, rd)); } 19 | 20 | vec3 rotateX(vec3 a, double angle) 21 | { 22 | vec3 b = a; 23 | b.z = a.z * cos(angle) - a.y * sin(angle); 24 | b.y = a.z * sin(angle) + a.y * cos(angle); 25 | return b; 26 | } 27 | 28 | vec3 rotateY(vec3 a, double angle) 29 | { 30 | vec3 b = a; 31 | b.x = a.x * cos(angle) - a.z * sin(angle); 32 | b.z = a.x * sin(angle) + a.z * cos(angle); 33 | return b; 34 | } 35 | 36 | vec3 rotateZ(vec3 a, double angle) 37 | { 38 | vec3 b = a; 39 | b.x = a.x * cos(angle) - a.y * sin(angle); 40 | b.y = a.x * sin(angle) + a.y * cos(angle); 41 | return b; 42 | } 43 | 44 | vec2 sphere(vec3 ro, vec3 rd, float r) { 45 | float b = dot(ro, rd); 46 | float c = dot(ro, ro) - r * r; 47 | float h = b * b - c; 48 | if (h < 0.0) return vec2(-1.0); 49 | h = sqrt(h); 50 | return vec2(-b - h, -b + h); 51 | } 52 | 53 | vec2 box(vec3 ro, vec3 rd, vec3 boxSize, vec3& outNormal) { 54 | vec3 m = vec3(1.0) / rd; 55 | vec3 n = m * ro; 56 | vec3 k = abs(m) * boxSize; 57 | vec3 t1 = -n - k; 58 | vec3 t2 = -n + k; 59 | float tN = fmax(fmax(t1.x, t1.y), t1.z); 60 | float tF = fmin(fmin(t2.x, t2.y), t2.z); 61 | if (tN > tF || tF < 0.0) return vec2(-1.0); 62 | vec3 yzx = vec3(t1.y, t1.z, t1.x); 63 | vec3 zxy = vec3(t1.z, t1.x, t1.y); 64 | outNormal = -sign(rd) * step(yzx, t1) * step(zxy, t1); 65 | return vec2(tN, tF); 66 | } 67 | 68 | float plane(vec3 ro, vec3 rd, vec3 p, float w) { 69 | return -(dot(ro, p) + w) / dot(rd, p); 70 | } -------------------------------------------------------------------------------- /console3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArtemOnigiri/Console3D/9ce7d5790d6ccb9b4646815edfccbb49eaf79a92/console3d.png --------------------------------------------------------------------------------