圖形學基礎 | 一個簡單光線追蹤渲染器

一個簡單光線追蹤渲染器

簡單的介紹可以參考:圖形學基礎 | 光線追蹤

qjh5606/RayTracer

在這裏插入圖片描述

單獨看一個像素上的追蹤過程的話:

  1. 從視線方向發射一條射線;
  2. 取得射線與場景最近的交點;
  3. 取得交點的材質顏色;
  4. 如果材質包含反射或折射,則改變光線的方向;
  5. 尋找下一個交點.並重復(2). 直到在場景內找不到交點.或者達到達到最大跟蹤次數.
  6. 對於(2). 因爲需要遍歷場景. 開銷隨場景複雜度上升而上升.

對於一些簡單的示例場景中, 可以簡化爲 射線和球. 或者射線與平面的相交. 求最近的交點.

以下是實現代碼的幾個問題

光線投射

在這裏插入圖片描述
對像素空間的每一點,變換到世界座標系中.
發射一條光線,對光線進行跟蹤.

float aspect = width / (float)height; // 防止失真
	for (size_t j = 0; j < height; j++) {
		for (size_t i = 0; i < width; i++) {
			// 將像素位置轉換成爲真實世界座標位置
			/*
				(i+0.5) 像素偏移量
				+(i+0.5)/(width/2.0)* tan(fov / 2.)*aspect 世界座標系偏移量
				起始世界座標 - 1*tan(fov / 2.)*aspect
			*/
			float x = (2* (i + 0.5) / (float)width - 1)*tan(fov / 2.)*aspect;
			float y = -(2 * (j + 0.5) / (float)height - 1)*tan(fov / 2.);
			// 發出的光線方向
			Vec3f dir = Vec3f(x, y, -1).normalize(); 
			framebuffer[i + j*width] = cast_ray(Vec3f(0, 0, 0), dir, spheres,lights);
		}
	}

射線與球的相交

參考之前的博客 射線與球的相交
在這裏插入圖片描述

反射光向量求解

幾何向量:計算光線反射reflect向量

折射光向量refract的計算

折射光向量refract的計算

如何產生陰影

就是求出射線與物體的交點之後.
求解出 交點與 光源i 之間的 射線 light_dir
light_dir 進行跟蹤.
從交點出發,看看能不能找到與它相交的物體.
如果可以,那麼就是處於 該光源i的陰影處. 不應該進行光照計算.

// 應用光照
	float diffuse_light_intensity = 0, specular_light_intensity = 0;
	for (size_t i = 0; i < lights.size(); i++) {
		// 光源的方向:交點指向光源
		Vec3f light_dir = (lights[i].position - point).normalize(); 
		float light_distance = light_dir.norm();  // 距離

		// 判斷是否 light[i]這個光線找不到point
		Vec3f shdow_orig = light_dir*N<0 ? point - N*1e-3 : point + N*1e-3; 
		Vec3f shadow_pt, shadow_N;
		Material tempmaterial;
		// 就是說從這個點出發,看看能不能找到與它相交的sphere,如果可以,那麼就是處於陰影.lights[i]找不到
		if (scene_intersect(shdow_orig, light_dir, spheres, shadow_pt, shadow_N, tempmaterial))
			continue;

		diffuse_light_intensity += lights[i].intensity * std::max(0.f, light_dir*N);
		specular_light_intensity += powf(std::max(0.f, -reflect(-light_dir, N)*dir), material.specular_exponent)
			*lights[i].intensity;
	}

渲染效果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章