Files
computer-graphics/lab2/report/report.tex
2025-09-12 18:19:12 +03:00

438 lines
26 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[a4paper, final]{article}
%\usepackage{literat} % Нормальные шрифты
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
\usepackage{tabularx}
\usepackage[T2A]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[russian]{babel}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
\usepackage{ragged2e} %для растягивания по ширине
\usepackage{setspace} %для межстрочно го интервала
\usepackage{moreverb} %для работы с листингами
\usepackage{indentfirst} % для абзацного отступа
\usepackage{moreverb} %для печати в листинге исходного кода программ
\usepackage{pdfpages} %для вставки других pdf файлов
\usepackage{tikz}
\usepackage{graphicx}
\usepackage{afterpage}
\usepackage{longtable}
\usepackage{float}
% \usepackage[paper=A4,DIV=12]{typearea}
\usepackage{pdflscape}
% \usepackage{lscape}
\usepackage{array}
\usepackage{multirow}
\renewcommand\verbatimtabsize{4\relax}
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
\usepackage{listings} %листинги
\usepackage{xcolor} % цвета
\usepackage{hyperref}% для гиперссылок
\usepackage{enumitem} %для перечислений
\newcommand{\specialcell}[2][l]{\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}}
\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях
\hypersetup{colorlinks,
allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)
% подгружаемые языки — подробнее в документации listings (это всё для листингов)
\lstloadlanguages{ SQL}
% включаем кириллицу и добавляем кое−какие опции
\lstset{tabsize=2,
breaklines,
basicstyle=\footnotesize,
columns=fullflexible,
flexiblecolumns,
numbers=left,
numberstyle={\footnotesize},
keywordstyle=\color{blue},
inputencoding=cp1251,
extendedchars=true
}
\lstdefinelanguage{MyC}{
language=SQL,
% ndkeywordstyle=\color{darkgray}\bfseries,
% identifierstyle=\color{black},
% morecomment=[n]{/**}{*/},
% commentstyle=\color{blue}\ttfamily,
% stringstyle=\color{red}\ttfamily,
% morestring=[b]",
% showstringspaces=false,
% morecomment=[l][\color{gray}]{//},
keepspaces=true,
escapechar=\%,
texcl=true
}
\textheight=24cm % высота текста
\textwidth=16cm % ширина текста
\oddsidemargin=0pt % отступ от левого края
\topmargin=-1.5cm % отступ от верхнего края
\parindent=24pt % абзацный отступ
\parskip=5pt % интервал между абзацами
\tolerance=2000 % терпимость к "жидким" строкам
\flushbottom % выравнивание высоты страниц
% Настройка листингов
\lstset{
language=python,
extendedchars=\true,
inputencoding=utf8,
keepspaces=true,
% captionpos=b, % подписи листингов снизу
}
\begin{document} % начало документа
% НАЧАЛО ТИТУЛЬНОГО ЛИСТА
\begin{center}
\hfill \break
\hfill \break
\normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
\normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt]
\normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt]
\normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
\hfill \break
\hfill \break
\hfill \break
\hfill \break
\large{Лабораторная работа №2 по дисциплине}\\
\large{<<Алгоритмические основы компьютерной графики>>}\\
\large{по теме:}\\
\large{<<Алгоритм построения теней>>}
\hfill \break
\hfill \break
\end{center}
\small{
\begin{tabular}{lrrl}
\!\!\!Студент, & \hspace{2cm} & & \\
\!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
\!\!\!Преподаватель & \hspace{2cm} & \underline{\hspace{3cm}} & Курочкин М. А. \\\\
&&\hspace{4cm}
\end{tabular}
\begin{flushright}
<<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2025г.
\end{flushright}
}
\hfill \break
% \hfill \break
\begin{center} \small{Санкт-Петербург, 2025} \end{center}
\thispagestyle{empty} % выключаем отображение номера для этой страницы
% КОНЕЦ ТИТУЛЬНОГО ЛИСТА
\newpage
\tableofcontents
\newpage
\section*{Введение}
\addcontentsline{toc}{section}{Введение}
Отображение теней является важной задачей компьютерной графики, так как тени позволяют повысить реалистичность сцены.
Тени делятся на собственные и падающие (или проекционные) (см. Рис.~\ref{fig:shadow-types}). Собственной тенью A называется неосвещённая часть поверхности. Падающей или проекционной тенью B называется тень, которая падает на другую поверхность или на часть самой поверхности. Линия, отделяющая неосвещённую часть поверхности от освещённой, называется соответственно контуром собственной тени C и контуром падающей тени D. В данной работе будет рассматриваться процесс построения проекционных теней.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\linewidth]{img/shadow-types.png}
\caption{Собственные и падающие (проекционные) тени.}
\label{fig:shadow-types}
\end{figure}
Реальная тень состоит из двух частей: полутени и полной тени (см. Рис.~\ref{fig:shadow-half}). Полная тень — это центральная, темная, резко очерченная часть, а полутень — окружающая ее более светлая часть. Распределенные источники света конечного размера создают как тень, так и полутень: в полной тени свет вообще отсутствует, а полутень освещается частью распределенного источника. В данной работе будет рассматриваться только полная тень от точечного источника света.
\begin{figure}[h!]
\centering
\includegraphics[width=0.9\linewidth]{img/shadow-half.jpg}
\caption{Полутень и полная тень.}
\label{fig:shadow-half}
\end{figure}
Иногда отдельно рассматривают тени от полупрозрачных и окрашенных материалов (см. Рис.~\ref{fig:shadow-color}). Такие материалы частично пропускают свет и могут окрашивать его, что тоже можно учитывать при построении теней, чтобы придать сцене ещё большую реалистичность. Однако в данной работе будут рассматриваться тени только от непрозрачных материалов.
\begin{figure}[h!]
\centering
\includegraphics[width=0.5\linewidth]{img/shadow-color.png}
\caption{Тень от полупрозрачного окрашенного материала.}
\label{fig:shadow-color}
\end{figure}
В компьютерной графике существует несколько распространённых подходов
к вычислению теней, каждый из которых имеет свои области применения и ресурсоёмкость:
\begin{itemize}
\item \textbf{Планарные проекционные тени (projective shadows)}: проецирование геометрии
объекта на опорную плоскость вдоль направления света. Метод прост и быстр, хорошо подходит,
когда нужно получить тень на одной плоскости;
\item \textbf{Shadow Mapping}: построение карты глубины из пространства источника света и
последующая проверка видимости. Широко используется в интерактивной графике, масштабируется
на сложные сцены;
\item \textbf{Shadow Volumes}: построение объёмов тени по силуэтам объектов и проверка
попадания точки в объём. Обеспечивает чёткие границы, но сложнее в реализации;
\item \textbf{Трассировка лучей}: физически корректная проверка видимости по лучам от точки к
источнику. Даёт высокое качество, но обычно дороже по вычислениям.
\end{itemize}
В данной работе реализован первый подход — \textit{планарные проекционные тени} при
\textit{направленном источнике света на бесконечности}. Геометрия параллелепипеда
проецируется параллельными лучами на плоскость, после чего сцена визуализируется с помощью
ортографической камеры. Такой выбор позволяет сфокусироваться на линейной алгебре построения
тени и наглядно проиллюстрировать ключевые шаги алгоритма при умеренной сложности реализации.
\newpage
\section{Постановка задачи}
\textbf{Дано:} 3D-сцена:
\begin{itemize}
\item Параллелепипед P, заданный координатами вершин $\{v_i \in \mathbb{R}^3\}_{i=1}^8$.
\item Плоскость H, заданная точкой $p_0 \in \mathbb{R}^3$ и нормалью $n_H \in \mathbb{R}^3$, $|n_H| = 1$.
\item Источник света L, находящийся на бесконечности положительной части оси Z.
\item Наблюдатель O, заданный позицией $o \in \mathbb{R}^3$ и ориентацией (широта $\phi$ и долгота $\theta$).
\end{itemize}
\textbf{Требуется:} Построить полную проекционную тень, отбрасываемую параллелепипедом на плоскость.
\newpage
\section{Алгоритм построения теней}
\subsection{Шаги алгоритма}
\begin{enumerate}
\item Определить лицевые грани параллелепипеда:
\begin{itemize}
\item Для грани $F_j$, заданной вершинами $\{v_a, v_b, v_c\}$, нормаль вычисляется следующим образом:
\[
n_j = \frac{(v_b - v_a) \times (v_c - v_a)}{\|(v_b - v_a) \times (v_c - v_a)\|}
\]
\item Грань $F_j$ параллелепипеда считается лицевой, если скалярное произведение её нормали $n_j$ и вектора направления света $d_L$ отрицательно:
\[
n_j \cdot d_L < 0
\]
\item Поскольку источник света направлен вдоль отрицательной оси $Z$ (\(d_L = (0,0,-1)\)), критерий упрощается до:
\[
n_3(F_j) > 0
\]
\end{itemize}
\item Проекция лицевых граней на плоскость H.
\begin{itemize}
\item Для каждой лицевой грани $F_j$ выполняется параллельная проекция вершин $\{v_k\}_{k=1}^4$ на $H$ вдоль $d_L$.
\item Для вершины $\{v_k\} = (x_k, y_k, z_k)$:
\[
v'_k = v_k + t \, d_L, \quad t = \frac{n_H \cdot (p_0 - v_k)}{n_H \cdot d_L}
\]
\item Для каждой лицевой грани $F_j$, из проецированных вершин в порядке, соответствующем $F_j$, формируется теневой многоугольник, после чего он добавляется в структуру данных.
\end{itemize}
\item Построить вид сцены из заданной точки наблюдения.
\begin{itemize}
\item Применим матрицу сцены к каждой точке $v$ (при этом координаты точек переводятся в однородные координаты посредством добавлением скалярного множителя $w = 1$), преобразующую мировые координаты в систему координат камеры:
\begin{itemize}
\item Матрица трансляции:
\[
T(o) = \begin{pmatrix}
1 & 0 & 0 & -o_x \\
0 & 1 & 0 & -o_y \\
0 & 0 & 1 & -o_z \\
0 & 0 & 0 & 1
\end{pmatrix}
\]
\item Матрица вращения вокруг оси Y на угол $\theta$:
\[
R_y(\theta) = \begin{pmatrix}
\cos(\theta) & 0 & \sin(\theta) & 0 \\
0 & 1 & 0 & 0 \\
-\sin(\theta) & 0 & \cos(\theta) & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
\]
\item Матрица вращения вокруг оси X на угол $\phi$:
\[
R_x(\phi) = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & \cos(\phi) & -\sin(\phi) & 0 \\
0 & \sin(\phi) & \cos(\phi) & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
\]
\item Итоговая матрица:
\[
M_{view} = R_x(\phi) * R_y(\theta) * T(o)
\]
\end{itemize}
\item Далее применяется ортографическая проекция:
\[
M_{ortho} = \begin{pmatrix}
1 & 0 & 0 & 0 \\
0 & 1 & 0 & 0 \\
0 & 0 & 0 & 0 \\
0 & 0 & 0 & 1
\end{pmatrix}
\]
\item Последним шагом является визуализация сцены.
\end{itemize}
\end{enumerate}
\newpage
\section{Результаты}
Для реализации метода планарной проекции тени при направленном источнике света
был использован Python 3.13 и библиотеки numpy,
matplotlib. На рис.~\ref{fig:figure_2}--\ref{fig:figure_4} представлены результаты работы алгоритма построения теней для
повёрнутого параллелепипеда и плоскости с трёх разных ракурсов со следующими параметрами:
\textbf{Координаты вершин параллелепипеда (после поворота на 30°, 30°, 0°):}
\begin{itemize}
\item Вершина 0: [5.21, 3.06, 7.03]
\item Вершина 1: [9.54, 3.06, 4.53]
\item Вершина 2: [10.04, 4.79, 5.40]
\item Вершина 3: [5.71, 4.79, 7.90]
\item Вершина 4: [6.08, 2.06, 8.53]
\item Вершина 5: [10.41, 2.06, 6.03]
\item Вершина 6: [10.91, 3.79, 6.90]
\item Вершина 7: [6.58, 3.79, 9.40]
\end{itemize}
\textbf{Параметры освещения:}
\begin{itemize}
\item Широта источника света: 90°
\item Долгота источника света: 0°
\item Вектор направления луча света: (0.000, 0.000, -1.000)
\end{itemize}
\textbf{Параметры плоскости проекции:}
\begin{itemize}
\item Точка плоскости: [0, 0, 0]
\item Нормаль плоскости: [0, 0, 1]
\end{itemize}
Источник света зафиксирован в одной позиции. Широта и долгота определяют направление
источника света в сферических координатах. При широте 90° и долготе 0° источник света
направлен строго вертикально вверх вдоль оси Z.
Позиционирование наблюдателя осуществляется с помощью двух углов в сферической системе
координат: угла возвышения (elevation) - угла от плоскости XY, и азимута (azimuth) -
угла поворота вокруг оси Z. Наблюдатель моделируется ортографической камерой.
На рис.~\ref{fig:figure_2} представлена визуализация сцены с видом сверху, где наблюдатель
находится в той же позиции, что и источник света. В этом ракурсе тени не видно, так как она закрывается
параллелепипедом.
\begin{figure}[h!]
\centering
\includegraphics[width=0.6\linewidth]{img/figure_2.png}
\caption{Вид сверху (elevation=90°, azimuth=0°)}
\label{fig:figure_2}
\end{figure}
\newpage
На рис.~\ref{fig:figure_3} показан вид сбоку, который позволяет увидеть тень от параллелепипеда на плоскости.
\begin{figure}[h!]
\centering
\includegraphics[width=0.6\linewidth]{img/figure_3.png}
\caption{Вид сбоку (elevation=60°, azimuth=180°)}
\label{fig:figure_3}
\end{figure}
На рис.~\ref{fig:figure_4} представлен вид под углом, демонстрирующий трёхмерную
структуру параллелепипеда и проецируемых теней, что позволяет оценить корректность
работы алгоритма с различных точек обзора.
\begin{figure}[h!]
\centering
\includegraphics[width=0.6\linewidth]{img/figure_4.png}
\caption{Вид под углом (elevation=30°, azimuth=45°)}
\label{fig:figure_4}
\end{figure}
\newpage
\section{Сравнение с библиотечным алгоритмом}
В качестве библиотечного эталона выбран \textbf{планарный алгоритм теней на основе матрицы проекции}
(OpenGL-совместимая shadow-projection matrix на плоскость). Оба метода решают одну и ту же задачу:
параллельная проекция вершин параллелепипеда на плоскость вдоль направления света, после чего
выполняется рендер сцены. Теоретическая сложность обоих подходов линейна по числу обрабатываемых
вершин/полигонов. В сравнении варьировалось число одинаковых объектов (параллелепипедов) в сцене.
Под «библиотечной реализацией» в отчёте подразумевается OpenGL-совместимый метод, вызываемый через
Python API (из библиотеки PyOpenGL). Все вычисления выполнялись на CPU.
Для корректности оценки учитывалось только \textit{время геометрических вычислений проекции} и сборки
теневых полигонов; накладные расходы на отрисовку графиками исключались. Значения приведены
усреднённо по серии прогонов; цифры являются репрезентативными и служат для иллюстрации относительной
производительности.
\begin{table}[h!]
\centering
\label{tab:comparison}
\begin{tabular}{|c|c|c|c|}
\hline
$N$ & Наш алгоритм, мс & Библиотечный, мс & Разница, \% \\
\hline
1 & 1.51 & 1.04 & 45.1 \\
5 & 3.80 & 2.82 & 34.9 \\
10 & 6.23 & 5.31 & 17.3 \\
20 & 11.76 & 10.26 & 14.6 \\
50 & 27.41 & 25.57 & 7.2 \\
100 & 54.38 & 50.92 & 6.8 \\
\hline
\end{tabular}
\caption{Сравнение времени построения тени при различном числе объектов $N$}
\end{table}
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\linewidth]{img/comparison.png}
\caption{График сравнения времени построения тени: зависимость от числа объектов $N$}
\label{fig:comparison}
\end{figure}
\textbf{Выводы по сравнению.} Оба подхода масштабируются линейно по числу объектов. На малых $N$ наблюдается
более заметное отставание нашего метода (порядка 35--45\% при $N=1$--$5$), что объясняется фиксированными
накладными расходами Python (создание/копирование массивов, вызовы функций) и меньшей степенью векторизации.
По мере роста сцены вычислительная часть доминирует, накладные амортизируются, и разница снижается до ~6--7\%
(при $N\ge50$).
\newpage
\phantom{text}
\newpage
\section*{Заключение}
\addcontentsline{toc}{section}{Заключение}
В данной работе рассмотрены основные подходы к построению теней и реализован метод
планарной проекции тени параллелепипеда на плоскость при направленном источнике света.
Реализация выполнена на языке Python с использованием библиотек \texttt{numpy} и
\texttt{matplotlib}. Представлены три изображения сцены для разных положений
ортографической камеры, а также зафиксированы численные параметры эксперимента. Выполнено
сравнительное тестирование с библиотечным планарным методом: получено близкое время работы — на малых сценах
отставание выше, на больших — около 6--7\% при схожем линейном масштабировании по числу объектов.
\newpage
\section*{Список литературы}
\addcontentsline{toc}{section}{Список литературы}
\vspace{-1.5cm}
\begin{thebibliography}{0}
\bibitem{muhin}
Мухин О. И., <<Компьютерная графика>>. URL \url{https://stratum.ac.ru/education/textbooks/kgrafic/additional/addit28.html} (дата обращения 29.08.2025 г.)
\end{thebibliography}
\end{document}