- •Задание
- •Аннотация
- •1.2 Пересечение лучей с эллиптическим параболоидом
- •1.3 Пересечение лучей с гиперболическим параболоидом
- •1.3 Модель освещения Фонга
- •2. Практическая часть
- •2.1 Эллиптический параболоид
- •2.2 Гиперболический параболоид
- •Тени и составляющие света
- •Визуализация объектов, отражающих свет
- •Заключение
- •Список используемых ресурсов
1.3 Пересечение лучей с гиперболическим параболоидом
С лева изображен гиперболический параболоид. Его уравнение имеет вид:
x2-z2-y=0. Пересечение луча и гиперболоида можно изобразить так:
Коэффициенты a, b, c:
a=
b =
c=
Дискриминант d = и, если он не отрицателен, имеются корни:
;
Для вычисления нормали к точке также используется градиент.
1.3 Модель освещения Фонга
Модель освещения Фонга расширяет стандартную модель диффузного освещения, добавляя в нее зеркальную компоненту.
N – нормаль к поверхности
L – направление к источнику света
R – направление отраженного луча
V – направление к наблюдателю
Причем каждый из векторов является единичным.
Зеркальная компонента освещения зависит от расположения наблюдателя. В реальной жизни можно заметить, что когда в солнечный день мы смотрим на «зеркальные» объекты (металл, вода, стекло и т.д.) освещенность объекта зависит на нашей точки обзора. При определенных углах заметны яркие блики.
С точки зрения физики, происходит примерно следующее: луч света отражается от гладкой поверхности, если этот луч попадает на сетчатку глаза, то мы видим яркий блик.
Таким образом, можно ввести некоторые дополнительные обозначения:
Is – зеркальная составляющая освещенности
ks- коэффициент зеркального освещения
is- интенсивность зеркального освещения
a – коэффициент блеска (свойство материала)
Суммарная освещенность объекта будет определяться как сумма всех трех компонент освещенности.
2. Практическая часть
2.1 Эллиптический параболоид
Реализовать возможность построения с использованием трассировки лучей геометрический объект «Базовый геометрический параболоид»
#pragma once
#include "GeometryObjectWithInitialTransformImpl.h"
#include "Ray.h"
#include "Intersection.h"
/************************************************************************/
/* Геометрический объект "Элиптический параболоид" */
/* Ось цилиндра совпадает с осью z. Основание находится в плоскости z=0 */
/************************************************************************/
class CEllipticParaboloid :
public CGeometryObjectWithInitialTransformImpl
{
public:
CEllipticParaboloid(CVector3d const& pos, CMatrix4d const& transform);
/*пересечение луча с параболоидом*/
virtual bool Hit(CRay const& ray, CIntersection & intersection)const;
};
Вычисление нормали происходит следующим образом:
// Координаты нормали к точке
CVector3d hitNormal1InObjectSpace = CVector3d(2*hitPoint1InObjectSpace.x, -1, 2*hitPoint1InObjectSpace.z);
if(Dot(hitNormal1InObjectSpace, ray.GetDirection()) > 0)
hitNormal1InObjectSpace = -hitNormal1InObjectSpace;
Вычисляется градиент
Если скалярное произведение направления луча и нормали к точке больше нуля, то поворачиваем нормаль в другую сторону.
2.2 Гиперболический параболоид
Реализовать возможность построения поверхности базового гиперболического параболоида, заданного на диапазоне координат x и y от -1 до +1. Точка пересечения луча с гиперболическим
параболоидом должна вычисляться аналитически.
#pragma once
#include "GeometryObjectWithInitialTransformImpl.h"
#include "Ray.h"
#include "Intersection.h"
/************************************************************************/
/* Геометрический объект "Гиперболический параболоид" */
/* Ось цилиндра совпадает с осью z. Основание находится в плоскости z=0 */
/************************************************************************/
class CHyperbolicParaboloid :
public CGeometryObjectWithInitialTransformImpl
{
public:
CHyperbolicParaboloid(CVector3d const& pos, CMatrix4d const& transform);
virtual bool Hit(CRay const& ray, CIntersection & intersection)const;
};
Вычисление нормали:
После вычисления корней уравнения, сортируем их в порядке возрастания
//сортировка
t1<t0?std::swap(t0,t1):false;
А дальше аналогично элиптическому параболоиду, только изменяем формулу градиента
// Координаты нормали к точке
CVector3d hitNormal1InObjectSpace = CVector3d(2*hitPoint1InObjectSpace.x, -1, -2*hitPoint1InObjectSpace.z);
if(Dot(hitNormal1InObjectSpace, ray.GetDirection()) > 0)
hitNormal1InObjectSpace = -hitNormal1InObjectSpace;