dodanie skyboxa i drobne poprawki
This commit is contained in:
parent
b89c7784ca
commit
7e63de4e57
196
grk/cw 6/Zadania 7.html
Normal file
196
grk/cw 6/Zadania 7.html
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<!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 7</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>
|
||||||
|
<h1 id="normal-mapping">Normal Mapping</h1>
|
||||||
|
<p>W tej części będziemy dalej modyfikować shadery <strong>shader_5_tex</strong> poprzez implementację normal mappingu.</p>
|
||||||
|
<p>Obliczenia dla map normalnych należy wykonywać w przestrzeni stycznych. Przestrzeń styczna jest wyliczana dla każdego punktu w obiekcie. Jej celem jest takie przekształcenie przestrzeni, żeby wektor normalny był wektorem jednostkowym (0,1,0).</p>
|
||||||
|
<p>Do wyliczenia przestrzeni stycznej potrzebujemy dla każdego wierzchołka oprócz wektora normalnego wektor styczny i bistyczny (<em>tangent</em> i <em>bitangent</em>). Są one wyliczane przez bibliotekę <code>Assimp</code>.</p>
|
||||||
|
<h3 id="wykonaj-kopię-shaderów-shader_4_tex.vert-shader_4_tex.frag">Wykonaj kopię shaderów shader_5_tex.vert shader_5_tex.frag</h3>
|
||||||
|
<h3 id="przenieś-obliczenia-światła-do-przestrzeni-stycznej.">Przenieś obliczenia światła do przestrzeni stycznej.</h3>
|
||||||
|
<ol type="1">
|
||||||
|
<li><p>Oblicz macierz <strong>TBN</strong>.</p>
|
||||||
|
<p>Macierz <strong>TBN</strong> to macierz 3x3 wyznaczana przez wektory <em>tangent</em>, <em>bitangent</em> i <em>normal</em>, służy do przenoszenia wektorów z przestrzeni świata do przestrzeni stycznej.</p>
|
||||||
|
<ol type="1">
|
||||||
|
<li>W <strong>vertex shaderze</strong> przekrztałć wektory <code>vertexNormal</code>, <code>vertexTangent</code> i <code>vertexBitangent</code> do przestrzeni świata (przemnóż macierz modelu przez te wektory, tak jak to robiliśmy wcześniej z wektorem normalnym, z uwzględnieniem zmiennej w=0) i zapisz wyniki odpowiednio w zmiennych <code>normal</code>, <code>tangent</code> i <code>bitangent</code>.
|
||||||
|
<ol type="1">
|
||||||
|
<li>Stwórz macierz 3x3 TBN jako transpose(mat3(tangent, bitangent, normal)). Macierz transponujemy, aby szybko uzyskać jej odwrotność (możemy tak zrobić przy założeniu, ze jest ortogonalna).</li>
|
||||||
|
</ol></li>
|
||||||
|
</ol></li>
|
||||||
|
</ol>
|
||||||
|
<ol start="2" type="1">
|
||||||
|
<li>Przenieś wektor światła i wektor widoku do przestrzeni stycznych
|
||||||
|
<ol type="1">
|
||||||
|
<li><p>Musimy przekształcić wektor światła (L) i wektor widoku (V) do przestrzeni stycznych. Zrobimy to w vertex shaderze. W tym celu przenieś potrzebne dane dotyczące światła i kamery (uniformy <code>lightPos</code> i <code>cameraPos</code>) z <strong>fragment shadera</strong> do <strong>vertex shadera.</strong></p></li>
|
||||||
|
<li><p>Oblicz wektor <code>viewDir</code> jako znormalizowana różnice <code>cameraPos</code> i <code>worldPos</code> (tu jeszcze działamy w przestrzeni świata). Analogicznie oblicz <code>lightDir</code> jako różnicę <code>lightPos</code> i <code>worldPos</code></p></li>
|
||||||
|
<li><p>Przekształć wektory <code>viewDir</code> i <code>lightDir</code> do przestrzeni stycznej mnożąc je przez macierz <strong>TBN</strong>. Wynik zapisz w zmiennych <code>viewDirTS</code> i <code>lightDirTS</code> odpowiednio.</p></li>
|
||||||
|
<li><p>Przekaż <code>viewDirTS</code> i <code>lightDirTS</code> do fragment shadera. (zadeklaruj je jako zmienne <code>out</code>)</p>
|
||||||
|
<blockquote>
|
||||||
|
<p>(Sufiks TS oznacza tangent space. Ważne jest, aby oznaczać (np. dopisując coś do nazwy zmiennej) w jakiej przestrzeni znajdują się używane wektory, tak aby poprawnie wykonywać obliczenia. Trzeba zawsze zwracać uwagę na to, w jakiej przestrzeni działamy.)</p>
|
||||||
|
</blockquote></li>
|
||||||
|
</ol></li>
|
||||||
|
<li>Przekształć <strong>fragment shader</strong>, by obsługiwał <strong>tangent space</strong>
|
||||||
|
<ol type="1">
|
||||||
|
<li>Nie potrzebujemy już we <strong>fragment shaderze</strong> informacji na temat pozycji fragmentu i wektora normalnego geometrii, skasuj wiec zmienne przekazujące te wektory pomiędzy shaderami.</li>
|
||||||
|
<li>wektora <code>lightDir</code> powinniśmy użyć wektora <code>lightDirTS</code> (należy go dodatkowo znormalizować), a jako wektor widoku V powinniśmy użyć wektora <code>viewDirTS</code> (również należy go znormalizować). Jako wektora N użyj na razie wektora vec3(0,0,1).</li>
|
||||||
|
</ol></li>
|
||||||
|
</ol>
|
||||||
|
<p>Efekt finalny powinien wyglądać tak samo, jak przed jakąkolwiek zmianą. Następnym krokiem będzie wykorzystanie map normalnych.</p>
|
||||||
|
<h3 id="wykorzystaj-normalmapy">Wykorzystaj normalmapy</h3>
|
||||||
|
<ol type="1">
|
||||||
|
<li>Chcemy wczytywać normalne z tekstury, w tym celu dodaj we <strong>fragment shaderze</strong> dodatkowy sampler do czytania map normalnych, nazwij go <code>normalSampler</code>. Pobierz z niego wektor normalny analogicznie, jak czytamy kolor zwykłej tekstury z samplera <code>textureSampler</code> i zapisz go w zmiennej <code>N</code>.
|
||||||
|
<ol start="2" type="1">
|
||||||
|
<li>Ponieważ w teksturze wartości są w przedziale <span class="math inline">\([0,1]\)</span>, musimy jeszcze przekształcić je do przedziału <span class="math inline">\([-1,1]\)</span>. W tym celu przemnóż wektor N przez 2 i odejmij 1. Na koniec warto jeszcze znormalizować wektor normalny, aby uniknąć błędów związanych z precyzja lub kompresja tekstury.</li>
|
||||||
|
<li>Wczytaj pliki zawierające mapy normalnych w kodzie C++ W tym celu załaduj przy użyciu funkcji <code>Core::LoadTexture</code> mapy normalnych dla wszystkich modeli. Maja one taką samą nazwę jak zwykle tekstury, tyle że z suffiksem "_normals".</li>
|
||||||
|
<li>Zmodyfikuj na koniec funkcje <code>drawObjectTexture</code>. Dodaj do niej nowy argument <code>GLuint normalmapId</code>, który będzie służył do przekazywania id tekstury zawierającej mapę normalnych. Przy użyciu funkcji <code>Core::SetActiveTexture</code> załaduj <code>normalmapId</code> jako <code>normalSampler</code> i ustaw jednostkę teksturowania nr 1. Argument odpowiadający za normalne w miejscach wywołania funkcji <code>drawObjectTexture</code>.</li>
|
||||||
|
</ol></li>
|
||||||
|
</ol>
|
||||||
|
<h3 id="zadanie">Zadanie</h3>
|
||||||
|
<p>Ustaw mapy normalne do statku planety i księżyca (lub przynajmniej 3 obiektów, jeżeli rysujesz swoją scenę). Wykorzystaj multitexturing na statku, musisz w takim wypadku mieszać zarówno tekstury koloru i normalanych.</p>
|
||||||
|
<h2 id="skybox">SkyBox</h2>
|
||||||
|
<p>Cubemapy są specjalnym rodzajem tekstur. Zawieją one 6 tekstur, każda z niej odpowiada za inną ścianę sześcianu. Nie służy ona do teksturowania zwykłego sześcianu, pozwala ona bowiem próbkować po wektorze kierunku. To znaczy, możemy o tym myśleć jak o kostce, w której środku się znaleźliśmy, co obrazuje poniższy rysunek. W przeciwieństwie do zwykłych tekstur samplujemy ją nie za pomocą dwuwymiarowych współrzędnych UV, ale za pomocą wektora trójwymiarowego, który odpowiada kierunkowi promienia. <img src="./img/cubemaps_sampling.png" /> Jednym z zastosowań Cubemapy jest wyświetlanie skyboxa, czyli dalekiego tła dla sceny. Może to być na przykład rozgwieżdżone niebo z górami na horyzoncie albo obraz dalekiej galaktyki.</p>
|
||||||
|
<h3 id="ładowanie-cubemapy">Ładowanie cubemapy</h3>
|
||||||
|
<p>Cubemapę generujemy podobnie jak inne tekstury, ale przy bindowaniu należy podać <code>GL_TEXTURE_CUBE_MAP</code>.</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>glGenTextures(<span class="dv">1</span>, &textureID);</span>
|
||||||
|
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);</span></code></pre></div>
|
||||||
|
<p>Skoro składa się ona z 6 tekstur, to należy każdą z nich załadować za pomocą <code>void glTexImage2D( GLenum target, ...)</code> <code>taget</code> wskazuje którą z tekstur ładujemy. Możliwe wartości rozpisane są w tabeli poniżej |Layer number|Texture target | Orientation| |—-|——————–:|———–:| |0|<code>GL_TEXTURE_CUBE_MAP_POSITIVE_X</code> | Right | |1|<code>GL_TEXTURE_CUBE_MAP_NEGATIVE_X</code>|Left| |2|<code>GL_TEXTURE_CUBE_MAP_POSITIVE_Y</code>|Top| |3|<code>GL_TEXTURE_CUBE_MAP_NEGATIVE_Y</code>|Bottom| |4|<code>GL_TEXTURE_CUBE_MAP_POSITIVE_Z</code>|Back| |5|<code>GL_TEXTURE_CUBE_MAP_NEGATIVE_Z</code>|Front|</p>
|
||||||
|
<p>Możemy je ładować w pętli biorąc za kolejne targety <code>GL_TEXTURE_CUBE_MAP_POSITIVE_X+i</code>, ale należy pamiętać o powyższej kolejności. Poniższy kod ładuje do wszystkich 6 ścian tę samą teksturę, która znajduje się pod <code>filepath</code>.</p>
|
||||||
|
<div class="sourceCode" id="cb2"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> w, h;</span>
|
||||||
|
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span>(<span class="dt">unsigned</span> <span class="dt">int</span> i = <span class="dv">0</span>; i < <span class="dv">6</span>; i++)</span>
|
||||||
|
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>{</span>
|
||||||
|
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">unsigned</span> <span class="dt">char</span>* image = SOIL_load_image(filepath, &w, &h, <span class="dv">0</span>, SOIL_LOAD_RGBA);</span>
|
||||||
|
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> glTexImage2D(</span>
|
||||||
|
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, </span>
|
||||||
|
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="dv">0</span>, GL_RGBA, w, h, <span class="dv">0</span>, GL_RGBA, GL_UNSIGNED_BYTE, image</span>
|
||||||
|
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> );</span>
|
||||||
|
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
|
||||||
|
<p>Na koniec pozostaje ustawić parametry opisujące zachowanie tekstury:</p>
|
||||||
|
<div class="sourceCode" id="cb3"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);</span>
|
||||||
|
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);</span>
|
||||||
|
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);</span>
|
||||||
|
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);</span>
|
||||||
|
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); </span></code></pre></div>
|
||||||
|
<h3 id="zadanie-1">Zadanie*</h3>
|
||||||
|
<p>Napisz funkcję, która będzie ładować cubmapę bazującą na tablicy 6 stringów i załaduj do niej tekstury z foldera <code>skybox</code>.</p>
|
||||||
|
<h3 id="rysowanie-skyboxa">Rysowanie skyboxa</h3>
|
||||||
|
<p>Skybox jest sześcianem, wewnątrz którego zamieszamy naszą scenę, przedstawia on dalekie tło, dzięki temu dostajemy iluzję głębi i przestrzeni. Do tego potrzebujemy narysować sześcian i narysować go odpowiednim shaderem. Rysowanie jest bardzo proste, polega wyłącznie na wyświetleniu koloru tekstury. Aby próbkować, teksturę potrzebujemy przesłać pozycję w przestrzeni modelu do shadera fragmentów.</p>
|
||||||
|
<div class="sourceCode" id="cb4"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">version 430 core</span></span>
|
||||||
|
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>layout(location = <span class="dv">0</span>) in vec3 vertexPosition;</span>
|
||||||
|
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>uniform mat4 transformation;</span>
|
||||||
|
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>out vec3 texCoord;</span>
|
||||||
|
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main()</span>
|
||||||
|
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>{</span>
|
||||||
|
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a> texCoord = vertexPosition;</span>
|
||||||
|
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a> gl_Position = transformation * vec4(vertexPosition, <span class="fl">1.0</span>);</span>
|
||||||
|
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
|
||||||
|
<blockquote>
|
||||||
|
<p>shader_skybox.vert</p>
|
||||||
|
</blockquote>
|
||||||
|
<p>W shaderze fragmentów wystarczy odebrać pozycję i próbkować za jej pomocą teksturę.</p>
|
||||||
|
<div class="sourceCode" id="cb5"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#</span><span class="er">version 430 core</span></span>
|
||||||
|
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>uniform samplerCube skybox;</span>
|
||||||
|
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>in vec3 texCoord;</span>
|
||||||
|
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>out vec4 out_color;</span>
|
||||||
|
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
|
||||||
|
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> main()</span>
|
||||||
|
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>{</span>
|
||||||
|
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a> out_color = texture(skybox,texCoord);</span>
|
||||||
|
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
|
||||||
|
<blockquote>
|
||||||
|
<p>shader_skybox.frag</p>
|
||||||
|
</blockquote>
|
||||||
|
<h3 id="zadanie-2">Zadanie*</h3>
|
||||||
|
<p>W modelach znajduje się <code>cube.obj</code>, załaduj go i narysuj shaderami <code>shader_skybox.vert</code> i <code>shader_skybox.vert</code>. Pamiętaj o przesłaniu macierzy transformacji i tekstury skyboxa. Aktywujemy ją za pomocą instrukcji:</p>
|
||||||
|
<div class="sourceCode" id="cb6"><pre class="sourceCode c++"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);</span></code></pre></div>
|
||||||
|
<p>Skybox potencjalnie zasłania pewne obiekty, które są umieszczone trochę dalej. Wynika to z tego, że renderowanie go nadpisuje bufor głębokości. Dlatego narysuj cubemapę z wyłączonym testem głębokości na samym początku. Następnie włącz test głębokości dla reszty sceny. Dezaktywację wykonasz za pomocą instrukcji <code>glDisable(GL_DEPTH_TEST);</code>, natomiast aktywację za pomocą<code>glEnable(GL_DEPTH_TEST);</code>.</p>
|
||||||
|
<p>Skybox reprezentuje obiekty, które są bardzo daleko. Tę iluzję możemy utracić, gdy kamera przysunie się zbyt blisko do skyboxa. Aby tego uniknąć, musimy tak umieścić skybox, by kamera zawsze była w jego środku. Przesuń skybox do pozycji kamery z użyciem macierzy translacji.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
148
grk/cw 6/Zadania 7.md
Normal file
148
grk/cw 6/Zadania 7.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# Normal Mapping
|
||||||
|
|
||||||
|
W tej części będziemy dalej modyfikować shadery **shader_5_tex** poprzez implementację normal mappingu.
|
||||||
|
|
||||||
|
Obliczenia dla map normalnych należy wykonywać w przestrzeni stycznych. Przestrzeń styczna jest wyliczana dla każdego punktu w obiekcie. Jej celem jest takie przekształcenie przestrzeni, żeby wektor normalny był wektorem jednostkowym (0,1,0).
|
||||||
|
|
||||||
|
Do wyliczenia przestrzeni stycznej potrzebujemy dla każdego wierzchołka oprócz wektora normalnego wektor styczny i bistyczny (*tangent* i *bitangent*). Są one wyliczane przez bibliotekę `Assimp`.
|
||||||
|
|
||||||
|
### Wykonaj kopię shaderów shader_4_tex.vert shader_4_tex.frag
|
||||||
|
|
||||||
|
### Przenieś obliczenia światła do przestrzeni stycznej.
|
||||||
|
|
||||||
|
1) Oblicz macierz **TBN**.
|
||||||
|
|
||||||
|
Macierz **TBN** to macierz 3x3 wyznaczana przez wektory *tangent*, *bitangent* i *normal*, służy do przenoszenia wektorów z przestrzeni świata do przestrzeni stycznej.
|
||||||
|
|
||||||
|
1. W **vertex shaderze** przekrztałć wektory `vertexNormal`, `vertexTangent` i `vertexBitangent` do przestrzeni świata (przemnóż macierz modelu przez te wektory, tak jak to robiliśmy wcześniej z wektorem normalnym, z uwzględnieniem zmiennej w=0) i zapisz wyniki odpowiednio w zmiennych `normal`, `tangent` i `bitangent`.
|
||||||
|
1. Stwórz macierz 3x3 TBN jako transpose(mat3(tangent, bitangent, normal)). Macierz transponujemy, aby szybko uzyskać jej odwrotność (możemy tak zrobić przy założeniu, ze jest ortogonalna).
|
||||||
|
|
||||||
|
2. Przenieś wektor światła i wektor widoku do przestrzeni stycznych
|
||||||
|
1. Musimy przekształcić wektor światła (L) i wektor widoku (V) do przestrzeni stycznych. Zrobimy to w vertex shaderze. W tym celu przenieś potrzebne dane dotyczące światła i kamery (uniformy `lightPos` i `cameraPos`) z **fragment shadera** do **vertex shadera.**
|
||||||
|
|
||||||
|
2. Oblicz wektor `viewDir` jako znormalizowana różnice `cameraPos` i `fragPos` (tu jeszcze działamy w przestrzeni świata). Analogicznie oblicz `lightDir` jako różnicę `lightPos` i `fragPos`
|
||||||
|
|
||||||
|
3. Przekształć wektory `viewDir` i `lightDir` do przestrzeni stycznej mnożąc je przez macierz **TBN**. Wynik zapisz w zmiennych`viewDirTS` i `lightDirTS` odpowiednio.
|
||||||
|
|
||||||
|
4. Przekaż `viewDirTS` i `lightDirTS` do fragment shadera. (zadeklaruj je jako zmienne `out`)
|
||||||
|
|
||||||
|
> (Sufiks TS oznacza tangent space. Ważne jest, aby oznaczać (np. dopisując coś do nazwy zmiennej) w jakiej przestrzeni znajdują się używane wektory, tak aby poprawnie wykonywać obliczenia. Trzeba zawsze zwracać uwagę na to, w jakiej przestrzeni działamy.)
|
||||||
|
|
||||||
|
3. Przekształć **fragment shader**, by obsługiwał **tangent space**
|
||||||
|
1. Nie potrzebujemy już we **fragment shaderze** informacji na temat pozycji fragmentu i wektora normalnego geometrii, skasuj wiec zmienne przekazujące te wektory pomiędzy shaderami.
|
||||||
|
2. wektora `lightDir` powinniśmy użyć wektora `lightDirTS` (należy go dodatkowo znormalizować), a jako wektor widoku V powinniśmy użyć wektora `viewDirTS` (również należy go znormalizować). Jako wektora N użyj na razie wektora vec3(0,0,1).
|
||||||
|
|
||||||
|
Efekt finalny powinien wyglądać tak samo, jak przed jakąkolwiek zmianą. Następnym krokiem będzie wykorzystanie map normalnych.
|
||||||
|
|
||||||
|
### Wykorzystaj normalmapy
|
||||||
|
|
||||||
|
1. Chcemy wczytywać normalne z tekstury, w tym celu dodaj we **fragment shaderze** dodatkowy sampler do czytania map normalnych, nazwij go `normalSampler`. Pobierz z niego wektor normalny analogicznie, jak czytamy kolor zwykłej tekstury z samplera `textureSampler` i zapisz go w zmiennej `N`.
|
||||||
|
2. Ponieważ w teksturze wartości są w przedziale $[0,1]$, musimy jeszcze przekształcić je do przedziału $[-1,1]$. W tym celu przemnóż wektor N przez 2 i odejmij 1.
|
||||||
|
Na koniec warto jeszcze znormalizować wektor normalny, aby uniknąć błędów związanych z precyzja lub kompresja tekstury.
|
||||||
|
3. Wczytaj pliki zawierające mapy normalnych w kodzie C++ W tym celu załaduj przy użyciu funkcji `Core::LoadTexture` mapy normalnych dla wszystkich modeli. Maja one taką samą nazwę jak zwykle tekstury, tyle że z suffiksem "_normals".
|
||||||
|
4. Zmodyfikuj na koniec funkcje `drawObjectTexture`. Dodaj do niej nowy argument `GLuint normalmapId`, który będzie służył do przekazywania id tekstury zawierającej mapę normalnych. Przy użyciu funkcji `Core::SetActiveTexture` załaduj `normalmapId` jako `normalSampler` i ustaw jednostkę teksturowania nr 1.
|
||||||
|
Argument odpowiadający za normalne w miejscach wywołania funkcji `drawObjectTexture`.
|
||||||
|
|
||||||
|
|
||||||
|
### Zadanie*
|
||||||
|
Ustaw mapy normalne do statku planety i księżyca (lub przynajmniej 3 obiektów, jeżeli rysujesz swoją scenę). Wykorzystaj multitexturing na statku, musisz w takim wypadku mieszać zarówno tekstury koloru i normalanych.
|
||||||
|
|
||||||
|
## SkyBox
|
||||||
|
Cubemapy są specjalnym rodzajem tekstur. Zawieją one 6 tekstur, każda z niej odpowiada za inną ścianę sześcianu. Nie służy ona do teksturowania zwykłego sześcianu, pozwala ona bowiem próbkować po wektorze kierunku. To znaczy, możemy o tym myśleć jak o kostce, w której środku się znaleźliśmy, co obrazuje poniższy rysunek. W przeciwieństwie do zwykłych tekstur samplujemy ją nie za pomocą dwuwymiarowych współrzędnych UV, ale za pomocą wektora trójwymiarowego, który odpowiada kierunkowi promienia.
|
||||||
|
![](./img/cubemaps_sampling.png)
|
||||||
|
Jednym z zastosowań Cubemapy jest wyświetlanie skyboxa, czyli dalekiego tła dla sceny. Może to być na przykład rozgwieżdżone niebo z górami na horyzoncie albo obraz dalekiej galaktyki.
|
||||||
|
|
||||||
|
### Ładowanie cubemapy
|
||||||
|
Cubemapę generujemy podobnie jak inne tekstury, ale przy bindowaniu należy podać `GL_TEXTURE_CUBE_MAP`.
|
||||||
|
```C++
|
||||||
|
glGenTextures(1, &textureID);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||||
|
```
|
||||||
|
Skoro składa się ona z 6 tekstur, to należy każdą z nich załadować za pomocą `void glTexImage2D( GLenum target, ...)` `taget` wskazuje którą z tekstur ładujemy. Możliwe wartości rozpisane są w tabeli poniżej
|
||||||
|
|Layer number|Texture target | Orientation|
|
||||||
|
|----|--------------------:|-----------:|
|
||||||
|
|0|`GL_TEXTURE_CUBE_MAP_POSITIVE_X` | Right |
|
||||||
|
|1|`GL_TEXTURE_CUBE_MAP_NEGATIVE_X`|Left|
|
||||||
|
|2|`GL_TEXTURE_CUBE_MAP_POSITIVE_Y`|Top|
|
||||||
|
|3|`GL_TEXTURE_CUBE_MAP_NEGATIVE_Y`|Bottom|
|
||||||
|
|4|`GL_TEXTURE_CUBE_MAP_POSITIVE_Z`|Back|
|
||||||
|
|5|`GL_TEXTURE_CUBE_MAP_NEGATIVE_Z`|Front|
|
||||||
|
|
||||||
|
Możemy je ładować w pętli biorąc za kolejne targety `GL_TEXTURE_CUBE_MAP_POSITIVE_X+i`, ale należy pamiętać o powyższej kolejności. Poniższy kod ładuje do wszystkich 6 ścian tę samą teksturę, która znajduje się pod `filepath`.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
unsigned char *data;
|
||||||
|
for(unsigned int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
unsigned char* image = SOIL_load_image(filepath, &w, &h, 0, SOIL_LOAD_RGBA);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||||
|
0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Na koniec pozostaje ustawić parametry opisujące zachowanie tekstury:
|
||||||
|
```C++
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zadanie
|
||||||
|
Napisz funkcję, która będzie ładować cubmapę bazującą na tablicy 6 stringów i załaduj do niej tekstury z foldera `skybox`.
|
||||||
|
|
||||||
|
### Rysowanie skyboxa
|
||||||
|
Skybox jest sześcianem, wewnątrz którego zamieszamy naszą scenę, przedstawia on dalekie tło, dzięki temu dostajemy iluzję głębi i przestrzeni. Do tego potrzebujemy narysować sześcian i narysować go odpowiednim shaderem. Rysowanie jest bardzo proste, polega wyłącznie na wyświetleniu koloru tekstury. Aby próbkować, teksturę potrzebujemy przesłać pozycję w przestrzeni modelu do shadera fragmentów.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
|
||||||
|
out vec3 texCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
texCoord = vertexPosition;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
> shader_skybox.vert
|
||||||
|
|
||||||
|
W shaderze fragmentów wystarczy odebrać pozycję i próbkować za jej pomocą teksturę.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
uniform samplerCube skybox;
|
||||||
|
|
||||||
|
in vec3 texCoord;
|
||||||
|
|
||||||
|
out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
out_color = texture(skybox,texCoord);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
> shader_skybox.frag
|
||||||
|
|
||||||
|
### Zadanie
|
||||||
|
W modelach znajduje się `cube.obj`, załaduj go i narysuj shaderami `shader_skybox.vert` i `shader_skybox.vert`. Pamiętaj o przesłaniu macierzy transformacji i tekstury skyboxa. Aktywujemy ją za pomocą instrukcji:
|
||||||
|
```C++
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
|
||||||
|
```
|
||||||
|
|
||||||
|
Skybox potencjalnie zasłania pewne obiekty, które są umieszczone trochę dalej. Wynika to z tego, że renderowanie go nadpisuje bufor głębokości. Dlatego narysuj cubemapę z wyłączonym testem głębokości na samym początku. Następnie włącz test głębokości dla reszty sceny.
|
||||||
|
Dezaktywację wykonasz za pomocą instrukcji `glDisable(GL_DEPTH_TEST);`, natomiast aktywację za pomocą`glEnable(GL_DEPTH_TEST);`.
|
||||||
|
|
||||||
|
Skybox reprezentuje obiekty, które są bardzo daleko. Tę iluzję możemy utracić, gdy kamera przysunie się zbyt blisko do skyboxa. Aby tego uniknąć, musimy tak umieścić skybox, by kamera zawsze była w jego środku. Przesuń skybox do pozycji kamery z użyciem macierzy translacji.
|
||||||
|
|
@ -38,10 +38,16 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="shaders\shader.frag" />
|
<None Include="shaders\shader.frag" />
|
||||||
<None Include="shaders\shader.vert" />
|
<None Include="shaders\shader.vert" />
|
||||||
|
<None Include="shaders\shader_skybox.frag" />
|
||||||
|
<None Include="shaders\shader_skybox.vert" />
|
||||||
|
<None Include="shaders\shader_smap.frag" />
|
||||||
|
<None Include="shaders\shader_smap.vert" />
|
||||||
<None Include="shaders\shader_tex.frag" />
|
<None Include="shaders\shader_tex.frag" />
|
||||||
<None Include="shaders\shader_tex.vert" />
|
<None Include="shaders\shader_tex.vert" />
|
||||||
<None Include="shaders\shader_sun.frag" />
|
<None Include="shaders\shader_sun.frag" />
|
||||||
<None Include="shaders\shader_sun.vert" />
|
<None Include="shaders\shader_sun.vert" />
|
||||||
|
<None Include="shaders\test.frag" />
|
||||||
|
<None Include="shaders\test.vert" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{3952C396-B1C6-44CD-96DD-C1AC15D32978}</ProjectGuid>
|
<ProjectGuid>{3952C396-B1C6-44CD-96DD-C1AC15D32978}</ProjectGuid>
|
||||||
|
@ -106,5 +106,23 @@
|
|||||||
<None Include="shaders\shader_tex.frag">
|
<None Include="shaders\shader_tex.frag">
|
||||||
<Filter>Shader Files</Filter>
|
<Filter>Shader Files</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="shaders\test.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\test.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_smap.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_smap.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_skybox.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_skybox.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
40
grk/cw 6/models/cube.obj
Normal file
40
grk/cw 6/models/cube.obj
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Blender v2.90.0 OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
mtllib cube.mtl
|
||||||
|
o Cube
|
||||||
|
v -10.000000 -10.000000 10.000000
|
||||||
|
v -10.000000 10.000000 10.000000
|
||||||
|
v -10.000000 -10.000000 -10.000000
|
||||||
|
v -10.000000 10.000000 -10.000000
|
||||||
|
v 10.000000 -10.000000 10.000000
|
||||||
|
v 10.000000 10.000000 10.000000
|
||||||
|
v 10.000000 -10.000000 -10.000000
|
||||||
|
v 10.000000 10.000000 -10.000000
|
||||||
|
vt 0.375000 0.000000
|
||||||
|
vt 0.625000 0.000000
|
||||||
|
vt 0.625000 0.250000
|
||||||
|
vt 0.375000 0.250000
|
||||||
|
vt 0.625000 0.500000
|
||||||
|
vt 0.375000 0.500000
|
||||||
|
vt 0.625000 0.750000
|
||||||
|
vt 0.375000 0.750000
|
||||||
|
vt 0.625000 1.000000
|
||||||
|
vt 0.375000 1.000000
|
||||||
|
vt 0.125000 0.500000
|
||||||
|
vt 0.125000 0.750000
|
||||||
|
vt 0.875000 0.500000
|
||||||
|
vt 0.875000 0.750000
|
||||||
|
vn -1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn 0.0000 -1.0000 0.0000
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
usemtl _PBR
|
||||||
|
s 1
|
||||||
|
f 1/1/1 2/2/1 4/3/1 3/4/1
|
||||||
|
f 3/4/2 4/3/2 8/5/2 7/6/2
|
||||||
|
f 7/6/3 8/5/3 6/7/3 5/8/3
|
||||||
|
f 5/8/4 6/7/4 2/9/4 1/10/4
|
||||||
|
f 3/11/5 7/6/5 5/8/5 1/12/5
|
||||||
|
f 8/5/6 4/13/6 2/14/6 6/7/6
|
@ -1,21 +0,0 @@
|
|||||||
#version 430 core
|
|
||||||
|
|
||||||
float AMBIENT = 0.1;
|
|
||||||
|
|
||||||
uniform vec3 color;
|
|
||||||
uniform vec3 lightPos;
|
|
||||||
uniform vec3 lightDir;
|
|
||||||
|
|
||||||
in vec3 vecNormal;
|
|
||||||
in vec3 worldPos;
|
|
||||||
|
|
||||||
out vec4 outColor;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
//vec3 lightDir = normalize(lightPos - worldPos);
|
|
||||||
|
|
||||||
vec3 normal = normalize(vecNormal);
|
|
||||||
float diffuse = max(0, dot(normal, lightDir));
|
|
||||||
outColor = vec4(color * min(1, AMBIENT + diffuse), 1.0);
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
#version 430 core
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 vertexPosition;
|
|
||||||
layout(location = 1) in vec3 vertexNormal;
|
|
||||||
layout(location = 2) in vec2 vertexTexCoord;
|
|
||||||
|
|
||||||
uniform mat4 transformation;
|
|
||||||
uniform mat4 modelMatrix;
|
|
||||||
|
|
||||||
out vec3 vecNormal;
|
|
||||||
out vec3 worldPos;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
worldPos = (modelMatrix * vec4(vertexPosition,1)).xyz;
|
|
||||||
vecNormal = (modelMatrix * vec4(vertexNormal,0)).xyz;
|
|
||||||
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
|
||||||
}
|
|
14
grk/cw 6/shaders/shader_skybox.frag
Normal file
14
grk/cw 6/shaders/shader_skybox.frag
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 430 core
|
||||||
|
|
||||||
|
uniform samplerCube skybox;
|
||||||
|
uniform vec3 lightColor;
|
||||||
|
|
||||||
|
in vec3 texCoord;
|
||||||
|
|
||||||
|
out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 textureColor = texture(skybox, texCoord);
|
||||||
|
out_color = vec4(vec3(textureColor) * lightColor * 0.03f, 1.0f);
|
||||||
|
}
|
13
grk/cw 6/shaders/shader_skybox.vert
Normal file
13
grk/cw 6/shaders/shader_skybox.vert
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
|
||||||
|
out vec3 texCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
texCoord = vertexPosition;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
float AMBIENT = 0.1;
|
float AMBIENT = 0.1;
|
||||||
|
|
||||||
uniform vec3 lightPos;
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 lightColor;
|
||||||
|
|
||||||
in vec3 vecNormal;
|
in vec3 vecNormal;
|
||||||
in vec3 worldPos;
|
in vec3 worldPos;
|
||||||
@ -18,5 +19,5 @@ void main()
|
|||||||
vec3 normal = normalize(vecNormal);
|
vec3 normal = normalize(vecNormal);
|
||||||
|
|
||||||
vec4 textureColor = texture2D(colorTexture, vtc);
|
vec4 textureColor = texture2D(colorTexture, vtc);
|
||||||
outColor = vec4(vec3(textureColor) * 1.5, 1.0);
|
outColor = vec4(vec3(textureColor) * lightColor * 0.015f, 1.0);
|
||||||
}
|
}
|
@ -57,14 +57,15 @@ namespace textureMaterials {
|
|||||||
GLuint clouds;
|
GLuint clouds;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
GLuint program;
|
|
||||||
GLuint programSun;
|
GLuint programSun;
|
||||||
GLuint programDepth;
|
GLuint programDepth;
|
||||||
GLuint programTex;
|
GLuint programTex;
|
||||||
|
GLuint programSkyBox;
|
||||||
|
|
||||||
Core::Shader_Loader shaderLoader;
|
Core::Shader_Loader shaderLoader;
|
||||||
|
|
||||||
Core::RenderContext sphereContext;
|
Core::RenderContext sphereContext;
|
||||||
|
Core::RenderContext cubeContext;
|
||||||
|
|
||||||
const char* const planetTexPaths[] = { "./textures/planets/earth.png", "./textures/planets/mercury.png", "./textures/planets/venus.jpg", "./textures/planets/mars.jpg",
|
const char* const planetTexPaths[] = { "./textures/planets/earth.png", "./textures/planets/mercury.png", "./textures/planets/venus.jpg", "./textures/planets/mars.jpg",
|
||||||
"./textures/planets/jupiter.jpg", "./textures/planets/saturn.jpg", "./textures/planets/uranus.jpg", "./textures/planets/neptune.jpg", "./textures/planets/icy.png",
|
"./textures/planets/jupiter.jpg", "./textures/planets/saturn.jpg", "./textures/planets/uranus.jpg", "./textures/planets/neptune.jpg", "./textures/planets/icy.png",
|
||||||
@ -82,8 +83,15 @@ const char* const sunTexPaths[] = { "./textures/suns/sol.jpg", "./textures/suns/
|
|||||||
int sunTexIndex = 20;
|
int sunTexIndex = 20;
|
||||||
GLuint sunTex;
|
GLuint sunTex;
|
||||||
|
|
||||||
glm::vec3 sunPos = glm::vec3(12.f, 0.f, 12.f);
|
glm::vec3 sunPos = glm::vec3(20.f, 0.f, 20.f);
|
||||||
float sunSize = 0.04f;
|
float sunSize = 0.05f;
|
||||||
|
|
||||||
|
const char* skyBoxPaths[] = { "./textures/skybox/space_rt.png", "./textures/skybox/space_lf.png", "./textures/skybox/space_up.png", "./textures/skybox/space_dn.png",
|
||||||
|
"./textures/skybox/space_bk.png", "./textures/skybox/space_ft.png" };
|
||||||
|
GLuint skyBoxTex;
|
||||||
|
|
||||||
|
glm::vec3 skyBoxPos = glm::vec3(0.f, 0.f, 0.f);
|
||||||
|
float skyBoxSize = 3.f;
|
||||||
|
|
||||||
glm::vec3 cameraPos = glm::vec3(-2.f, 0.f, 0.f);
|
glm::vec3 cameraPos = glm::vec3(-2.f, 0.f, 0.f);
|
||||||
glm::vec3 cameraDir = glm::vec3(1.f, 0.f, 0.f);
|
glm::vec3 cameraDir = glm::vec3(1.f, 0.f, 0.f);
|
||||||
@ -100,7 +108,7 @@ unsigned int depthMapFBO;
|
|||||||
int HDR_WIDTH = 1024;
|
int HDR_WIDTH = 1024;
|
||||||
int HDR_HEIGHT = 1024;
|
int HDR_HEIGHT = 1024;
|
||||||
|
|
||||||
float lightPower = 50.f;
|
float lightPower = 100.f;
|
||||||
glm::vec3 lightColor = glm::vec3(lightPower, lightPower, lightPower);
|
glm::vec3 lightColor = glm::vec3(lightPower, lightPower, lightPower);
|
||||||
|
|
||||||
glm::mat4 createCameraMatrix() {
|
glm::mat4 createCameraMatrix() {
|
||||||
@ -123,8 +131,8 @@ glm::mat4 createCameraMatrix() {
|
|||||||
|
|
||||||
glm::mat4 createPerspectiveMatrix() {
|
glm::mat4 createPerspectiveMatrix() {
|
||||||
glm::mat4 perspectiveMatrix;
|
glm::mat4 perspectiveMatrix;
|
||||||
float n = 0.05f;
|
float n = 0.01f;
|
||||||
float f = 20.f;
|
float f = 200.f;
|
||||||
float fov = 105.f;
|
float fov = 105.f;
|
||||||
float PI = 3.14159265359f;
|
float PI = 3.14159265359f;
|
||||||
float S = 1 / (tan((fov / 2) * (PI / 180)));
|
float S = 1 / (tan((fov / 2) * (PI / 180)));
|
||||||
@ -182,7 +190,7 @@ void initDepthMap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void drawObjectTexture(Core::RenderContext& context, glm::mat4 modelMatrix, GLuint texture) {
|
void drawPlanet(Core::RenderContext& context, glm::mat4 modelMatrix, GLuint texture) {
|
||||||
glUseProgram(programTex);
|
glUseProgram(programTex);
|
||||||
Core::SetActiveTexture(texture, "colorTexture", programTex, 0);
|
Core::SetActiveTexture(texture, "colorTexture", programTex, 0);
|
||||||
glm::mat4 viewProjectionMatrix = createPerspectiveMatrix() * createCameraMatrix();
|
glm::mat4 viewProjectionMatrix = createPerspectiveMatrix() * createCameraMatrix();
|
||||||
@ -203,6 +211,19 @@ void drawSun(Core::RenderContext& context, glm::mat4 modelMatrix, GLuint texture
|
|||||||
glUniformMatrix4fv(glGetUniformLocation(programSun, "transformation"), 1, GL_FALSE, (float*)&transformation);
|
glUniformMatrix4fv(glGetUniformLocation(programSun, "transformation"), 1, GL_FALSE, (float*)&transformation);
|
||||||
glUniformMatrix4fv(glGetUniformLocation(programSun, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
|
glUniformMatrix4fv(glGetUniformLocation(programSun, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
|
||||||
glUniform3f(glGetUniformLocation(programSun, "lightPos"), sunPos.x, sunPos.y, sunPos.z);
|
glUniform3f(glGetUniformLocation(programSun, "lightPos"), sunPos.x, sunPos.y, sunPos.z);
|
||||||
|
glUniform3f(glGetUniformLocation(programSun, "lightColor"), lightColor.x, lightColor.y, lightColor.z);
|
||||||
|
Core::DrawContext(context);
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawSkyBox(Core::RenderContext& context, glm::mat4 modelMatrix, GLuint texture) {
|
||||||
|
glUseProgram(programSkyBox);
|
||||||
|
Core::SetActiveSkyBox(texture, "skybox", programSkyBox, 0);
|
||||||
|
glm::mat4 viewProjectionMatrix = createPerspectiveMatrix() * createCameraMatrix();
|
||||||
|
glm::mat4 transformation = viewProjectionMatrix * modelMatrix;
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(programSkyBox, "transformation"), 1, GL_FALSE, (float*)&transformation);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(programSkyBox, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
|
||||||
|
glUniform3f(glGetUniformLocation(programSkyBox, "lightColor"), lightColor.x, lightColor.y, lightColor.z);
|
||||||
Core::DrawContext(context);
|
Core::DrawContext(context);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
}
|
}
|
||||||
@ -238,21 +259,30 @@ void drawObjectPBR(Core::RenderContext& context, glm::mat4 modelMatrix, glm::vec
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
void renderScene(GLFWwindow* window) {
|
void renderScene(GLFWwindow* window) {
|
||||||
glClearColor(0.0f, 0.0f, 0.15f, 1.0f);
|
glClearColor(0.5f, 0.0f, 0.25f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
float time = glfwGetTime();
|
float time = glfwGetTime();
|
||||||
|
|
||||||
|
//rysowanie planety
|
||||||
glm::mat4 planetScale = glm::scale(glm::vec3(planetSize));
|
glm::mat4 planetScale = glm::scale(glm::vec3(planetSize));
|
||||||
glm::mat4 planetRotate = glm::rotate(time * planetRot, glm::vec3(0, 1, 0));
|
glm::mat4 planetRotate = glm::rotate(time * planetRot, glm::vec3(0, 1, 0));
|
||||||
glm::mat4 planetTranslate = glm::translate(planetPos);
|
glm::mat4 planetTranslate = glm::translate(planetPos);
|
||||||
|
|
||||||
drawObjectTexture(sphereContext, planetTranslate * planetRotate * planetScale, planetTex);
|
drawPlanet(sphereContext, planetTranslate * planetRotate * planetScale, planetTex);
|
||||||
|
|
||||||
|
//rysowanie słońca
|
||||||
glm::mat4 sunScale = glm::scale(glm::vec3(sunSize));
|
glm::mat4 sunScale = glm::scale(glm::vec3(sunSize));
|
||||||
glm::mat4 sunTranslate = glm::translate(sunPos);
|
glm::mat4 sunTranslate = glm::translate(sunPos);
|
||||||
|
|
||||||
drawSun(sphereContext, sunTranslate * sunScale, sunTex);
|
drawSun(sphereContext, sunTranslate * sunScale, sunTex);
|
||||||
|
|
||||||
|
//rysowanie skyboxa
|
||||||
|
skyBoxPos = cameraPos;
|
||||||
|
glm::mat4 skyBoxScale = glm::scale(glm::vec3(skyBoxSize));
|
||||||
|
glm::mat4 skyBoxTranslate = glm::translate(skyBoxPos);
|
||||||
|
|
||||||
|
drawSkyBox(cubeContext, skyBoxTranslate * skyBoxScale, skyBoxTex);
|
||||||
|
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +307,7 @@ void init(GLFWwindow* window) {
|
|||||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
//glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
//initDepthMap();
|
//initDepthMap();
|
||||||
initHDR();
|
initHDR();
|
||||||
@ -284,17 +315,22 @@ void init(GLFWwindow* window) {
|
|||||||
programDepth = shaderLoader.CreateProgram("shaders/shader_smap.vert", "shaders/shader_smap.frag");
|
programDepth = shaderLoader.CreateProgram("shaders/shader_smap.vert", "shaders/shader_smap.frag");
|
||||||
programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
|
programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
|
||||||
programSun = shaderLoader.CreateProgram("shaders/shader_sun.vert", "shaders/shader_sun.frag");
|
programSun = shaderLoader.CreateProgram("shaders/shader_sun.vert", "shaders/shader_sun.frag");
|
||||||
|
programSkyBox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag");
|
||||||
|
|
||||||
loadModelToContext("./models/sphere.obj", sphereContext);
|
loadModelToContext("./models/sphere.obj", sphereContext);
|
||||||
|
loadModelToContext("./models/cube.obj", cubeContext);
|
||||||
|
|
||||||
planetTex = Core::LoadTexture(planetTexPaths[std::abs(planetTexIndex % 20)]);
|
planetTex = Core::LoadTexture(planetTexPaths[std::abs(planetTexIndex % 20)]);
|
||||||
sunTex = Core::LoadTexture(sunTexPaths[std::abs(sunTexIndex % 5)]);
|
sunTex = Core::LoadTexture(sunTexPaths[std::abs(sunTexIndex % 5)]);
|
||||||
|
|
||||||
|
skyBoxTex = Core::LoadSkyBox(skyBoxPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shutdown(GLFWwindow* window) {
|
void shutdown(GLFWwindow* window) {
|
||||||
shaderLoader.DeleteProgram(programDepth);
|
shaderLoader.DeleteProgram(programDepth);
|
||||||
shaderLoader.DeleteProgram(programTex);
|
shaderLoader.DeleteProgram(programTex);
|
||||||
shaderLoader.DeleteProgram(programSun);
|
shaderLoader.DeleteProgram(programSun);
|
||||||
|
shaderLoader.DeleteProgram(programSkyBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
//obsluga wejscia
|
//obsluga wejscia
|
||||||
@ -356,11 +392,11 @@ void processInput(GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//siła światła
|
//siła światła
|
||||||
float powerSpeed = 0.5f;
|
float powerSpeed = 1.f;
|
||||||
|
|
||||||
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS && lightPower < 250.f)
|
if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS && lightPower < 300.f)
|
||||||
lightPower += powerSpeed;
|
lightPower += powerSpeed;
|
||||||
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS && lightPower > 0.5f)
|
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS && lightPower > 10.f)
|
||||||
lightPower -= powerSpeed;
|
lightPower -= powerSpeed;
|
||||||
|
|
||||||
lightColor = glm::vec3(lightPower, lightPower, lightPower);
|
lightColor = glm::vec3(lightPower, lightPower, lightPower);
|
||||||
|
@ -29,7 +29,29 @@ GLuint Core::LoadTexture( const char * filepath )
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint Core::LoadSkyBox( const char ** filepath )
|
||||||
|
{
|
||||||
|
GLuint id;
|
||||||
|
glGenTextures(1, &id);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
for (unsigned int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
unsigned char* image = SOIL_load_image(filepath[i], &w, &h, 0, SOIL_LOAD_RGBA);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
|
||||||
|
0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
void Core::SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit)
|
void Core::SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit)
|
||||||
{
|
{
|
||||||
@ -37,3 +59,10 @@ void Core::SetActiveTexture(GLuint textureID, const char * shaderVariableName, G
|
|||||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||||
glBindTexture(GL_TEXTURE_2D, textureID);
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::SetActiveSkyBox(GLuint textureID, const char* shaderVariableName, GLuint programID, int textureUnit)
|
||||||
|
{
|
||||||
|
glUniform1i(glGetUniformLocation(programID, shaderVariableName), textureUnit);
|
||||||
|
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
|
||||||
|
}
|
@ -6,10 +6,11 @@
|
|||||||
namespace Core
|
namespace Core
|
||||||
{
|
{
|
||||||
GLuint LoadTexture(const char * filepath);
|
GLuint LoadTexture(const char * filepath);
|
||||||
|
GLuint LoadSkyBox(const char ** filepath);
|
||||||
// textureID - identyfikator tekstury otrzymany z funkcji LoadTexture
|
// textureID - identyfikator tekstury otrzymany z funkcji LoadTexture
|
||||||
// shaderVariableName - nazwa zmiennej typu 'sampler2D' w shaderze, z ktora ma zostac powiazana tekstura
|
// shaderVariableName - nazwa zmiennej typu 'sampler2D' w shaderze, z ktora ma zostac powiazana tekstura
|
||||||
// programID - identyfikator aktualnego programu karty graficznej
|
// programID - identyfikator aktualnego programu karty graficznej
|
||||||
// textureUnit - indeks jednostki teksturujacej - liczba od 0 do 7. Jezeli uzywa sie wielu tekstur w jednym shaderze, to kazda z nich nalezy powiazac z inna jednostka.
|
// textureUnit - indeks jednostki teksturujacej - liczba od 0 do 7. Jezeli uzywa sie wielu tekstur w jednym shaderze, to kazda z nich nalezy powiazac z inna jednostka.
|
||||||
void SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
|
void SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
|
||||||
|
void SetActiveSkyBox(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
|
||||||
}
|
}
|
BIN
grk/cw 6/textures/skybox/space_bk.png
Normal file
BIN
grk/cw 6/textures/skybox/space_bk.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 KiB |
BIN
grk/cw 6/textures/skybox/space_dn.png
Normal file
BIN
grk/cw 6/textures/skybox/space_dn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 636 KiB |
BIN
grk/cw 6/textures/skybox/space_ft.png
Normal file
BIN
grk/cw 6/textures/skybox/space_ft.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 545 KiB |
BIN
grk/cw 6/textures/skybox/space_lf.png
Normal file
BIN
grk/cw 6/textures/skybox/space_lf.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 508 KiB |
BIN
grk/cw 6/textures/skybox/space_rt.png
Normal file
BIN
grk/cw 6/textures/skybox/space_rt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 326 KiB |
BIN
grk/cw 6/textures/skybox/space_up.png
Normal file
BIN
grk/cw 6/textures/skybox/space_up.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 507 KiB |
Loading…
Reference in New Issue
Block a user