Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Ascii Raymarcher(old)
#include <math.h>
#include <algorithm>
#include <string>
#include <immintrin.h>
using namespace std;typedef float R;
#define _W 79
#define _H 39
#define EP 0.01f
#define OP operator
#define C const
#define E return
#define PQ M*(3.1415f/180)
union J{__m128 V;J(__m128 V):V(V){}J(R X,R Y,R Z):X(X),Y(Y),Z(Z){}struct{R X,Y,Z;};R L()C{E _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(V,V,0x71)));}J N()C{E _mm_mul_ps(V,_mm_rsqrt_ps(_mm_dp_ps(V,V,0x7f)));}R D(C J& O)C{E _mm_cvtss_f32(_mm_dp_ps(V,O.V,0x71));}J A()C{E J{abs(X),abs(Y),abs(Z)};}J OP+(C J& O)C{E _mm_add_ps(V,O.V);}J OP-(C J& O)C{E _mm_sub_ps(V,O.V);}J OP*(C J& O)C{E _mm_mul_ps(V,O.V);}J OP/(C J& O)C{E _mm_div_ps(V,O.V);}J OP+(C R& O)C{E _mm_add_ps(V,_mm_set1_ps(O));}J OP-(C R& O)C{E _mm_sub_ps(V,_mm_set1_ps(O));}J OP*(C R& O)C{E J{_mm_mul_ps(V,_mm_set1_ps(O))};}};R BX(C J& P,J B){J D=P.A()-B;E min(max(D.X,max(D.Y, D.Z)),.0f)+J{max(D.X,.0f),max(D.Y,.0f),max(D.Z,0.0f)}.L();}R RB(C J& P,J B,R R){E BX(P,B)-R;}J RY(C J& P,R A){E J{P.Z*sin(A)+P.X*cos(A),P.Y,P.Z*cos(A)-P.X*sin(A),};}J RZ(C J& P,R A){E J{P.X*cos(A)-P.Y*sin(A),P.X*sin(A)+P.Y*cos(A),P.Z,};}static size_t M=0;R Q(C J& P){R D=P.Y+2;D=min(D,RB(RY(RZ(P,PQ),PQ),J{2,2,2},0.5f));E D;}J Nor(C J& P){E J{Q(P+J{EP,0,0})-Q(P-J{EP,0,0}),Q(P+J{0,EP,0})-Q(P-J{0,EP,0}),Q(P+J{0,0,EP})-Q(P-J{0,0,EP}),}.N();}R Y(C J& O,C J& D,bool* H){R T=0;for(size_t i=0;i<128;i++){R Y=Q(O+(D*T));if(Y<EP){*H=1;break;}T+=Y;}E T;}R B(C J& O,C J& D,R U,R I,R K){R S=1;for(R t=U;t<I;){R di=Q(O+D*t);if(di<EP){E 0;}S=min(S,K*di/t);t+=di;}E S;}int main(){J LD=J{0.5,1,0.25}.N();J G=J{0,1,-8};string S;S.reserve(_W*_H);do{M++;for(size_t y=0;y<_H;y++){for(size_t x=0;x<_W;x++){J K(x,y,1);K=K/J(_W,_H,1);K=(K*2.0)-1;K.Y=-K.Y;K.X*=_W/_H;K.Z=R(1/0.726);K=K.N();bool H=0;R Z=Y(G,K,&H);J P=G+(K*Z);if(H){J N=Nor(P);R D=N.D(LD);D*=0.5;D+=0.5;D*=D;D*=B(P,LD,R(0.5),10,10);S+=".:*oe$&#%@"[static_cast<size_t>(D*10)];}else{S+=' ';}}S+="\n";}printf("%s",S.c_str());S.clear();}while(M<360);E 0;}
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <algorithm>
#include <string>
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#include <fstream>
void CaptureScreen(HWND Window, const char* filename)
{
RECT WindowBounds;
GetWindowRect(Window, &WindowBounds);
int Width = WindowBounds.right - WindowBounds.left;
int Height = WindowBounds.bottom - WindowBounds.top;
std::ofstream fOut(filename, std::ios::binary);
if( !fOut ) return;
BITMAPFILEHEADER BmpHeader;
BITMAPINFOHEADER InfoHeader;
BmpHeader.bfType = 0x4d42;
BmpHeader.bfSize = 0;
BmpHeader.bfReserved1 = 0;
BmpHeader.bfReserved2 = 0;
BmpHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
InfoHeader.biSize = sizeof(InfoHeader);
InfoHeader.biWidth = Width;
InfoHeader.biHeight = Height;
InfoHeader.biPlanes = 1;
InfoHeader.biBitCount = 24;
InfoHeader.biCompression = BI_RGB;
InfoHeader.biSizeImage = 0;
InfoHeader.biXPelsPerMeter = 0;
InfoHeader.biYPelsPerMeter = 0;
InfoHeader.biClrUsed = 0;
InfoHeader.biClrImportant = 0;
fOut.write((char*)&BmpHeader, sizeof(BmpHeader));
fOut.write((char*)&InfoHeader, sizeof(InfoHeader));
BITMAPINFO BmpInfo;
BmpInfo.bmiHeader = InfoHeader;
HDC winDC = GetWindowDC(Window);
HDC memDC = CreateCompatibleDC(winDC);
BYTE* Buffer = 0;
HBITMAP ImageDC = CreateDIBSection(winDC, &BmpInfo, DIB_RGB_COLORS, (void**)&Buffer, 0, 0);
SelectObject(memDC, ImageDC);
BitBlt(memDC, 0, 0, Width, Height, winDC, 0, 0, SRCCOPY);
DeleteDC(memDC);
ReleaseDC(Window, winDC);
size_t Size = (((24 * Width + 31) & (~31)) / 8)*Height;
fOut.write((const char*)Buffer, Size);
DeleteObject(ImageDC);
}
#endif
typedef float Real;
#define USE_SSE
#ifdef USE_SSE
#include <pmmintrin.h>
// Simd Modulo
inline __m128 _mm_mod_ps2(const __m128& A, const __m128& Divisor)
{
__m128 C = _mm_div_ps(A, Divisor);
__m128i I = _mm_cvttps_epi32(C);
__m128 Trunc = _mm_cvtepi32_ps(I);
__m128 Base = _mm_mul_ps(Trunc, Divisor);
__m128 Remainder = _mm_sub_ps(A, Base);
return Remainder;
}
#endif
union Vec3
{
#ifdef USE_SSE
__m128 SimdReals;
Vec3(__m128 Vec)
:
SimdReals(Vec)
{
}
#endif
Vec3(Real X, Real Y, Real Z)
:
X(X), Y(Y), Z(Z)
{
}
Real Reals[3];
struct
{
Real X, Y, Z;
};
Real Length() const
{
#ifdef USE_SSE
return static_cast<Real>(
_mm_cvtss_f32(
_mm_sqrt_ss(
_mm_dp_ps(SimdReals, SimdReals, 0x71)
)
)
);
#else
return static_cast<Real>(
sqrt(X*X + Y*Y + Z*Z)
);
#endif
}
Vec3 Normalized() const
{
#ifdef USE_SSE
return Vec3{ _mm_mul_ps(
this->SimdReals, _mm_rsqrt_ps(
_mm_dp_ps(this->SimdReals, this->SimdReals, 0x7f)
)
)
};
#else
const Real Len = Length();
return (*this) / Len;
#endif
}
Real Dot(const Vec3& Other) const
{
#ifdef USE_SSE
return static_cast<Real>(
_mm_cvtss_f32(
_mm_dp_ps(SimdReals, Other.SimdReals, 0x71)
)
);
#else
return X * Other.X + Y * Other.Y + Z * Other.Z;
#endif
}
Vec3 Abs() const
{
return Vec3{
abs(X),
abs(Y),
abs(Z)
};
}
Vec3 operator + (const Vec3& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_add_ps(SimdReals, Other.SimdReals)
};
#else
return Vec3{
X + Other.X,
Y + Other.Y,
Z + Other.Z
};
#endif
}
Vec3 operator - (const Vec3& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_sub_ps(SimdReals,Other.SimdReals)
};
#else
return Vec3{
X - Other.X,
Y - Other.Y,
Z - Other.Z
};
#endif
}
Vec3 operator * (const Vec3& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_mul_ps(SimdReals,Other.SimdReals)
};
#else
return Vec3{
X * Other.X,
Y * Other.Y,
Z * Other.Z
};
#endif
}
Vec3 operator / (const Vec3& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_div_ps(SimdReals,Other.SimdReals)
};
#else
return Vec3{
X / Other.X,
Y / Other.Y,
Z / Other.Z
};
#endif
}
Vec3 operator % (const Vec3& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_mod_ps2(SimdReals,Other.SimdReals)
};
#else
return Vec3{
fmod(X,Other.X),
fmod(Y,Other.Y),
fmod(Z,Other.Z)
};
#endif
}
Vec3 operator + (const Real& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_add_ps(SimdReals,_mm_set1_ps(Other))
};
#else
return Vec3{
X + Other,
Y + Other,
Z + Other
};
#endif
}
Vec3 operator - (const Real& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_sub_ps(SimdReals,_mm_set1_ps(Other))
};
#else
return Vec3{
X - Other,
Y - Other,
Z - Other
};
#endif
}
Vec3 operator * (const Real& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_mul_ps(SimdReals,_mm_set1_ps(Other))
};
#else
return Vec3{
X * Other,
Y * Other,
Z * Other
};
#endif
}
Vec3 operator / (const Real& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_div_ps(SimdReals,_mm_set1_ps(Other))
};
#else
return Vec3{
X / Other,
Y / Other,
Z / Other
};
#endif
}
Vec3 operator % (const Real& Other) const
{
#ifdef USE_SSE
return Vec3{
_mm_mod_ps2(SimdReals,_mm_set1_ps(Other))
};
#else
return Vec3{
fmod(X,Other),
fmod(Y , Other),
fmod(Z , Other)
};
#endif
}
};
namespace Shapes
{
Real Plane(const Vec3& Position, const Vec3& Normal)
{
return Position.Dot(Normal.Normalized());
}
Real Sphere(const Vec3& Position, Real Radius)
{
return Position.Length() - Radius;
}
Real Box(const Vec3& Position, Vec3 Bounds)
{
Vec3 Dist = Position.Abs() - Bounds;
return std::min<Real>(std::max(Dist.X, std::max<Real>(Dist.Y, Dist.Z)), 0.0) +
Vec3{ std::max<Real>(Dist.X,0.0),
std::max<Real>(Dist.Y,0.0),
std::max<Real>(Dist.Z,0.0) }.Length();
}
Real RoundBox(const Vec3& Position, Vec3 Bounds, Real Radius)
{
return Box(Position, Bounds) - Radius;
}
Real Capsule(const Vec3& Position, Vec3 A, Vec3 B, Real Radius)
{
Vec3 Pa = Position - A;
Vec3 Ba = B - A;
Real H = (Pa.Dot(Ba) / Ba.Dot(Ba));
H = std::min<Real>(0, std::max<Real>(1.0, H));
return (Pa - (Ba*H)).Length() - Radius;
}
Real Torus(const Vec3& Position, Real InRadius, Real OutRadius)
{
Vec3 Q{ Vec3{ Position.X,Position.Z,0 }.Length() - OutRadius,Position.Y,0 };
return Q.Length() - InRadius;
}
}
namespace Operations
{
Real Clamp(Real A, Real Min, Real Max)
{
const Real T = A < Min ? Min : A;
return T > Max ? Max : T;
}
Real Lerp(Real A, Real B, Real T)
{
return std::fma(T, B, std::fma(-T, A, A));
}
Real Union(Real A, Real B)
{
return std::min(A, B);
}
Real SmoothUnion(Real A, Real B, Real K = 1)
{
/*
Power Smooth
A = std::pow(A, K);
B = std::pow(B, K);
return std::pow((A*B) / (A + B), Real(1) / K);
*/
Real H = Clamp(Real(0.5) + Real(0.5)*(B - A) / K, 0, 1);
return Lerp(B, A, H) - (K*H*(Real(1.0) - H));
}
Real Intersection(Real A, Real B)
{
return std::max(A, B);
}
Real Subtract(Real A, Real B)
{
return Intersection(-A, B);
}
}
namespace Translate
{
const static Real Pi(static_cast<Real>(3.1415926535897932384626433));
Vec3 RotX(const Vec3& Position, Real Angle)
{
Angle *= Pi / Real(180);
return Vec3{
Position.X,
Position.Y * cos(Angle) - Position.Z * sin(Angle),
Position.Y * sin(Angle) + Position.Z * cos(Angle),
};
}
Vec3 RotY(const Vec3& Position, Real Angle)
{
Angle *= Pi / Real(180);
return Vec3{
Position.Z * sin(Angle) + Position.X * cos(Angle),
Position.Y,
Position.Z * cos(Angle) - Position.X * sin(Angle),
};
}
Vec3 RotZ(const Vec3& Position, Real Angle)
{
Angle *= Pi / Real(180);
return Vec3{
Position.X * cos(Angle) - Position.Y * sin(Angle),
Position.X * sin(Angle) + Position.Y * cos(Angle),
Position.Z,
};
}
Vec3 Repeat(const Vec3& Position, const Vec3& Bounds)
{
return (Position % Bounds) - (Bounds*Real(0.5));
}
Vec3 RepeatGround(const Vec3& Position, const Vec3& Bounds)
{
Vec3 Rep{ Position };
Rep.X = std::remainder(Rep.X, Bounds.X) - (Bounds.X * Real(0.5));
Rep.Z = std::remainder(Rep.Z, Bounds.Z) - (Bounds.Z * Real(0.5));
return Rep;
}
}
#define WIDTH (79)
#define HEIGHT (39)
#define PREC 0.002
static size_t Tick = 0;
//// SCENE
Real Scene(const Vec3& Point)
{
Real Distance = 0;
Distance = Shapes::Plane(Point, Vec3{ 0,1,0 });
Distance = Operations::Union(
Distance,
Shapes::RoundBox(
Translate::RotZ(
Point - Vec3{ -5,2,5 }, Real(15 + Tick * 15)
),
Vec3{ 1,2,1 }, 0.525f)
);
Distance = Operations::Union(
Distance,
Shapes::Capsule(Point,
Vec3{ 5,5,6 },
Vec3{ -5,5,6 },
Real(3.75)
));
Distance = Operations::SmoothUnion(
Distance,
Shapes::Torus(
Translate::RotX(Point - Vec3{ 0,Real(0.5),12 }, 45),
Real(0.5), Real(7)
), 3
);
for( size_t i = 1; i < 5; i++ )
{
Distance = Operations::SmoothUnion(
Distance,
Shapes::Torus(
Translate::RotZ(
Translate::RotX(Point - Vec3{ 0,Real(0.5),Real(12 + i * 7) }, 85), Real(i * 30 + (Tick * 5))
),
Real(1), Real(6)
), 3);
}
return Distance;
}
Vec3 CalcNormal(const Vec3& Point)
{
#define EPSILON static_cast<Real>(0.001)
return Vec3{
Scene(Point + Vec3{ EPSILON,0,0 }) - Scene(Point - Vec3{ EPSILON,0,0 }),
Scene(Point + Vec3{ 0,EPSILON,0 }) - Scene(Point - Vec3{ 0,EPSILON,0 }),
Scene(Point + Vec3{ 0,0,EPSILON }) - Scene(Point - Vec3{ 0,0,EPSILON }),
}.Normalized();
}
Real March(const Vec3& Origin, const Vec3& Ray, bool* Hit)
{
Real Distance = 0;
for( size_t i = 0; i < 128; i++ )
{
Real ClosestSurface = Scene(Origin + (Ray * Distance));
if( ClosestSurface < PREC )
{
// "Hit" a surface
if( Hit != nullptr )
{
*Hit = true;
}
break;
}
Distance += ClosestSurface * Real(0.75);
}
return Distance;
}
Real Shadow(const Vec3& LightPos, const Vec3& LightDir, Real Min, Real Max, Real K)
{
Real Res = 1;
for( Real t = Min; t < Max;)
{
Real Distance = Scene(LightPos + LightDir*t);
if( Distance < PREC )
{
return 0.0;
}
Res = std::min(Res, K*Distance / t);
t += Distance;
}
return Res;
}
const char Shades[] = ".:*oe&#%@";
int main()
{
Vec3 LightDir = Vec3{ 1,1,1 }.Normalized();
Vec3 EyePos = Vec3{ 0,2,-6 };
std::string Screen;
Screen.reserve(WIDTH * HEIGHT);
do
{
EyePos.Z += Real(0.25);
Tick++;
for( size_t y = 0; y < HEIGHT; y++ )
{
for( size_t x = 0; x < WIDTH; x++ )
{
Vec3 UV{
static_cast<Real>(x),
static_cast<Real>(y),
1 };
UV = UV / Vec3{
WIDTH,
HEIGHT,
1 };
// Recanonicalize [-1,1]
UV = (UV * 2.0) - 1.0;
// Flip Y axis
UV.Y *= Real(-1);
// Aspect Ratio Correction
UV.X *= WIDTH / HEIGHT;
//UV.X *= 0.75;
/* Fov
15deg bisec = tan((pi/12)/2) = 30 degrees fov = 0.1316524975873958
30deg bisec = tan((pi/6)/2) = 60 degrees fov = 0.26794919243112270
36deg bisec = tan(((2pi)/5)/2) = 72 degrees fov = 0.7265425280053608858
45dec bisec = tan((pi/2)/2) = 90 degrees fov = 1
*/
UV.Z = Real(1 / 0.7265425280053608858);
UV = UV.Normalized();
bool Hit = false;
Real Distance = March(EyePos, UV, &Hit);
Vec3 Point = EyePos + (UV * Distance);
if( Hit )
{
Vec3 Normal = CalcNormal(Point);
Real Diffuse = Normal.Dot(LightDir);
Diffuse *= 0.5;
Diffuse += 0.5;
Diffuse *= Diffuse;
Diffuse *= Shadow(Point, LightDir, Real(0.5), 10, 10);
Screen += Shades[static_cast<size_t>(Diffuse*(sizeof(Shades) - 2))];
}
else
{
Screen += ' ';
}
}
Screen += "\n";
}
printf("%s", Screen.c_str());
#ifdef _WIN32
//CaptureScreen(GetForegroundWindow(), (std::to_string(Tick) + ".bmp").c_str());
#endif
Screen.clear();
} while( Tick < 300 );
return 0;
}
@DadKeats

This comment has been minimized.

Copy link

@DadKeats DadKeats commented Dec 30, 2015

so cool

@bonnieking

This comment has been minimized.

Copy link

@bonnieking bonnieking commented Dec 30, 2015

Awesome!

@sumantsk

This comment has been minimized.

Copy link

@sumantsk sumantsk commented Dec 30, 2015

awesome

@Vafilor

This comment has been minimized.

Copy link

@Vafilor Vafilor commented Dec 30, 2015

Daaang. Very cool.

@morontt

This comment has been minimized.

Copy link

@morontt morontt commented Jan 17, 2016

Super!

@selfdeceited

This comment has been minimized.

Copy link

@selfdeceited selfdeceited commented Feb 19, 2016

nice!

@petercunha

This comment has been minimized.

Copy link

@petercunha petercunha commented Dec 10, 2017

Just saw your video. This is incredible!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment