Skip to content

Latest commit

 

History

History
208 lines (168 loc) · 4.37 KB

README.md

File metadata and controls

208 lines (168 loc) · 4.37 KB

Ray Tracing

기본적으로 레이 트레이싱이란, 현실에서 일어나는 빛의 반사, 굴절 등을 시뮬레이션 하는 기술이다. 실세계의 태양으로 부터 발산되는 빛의 반사는 컴퓨터로 시뮬레이션 하기에 너무 복잡하며 거의 불가능에 가깝다.

컴퓨터는 이를 해결하기 위해 시야로 부터 빛을 쏴서 역으로 추적하는 방식을 사용한다. 더욱 사실적인 묘사를 하기 위해선 레이 트레이싱의 차원이나 깊이를 늘려서 더욱 정교한 렌더링을 할 수 있다. (ex 물의 굴절을 추가적으로 계산하거나 반사의 반사을 어디까지 할 것인가 등)

Ray Tracing 코드

실제 과정을 흉내낸 코드에 불과합니다.

#version 330

in vec3 N3; 
in vec3 L3; 
in vec3 V3; 
in vec3 wV;
in vec3 wP;
in vec3 wN;

out vec4 fColor;

struct Material {
	vec4  k_d;
	vec4  k_s;
	float n;
};

struct Sphere {
	vec4     center;
	float    radius;
	Material mtl;
};

struct Ray {
	vec3 pos;
	vec3 dir;
};

struct HitInfo {
	float    t;
	vec4     position;
	vec3     normal;
	Material mtl;
};

uniform mat4 uModelMat; 
uniform mat4 uViewMat; 
uniform mat4 uProjMat; 
uniform vec4 uLPos; 
uniform vec4 uLIntensity;
uniform vec4 uAmb; 
uniform vec4 uDif; 
uniform vec4 uSpc; 
uniform float uShininess; 
uniform samplerCube uCube;
uniform vec4 uEPos;
uniform int uNumSphere;
uniform Sphere uSpheres[20];
uniform int uBounceLimit;
uniform int uDrawingMode;

bool IntersectRay( inout HitInfo hit, Ray ray );

vec4 Shade( Material mtl, vec4 position, vec3 normal, vec3 view )
{
	HitInfo hit; 
	Ray r;

	vec4 color = vec4(0,0,0,1);
	r.pos = position.xyz;
	r.dir = (uLPos - position).xyz;

	if(IntersectRay(hit, r))
	{
		color += mtl.k_d * 0.01;
	}
	else
	{
		vec3 N = normalize(normal).xyz;
		vec3 L = normalize(uLPos - position).xyz;
		float NL = max(dot(N, L), 0);

		color += (mtl.k_d * NL) * uLIntensity;	// change this line
	}

	return color;
}

bool IntersectRay( inout HitInfo hit, Ray ray )
{
	hit.t = 1e30;
	bool foundHit = false;

	for ( int i=0; i<uNumSphere; ++i ) 
	{
		Sphere sphere = uSpheres[i];

		float a = dot(ray.dir, ray.dir);
		float b = dot(ray.pos - sphere.center.xyz, ray.dir);
		float c = dot(ray.pos - sphere.center.xyz, ray.pos - sphere.center.xyz) - sphere.radius * sphere.radius;
		float discriminant = b*b - a*c;
		if(discriminant < 0)
			continue ;
		
		float t = (-b - sqrt(discriminant)) / a;
		if(t < hit.t && t > 0)
		{
			foundHit = true;
			hit.t = t;
			hit.position = vec4((ray.pos + t*ray.dir), 1);
			hit.normal = normalize(hit.position - sphere.center).xyz;
			hit.mtl = sphere.mtl;
		}
	}

	return foundHit;
}

vec4 RayTracer( Ray ray )
{
	HitInfo hit;

	if ( IntersectRay( hit, ray ) ) 
	{
		vec3 view = normalize( ray.dir );
		vec4 clr = Shade( hit.mtl, hit.position, vec3(hit.normal), vec3(view));

		vec4 k_s = hit.mtl.k_s;
		for ( int bounce=0; bounce<uBounceLimit; bounce++ ) 
		{
			if ( hit.mtl.k_s.r + hit.mtl.k_s.g + hit.mtl.k_s.b <= 0.0 )
			{
				break;
			}

			Ray r;
			HitInfo h;

			r.pos = hit.position.xyz;
			r.dir = normalize(reflect(view, hit.normal)).xyz;
			
			if ( IntersectRay( h, r ) ) 
			{
				clr += k_s * Shade(h.mtl, h.position, vec3(h.normal), vec3(r.dir));
				hit = h;
				view = r.dir;
				k_s *= h.mtl.k_s;
			} 
			else 
			{
				clr += k_s * texture(uCube, vec3(1,-1,1)*r.dir);
				break;
			}
		}

		return clr;
	} 
	else 
	{
		return texture(uCube, vec3(1,-1,1)*ray.dir);
	}
}

void main()
{
	if(uDrawingMode == 0) 
	{
		vec3 N = normalize(N3); 
		vec3 L = normalize(L3); 
		vec3 V = normalize(V3); 
		vec3 H = normalize(V+L); 

		float NL = max(dot(N, L), 0); 
		float VR = pow(max(dot(H, N), 0), uShininess); 

		fColor = uAmb + uLIntensity*uDif*NL + uLIntensity*uSpc*VR; 
		fColor.w = 1; 

		vec3 viewDir = wP - wV;
		vec3 dir = reflect(viewDir, wN);

		fColor += uSpc*texture(uCube, vec3(1,-1,1)*dir);
	}
	else if(uDrawingMode == 1)
	{
		Ray r;
		r.pos = wV;
		r.dir = normalize(wP - wV);

		vec3 N = normalize(N3);
		vec3 L = normalize(L3);
		vec3 V = normalize(V3);
		vec3 H = normalize(V+L);
		float NL = max(dot(N, L), 0);
		float VR = pow(max(dot(H, N), 0), uShininess);
		fColor = uLIntensity * uSpc * VR;
		fColor += RayTracer (r);
	}
}