КомпГр_ЛР6_Заболотников_Петрова_Романова_9373
.pdfМИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра ИС
ОТЧЕТ по лабораторной работе№6
по дисциплине «Компьютерная графика» Тема: Формирования реалистических изображений с использованием
простых моделей освещения одним или двумя точечными источниками
Студент гр. 9373 |
_______________ |
Заболотников М. Е. |
Студентка гр. 9373 |
_______________ |
Петрова С. В. |
Студентка гр. 9373 |
_______________ |
Романова Е. С. |
Преподаватель |
_______________ |
Матвеева И.В. |
Санкт-Петербург
2022
Цель работы.
Реализовать алгоритм трассировки лучей при формировании сложной сцены.
Задание на работу.
Необходимо написать программу в которой реализуется алгоритм трассировки лучей для сложной сцены с тремя сферами.
Общие сведения.
Для выполнения работы потребовались следующие теоретические
сведения.
Трассировка лучей – один из методов геометрической оптики – исследование оптических систем путём отслеживания взаимодействия отдельных лучей с поверхностями. В узком смысле - технология построения изображения трёхмерных моделей в компьютерных программах, при которых отслеживается обратная траектория распространения луча (от экрана к
источнику).
Трассировка лучей в компьютерных играх – это решение для создания реалистичного освещения, отражений и теней, обеспечивающее более высокий уровень реализма по сравнению с традиционными способами
рендеринга. |
|
|
Пусть у нас есть две точки |
и |
– независимо от размерности: |
1, 2, 3, … , , тогда вектор, идущий |
от |
к , может быть найден путем |
поэлементного вычитания из .
Длину вектора – независимо от его размерности – можно найти,
вычислив квадратный корень из суммы возведенных в квадрат компонентов.
Длина вектора обозначается || ||.
Единичный вектор — это вектор длины 1: || || = 1.
2
Для данного вектора другой вектор, идущий в том же направлении, но имеющий длину 1, может быть найден путем деления каждого компонента первого вектора на его длину — это называется нормализацией: = || ||.
Скалярное произведение для векторов вычисляется как: , = || ||².
Ход работы.
Рассмотрим работу программы, которая заключается в взятии значений из полей и вызове функции отрисовки изображения с посредствующим вызовом окошка для отображения получавшегося изображения.
Выполнение работы.
Ссылка на видео с демонстрацией работы программы: https://www.youtube.com/watch?v=J7k6sftALfM
Программа была написана в приложении Jupiter на языке Python с
использованием графических библиотек.
Для работы с программой необходимо ввести координаты и радиус сфер в соответствующие для этого поля и цвет для каждой сферы, также следует указать высоту изображения, а затем нажать на «Обновить значения» и «Нарисовать сцену». Так как данный процесс занимает время, то под
«Загрузка», будет двигаться ползунок. Когда он достигнет конца строки, то появится окошко и изображением. Кнопка «Обнулить значения» обнуляется все поля ввода.
Тесты работы программы.
На рис.1 – 3 представлены результаты выполнения работы программы:
3
Рисунок 1 – Трассировка лучей сложной сцены с тремя сферами с высотой 100
Рисунок 2 – Трассировка лучей сложной сцены с тремя сферами с высотой 200
4
Рисунок 3 – Трассировка лучей сложной сцены без сфер
Выводы.
В данной работе была реализована программа трассировки лучей при формировании сложной сцены, состоящий из трех сфер, с возможностью регулировки высоты изображения.
5
ПРИЛОЖЕНИЕ А
Файл «Komp_GR_6.ipynb»
import tkinter
from tkinter import StringVar import tkinter.messagebox import customtkinter as ctk from vector import *
from color import * from start import * import numpy
ctk.set_appearance_mode("Light") ctk.set_default_color_theme("green")
class App(ctk.CTk): WIDTH = 780 HEIGHT = 660
def __init__(self): super().__init__()
self.x1 = StringVar(value="-3.0") self.y1 = StringVar(value="1.0") self.z1 = StringVar(value="1.0") self.x2 = StringVar(value="0.0") self.y2 = StringVar(value="1.0") self.z2 = StringVar(value="1.0") self.x3 = StringVar(value="2.0") self.y3 = StringVar(value="1.0") self.z3 = StringVar(value="1.0") self.sph_c = [
[self.x1, self.y1, self.z1], [self.x2, self.y2, self.z2], [self.x3, self.y3, self.z3]
]
self.r1 = StringVar(value="2.0") self.g1 = StringVar(value="2.0") self.b1 = StringVar(value="2.0") self.r2 = StringVar(value="1.0") self.g2 = StringVar(value="1.0")
6
self.b2 = StringVar(value="1.0") self.r3 = StringVar(value="1.0") self.g3 = StringVar(value="2.") self.b3 = StringVar(value="2.0") self.sph_col = [
[self.r1, self.g1, self.b1], [self.r2, self.g2, self.b2], [self.r3, self.g3, self.b3]
]
self.width_im = StringVar(value="100") self.height = int(self.width_im.get()) self.width = int(self.height*16.0/9.0)
self.spheres = [Sphere(vect3(0, -1000, 0), vect3(1, 1, 1), 1000), Sphere(vect3(-3,1,1), vect3(2,2,2), 1), Sphere(vect3(0,1,1), vect3(1,1,1), 0.8), Sphere(vect3(2,1,1), vect3(1,2,2), 0.6),
]
# light sources
self.lights = [Sphere(vect3(0, 100, 0), vect3(0.0, 0.1, 0.2), 0), Sphere(vect3(100, 100, 200), vect3(0.3, 0.1, 0), 0), Sphere(vect3(-100, 100, 200), vect3(0.1, 0.3, 0.0), 0)]
self.title("Работа №6") self.geometry(f"{App.WIDTH}x{App.HEIGHT}") self.protocol("WM_DELETE_WINDOW", self.on_closing) # call
.on_closing() when app gets closed
# ============ create two frames ============
self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1)
self.frame_left = ctk.CTkFrame(master=self, width=180, corner_radius=0)
self.frame_left.grid(row=0, column=0, sticky="nswe")
self.frame_right = ctk.CTkFrame(master=self) self.frame_right.grid(row=0, column=1, sticky="nswe", padx=20,
pady=20)
# ============ frame_left ============
7
self.frame_left.grid_rowconfigure(0, minsize=10) |
# empty row with |
minsize as spacing |
|
self.frame_left.grid_rowconfigure(5, weight=1) # |
empty row as |
spacing |
|
self.frame_left.grid_rowconfigure(8, minsize=20) |
# empty row with |
minsize as spacing |
|
self.frame_left.grid_rowconfigure(11, minsize=10) |
# empty row with |
minsize as spacing |
|
self.label_1 = ctk.CTkLabel(master=self.frame_left, text="Значения",
text_font=("Roboto Medium", -16)) # font
name and size in px
self.label_1.grid(row=7, column=0, pady=10, padx=10)
self.button_1 = ctk.CTkButton(master=self.frame_left, text="Обновить значения", command = self.apply)
self.button_1.grid(row=8, column=0, pady=10, padx=20)
self.button_2 = ctk.CTkButton(master=self.frame_left, text="Обнулить значения", command=self.reset)
self.button_2.grid(row=9, column=0, pady=10, padx=20)
#============ frame_right ============
#configure grid layout (3x7)
self.frame_right.rowconfigure((0, 1, 2, 3), weight=1) self.frame_right.rowconfigure(7, weight=10) self.frame_right.columnconfigure((0, 1), weight=1) self.frame_right.columnconfigure(2, weight=0)
self.frame_info = ctk.CTkFrame(master=self.frame_right) self.frame_info.grid(row=0, column=0, columnspan=4, rowspan=4,
pady=20, padx=20, sticky="nsew")
#============ frame_info ============
#configure grid layout (1x1)
8
self.frame_info.rowconfigure(0, weight=1) self.frame_info.columnconfigure(0, weight=1)
self.label_info_1 = ctk.CTkLabel(master=self.frame_info, text="Загрузка...", text_font=("Roboto Medium", -16), height=100,
corner_radius=6, # <- custom corner
radius
fg_color=("#9de0b4", "gray38"), #
<- custom tuple-color
justify=tkinter.LEFT) self.label_info_1.grid(column=0, row=0, sticky="nwe", padx=15,
pady=15)
self.progressbar = ctk.CTkProgressBar(master=self.frame_info) self.progressbar.grid(row=1, column=0, sticky="ew", padx=15, pady=15) self.progressbar.set(0)
# ============ frame_right ============
self.radio_var = tkinter.IntVar(value=0)
self.sphere = ctk.CTkLabel(master=self.frame_right,
text="Введите координаты и радиус сфер
",
text_font=("Roboto Medium", -16)) # font
name and size in px
self.sphere.grid(row=4, column=0, pady=5, padx=0) |
|
|
self.sphere_col = ctk.CTkLabel(master=self.frame_right, |
|
|
text=" |
Введите цвет сфер |
", |
text_font=("Roboto Medium", -16)) |
# |
|
font name and size in px |
|
|
self.sphere_col.grid(row=8, column=0, pady=0, padx=0, sticky="w") |
|
|
self.sphere_col = ctk.CTkLabel(master=self.frame_right, |
|
|
text=" |
Высота изображения |
|
(16:9) ", |
|
|
text_font=("Roboto Medium", -16)) |
# |
font name and size in px
self.sphere_col.grid(row=12, column=0, pady=0, padx=0, sticky="wn")
9
self.entry0 = ctk.CTkEntry(master=self.frame_right,
width=80, textvariable=self.x1, validate =
"all")
self.entry0.grid(row=5, column=0, columnspan=2, pady=-0, padx=20, sticky="w")
self.entry1 = ctk.CTkEntry(master=self.frame_right, width=50, textvariable=self.y1)
self.entry1.grid(row=5, column=0, columnspan=2, pady=-0, padx=145, sticky="we")
self.entry2 = ctk.CTkEntry(master=self.frame_right, width=80,
textvariable=self.z1) self.entry2.grid(row=5, column=0, columnspan=2, pady=0, padx=20,
sticky="e")
self.label_number_sphere_1 = ctk.CTkLabel(master=self.frame_right, text="Первая сфера")
self.label_number_sphere_1.grid(row=5, column=0,columnspan=4, pady=0, padx=20, sticky="e")
self.entry00 = ctk.CTkEntry(master=self.frame_right, width=80,
textvariable=self.x2) self.entry00.grid(row=6, column=0, columnspan=2, pady=0, padx=20,
sticky="w")
self.entry11 = ctk.CTkEntry(master=self.frame_right, width=50,
textvariable=self.y2) self.entry11.grid(row=6, column=0, columnspan=2, pady=0, padx=145,
sticky="we")
self.entry22 = ctk.CTkEntry(master=self.frame_right, width=80,
textvariable=self.z2) self.entry22.grid(row=6, column=0, columnspan=2, pady=0, padx=20,
sticky="e")
10