grafika-uam-rybki-21-22/cw 3/zadania_3.html
2021-12-27 21:29:18 +01:00

123 lines
11 KiB
HTML
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zadania_3</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="style.css" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h2 id="rzutowanie-perspektywiczne">Rzutowanie perspektywiczne</h2>
<p>Zadania <strong>main_3_1</strong> zaczynają się w miejscu, w którym skończyło się zadanie <strong>main_2_1</strong> z poprzednich zajęć. Widać w nim jedynie kwadrat, nie cały prostopadłościan. Wyświetlimy go w rzutowaniu perspektywicznym, dzięki temu otrzymamy iluzję trzech wymiarów.</p>
<h4 id="zadanie-1">Zadanie 1</h4>
<p>Macierz perspektywy tworzy funkcja <code>createPerspectiveMatrix()</code>, przyjrzyj się definicji tej funkcji. Prześlij macierz perspektywy do shadera.</p>
<p>Wynik wygląda nie do końca tak jakbyśmy się spodziewali. Wynika to z tego, że kamera znajduje się wewnątrz prostopadłościanu. Dodaj macierz kamery do macierzy transformacji, dzięki temu będzie można przesuwać kamerę za pomocą klawiszy. Przesuń prostopadłościan tak, żeby można go było zobaczyć od zewnątrz.</p>
<h4 id="zadanie-1-1">Zadanie 1*</h4>
<p>Zmodyfikuj macierz perspektywy. W funkcji <code>createPerspectiveMatrix()</code> znajduje się zmienna <code>frustumScale</code>, która odpowiada ona za kąt widzenia, zmodyfikuj jej wartość i zobacz jaki jest efekt. By obliczyć jej wartość możesz skorzystać ze wzoru $ S = $, gdzie <span class="math inline">\(fov\)</span> oznacza kąt widzenia.</p>
<h4 id="zadanie-1-2">Zadanie 1**</h4>
<p>Wciąż jest problem z rozciąganiem się obrazu przy zmianie kształtu okna. Rozwiązaniem jest wstawienie różnej wartości <strong>frustumScale</strong> dla współrzędnych <strong>X</strong> i <strong>Y</strong>. by to naprawić wykorzystaj funkcję <code>onReshape</code>, która jest wywoływana przy zmianie wielkości ekranu. Najpierw oblicz w niej proporcje ekranu i przypisz do zmiennej globalnej <code>screenRatio</code>. Następnie przemnóż odpowiednią współrzędną przez <code>screenRatio</code> w funkcji <code>createPerspectiveMatrix()</code>.</p>
<h2 id="obsługa-shaderów">Obsługa Shaderów</h2>
<p>W tej części zadań będziemy korzystać z innych obiektów, usuń z funkcji <code>init</code> inicjalizację prostopadłościanu i jego rysowanie z funkcji <code>renderScene</code> oraz zamień shadery na <code>shaders/shader_3_2.vert</code> i <code>shaders/shader_3_2.frag</code>.</p>
<h4 id="zadanie-2">Zadanie 2</h4>
<p>Wczytaj statek i sferę za pomocą do <code>loadModelToContext</code> do odpowiednich <code>Core::RenderContext</code>. Następnie wyświetl je za pomocą funkcji <code>Core::DrawContext</code>. Rozmieść je w różnych miejscach w przestrzeni.</p>
<h5 id="dodaj-możliwość-zmiany-kolorów-obiektów">Dodaj możliwość zmiany kolorów obiektów:</h5>
<p>Stwórz zmienną <code>uniform vec3 objectColor</code> w pliku <code>shader_3_2.frag</code> (jej definicja musi się ona znajdować nad definicją funkcji <code>main</code>), wykorzystamy ją do przesłania koloru w formacie RGB do shadera. Zmienna wbudowana <code>gl_FragColor</code> jest typu <code>vec4</code> w formacie RGBA, współrzędne przyjmują wartości od od 0 do 1. Do części RGB przypisz wartość <code>objectColor</code> a do A wartość 1.</p>
<p>Możemy teraz ustawić kolor rysowanego obiektu ustawiając wartość zmiennej <code>objectColor</code> przed rysowaniem obiektu. Robimy to korzystając z funkcji <code>glUniform3f( int location, float v0, float v1, float v2 )</code>, gdzie parametr <code>location</code> oznacza adres zmiennej w pamięci karty graficznej, do której chcemy wartości wysłać. Można ten adres uzyskać wywołując funkcje <code>glGetUniformLocation(program, "nazwa zmiennej")</code>.</p>
<h4 id="zadanie-2-1">Zadanie 2*</h4>
<p>Zmodyfikuj program tak, żeby kolor statku zmieniał się w czasie.</p>
<h4 id="zadanie-3">Zadanie 3</h4>
<p>Wyświetl “kolor” wektora normalnego do powierzchni w danym punkcie.</p>
<blockquote>
<p>Wektor normalny to wektor prostopadły do powierzchni w danym punkcie, pozwala on na przykład na policzenie odbicia światła.</p>
</blockquote>
<p>Wektor normalny wierzcholka dostępny jest w <em>vertex shaderze</em> (plik z rozszerzeniem <strong>.vert</strong>). Kolor powierzchni (piksela) ustala sie jednak we <em>fragment shaderze</em> (<strong>.frag</strong>). Zatem należy przesłać wartość wektora normalnego z <em>vertex</em> do <em>fragment</em> shadera. Służą do tego specjalne zmienne (interpolatory).</p>
<p>Stwórz zmienną typu <code>out vec3 nazwa</code> w <em>vertex shaderze</em> oraz odpowiadająca mu zmienna <code>in vec3 nazwa</code> we <em>fragment shaderze</em>. Prześlij przy jej użyciu wartość wektora normalnego.</p>
<p>Użyj tej wartości, aby w jakiś sposób przypisać kolor pikselowi.</p>
<p>Aby otrzymać ładny efekt, najpierw znormalizuj wektor otrzymany przez <em>fragment shader</em>. Następnie przeskaluj wartości (x, y, z) wektora z przedziału [-1, 1] do [0, 1] i przypisz je do kanałów R, G, B zmiennej <code>gl_FragColor</code>.</p>
<p>#### Zadanie 4 Stwórz funkcje <code>drawObject</code>, która ułatwi rysowanie wielu obiektów. Na liście parametrów musza znaleźć się referencja do <code>Core::RenderContext</code> oraz macierz modelu (<em>model matrix</em>) obiektu. Wyświetl kilka obiektów w różnych pozycjach (i obejrzyj je z każdej strony).</p>
<p>“Przyczep” model statku do kamery - uzależnij jego macierz modelu od pozycji i orientacji kamery tak, aby wyglądało jakbyś poruszał(a) się statkiem.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>glm::mat4 shipModelMatrix = </span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> glm::translate(cameraPos + cameraDir * <span class="fl">0.5</span><span class="bu">f</span> + glm::vec3(<span class="dv">0</span>,-<span class="fl">0.25</span><span class="bu">f</span>,<span class="dv">0</span>)) * </span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> glm::rotate(-cameraAngle + glm::radians(<span class="fl">90.0</span><span class="bu">f</span>), glm::vec3(<span class="dv">0</span>,<span class="dv">1</span>,<span class="dv">0</span>)) *</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> glm::scale(glm::vec3(<span class="fl">0.25</span><span class="bu">f</span>));</span></code></pre></div>
<p>Przeanalizuj tą macierz modelu lub napisz własną.</p>
<h4 id="zadanie-5">Zadanie 5</h4>
<p>Stwórz układ planetarny - jedna nieruchoma kule na środku (Słonce) i kilka orbitujących wokół niej planet. Niech przynajmniej jedna planeta ma księżyce.</p>
</body>
</html>