小白的光线追踪之旅 | 三 光线渲染和摄像调距

224 阅读2分钟

通过使用glm::vec4将使用光线追踪原理显示的"粉色圆形"多彩化,显示更为立体:

glm::vec4 Renderer::PerPixel(glm::vec2 coord)
{

	glm::vec3 rayOrigin(0.0f, 0.0f, 2.0f);
	glm::vec3 rayDirection(coord.x, coord.y, -1.0f);
	float radius = 0.5f;
	// rayDirection = glm::normalize(rayDirection);

	// (bx^2 + by^2)t^2 + (2(axbx + ayby))t + (ax^2 + ay^2 - r^2) = 0
	// where
	// a = ray origin
	// b = ray direction
	// r = radius
	// t = hit distance
	
	//float a = coord.x * coord.x + coord.y * coord.y + coord.z * coord.z;
	float a = glm::dot(rayDirection, rayDirection);
	float b = 2.0f * glm::dot(rayOrigin, rayDirection);
	float c = glm::dot(rayOrigin, rayOrigin) - radius * radius;

	// Quadratic formula discriminant:
	// b^2 - 4ac



	float discriminant = b * b - 4.0f * a * c;

	if (discriminant < 0.0f)
	{
		return glm::vec4(0, 0, 0, 1);
	}
	// (-b +- sqrt(discriminant)) / 2a
	float t0 = (-b + glm::sqrt(discriminant)) / (2.0f * a);
	float closestT = (-b - glm::sqrt(discriminant)) / (2.0f * a);

	//glm::vec3 h0 = rayOrigin + rayDirection * t0;
	glm::vec3 hitPoint = rayOrigin + rayDirection * closestT;

	glm::vec3 sphereColor(1, 0, 1);
	sphereColor = hitPoint;
	return glm::vec4(sphereColor, 1.0f);   // 0xff000000
}

image.png

在人们的视图原理中,眼睛通过接收光线来形成图形视图,当我们旋转物体时,迎光的一面会显得更亮,背光的一面会显得更暗,我们通常会定义一个法线向量(normal vector)来对物体的方向和角度的定义。

修改如下代码,使用glfm图形库进行法线向量的使用:


	//glm::vec3 h0 = rayOrigin + rayDirection * t0;
	glm::vec3 hitPoint = rayOrigin + rayDirection * closestT;
	glm::vec3 normal = glm::normalize(hitPoint);

	glm::vec3 sphereColor(1, 0, 1);
	sphereColor = normal;
	return glm::vec4(sphereColor, 1.0f);   // 0xff000000

显示如图:

image.png

可以看到亮度变得很高了。因为是正对点光源的。

更改rayOrigin的位置,再运行程序:

	glm::vec3 rayOrigin(0.0f, 0.0f, 1.0f);
	glm::vec3 rayDirection(coord.x, coord.y, -1.0f);
	float radius = 0.5f;

显示如下:

image.png

球形看起来大了很多,那么应该是距离摄像机距离更近了,相对看起来就显得更大。

在进行法向量的显示修改


	glm::vec3 sphereColor(1, 0, 1);
	sphereColor = normal * 0.5f + 0.5f;
	return glm::vec4(sphereColor, 1.0f);   // 0xff000000

显示如图:

image.png 渲染出来的球形对比度降低了,摄像机的蓝光范围更小,光圈更大,上面的天蓝色光和右边的紫光也光圈更大,

更换成一个光源,让光影感更加好一些:


	glm::vec3 lightDir = glm::normalize(glm::vec3(-1, -1, -1));

	float d = glm::max(glm::dot(normal, -lightDir), 0.0f);  // == cos(angle)

	glm::vec3 sphereColor(1, 0, 1);
	sphereColor *= d;
	return glm::vec4(sphereColor, 1.0f);   // 0xff000000

显示如下:

image.png 这样显示出来的球形有一些写实风格了,虽然还是很假,右上到左下逐渐变暗。

电脑不好,可以看到有右上角显示的渲染速率,只有5,6帧每秒,因为完全使用cpu运行程序,又是使用的vulkan库,对电脑要求很高。