dodanie skyboxa i drobne poprawki

This commit is contained in:
K4RP4T 2024-01-21 13:34:33 +01:00
parent b89c7784ca
commit 7e63de4e57
19 changed files with 516 additions and 53 deletions

196
grk/cw 6/Zadania 7.html Normal file
View 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>, &amp;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 &lt; <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, &amp;w, &amp;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
View 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.

View File

@ -38,10 +38,16 @@
<ItemGroup>
<None Include="shaders\shader.frag" />
<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.vert" />
<None Include="shaders\shader_sun.frag" />
<None Include="shaders\shader_sun.vert" />
<None Include="shaders\test.frag" />
<None Include="shaders\test.vert" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{3952C396-B1C6-44CD-96DD-C1AC15D32978}</ProjectGuid>

View File

@ -106,5 +106,23 @@
<None Include="shaders\shader_tex.frag">
<Filter>Shader Files</Filter>
</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>
</Project>

40
grk/cw 6/models/cube.obj Normal file
View 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

View File

@ -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);
}

View File

@ -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);
}

View 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);
}

View 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);
}

View File

@ -3,6 +3,7 @@
float AMBIENT = 0.1;
uniform vec3 lightPos;
uniform vec3 lightColor;
in vec3 vecNormal;
in vec3 worldPos;
@ -18,5 +19,5 @@ void main()
vec3 normal = normalize(vecNormal);
vec4 textureColor = texture2D(colorTexture, vtc);
outColor = vec4(vec3(textureColor) * 1.5, 1.0);
outColor = vec4(vec3(textureColor) * lightColor * 0.015f, 1.0);
}

View File

@ -57,14 +57,15 @@ namespace textureMaterials {
GLuint clouds;
}
*/
GLuint program;
GLuint programSun;
GLuint programDepth;
GLuint programTex;
GLuint programSkyBox;
Core::Shader_Loader shaderLoader;
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",
"./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;
GLuint sunTex;
glm::vec3 sunPos = glm::vec3(12.f, 0.f, 12.f);
float sunSize = 0.04f;
glm::vec3 sunPos = glm::vec3(20.f, 0.f, 20.f);
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 cameraDir = glm::vec3(1.f, 0.f, 0.f);
@ -100,7 +108,7 @@ unsigned int depthMapFBO;
int HDR_WIDTH = 1024;
int HDR_HEIGHT = 1024;
float lightPower = 50.f;
float lightPower = 100.f;
glm::vec3 lightColor = glm::vec3(lightPower, lightPower, lightPower);
glm::mat4 createCameraMatrix() {
@ -123,8 +131,8 @@ glm::mat4 createCameraMatrix() {
glm::mat4 createPerspectiveMatrix() {
glm::mat4 perspectiveMatrix;
float n = 0.05f;
float f = 20.f;
float n = 0.01f;
float f = 200.f;
float fov = 105.f;
float PI = 3.14159265359f;
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);
Core::SetActiveTexture(texture, "colorTexture", programTex, 0);
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, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
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);
glUseProgram(0);
}
@ -238,21 +259,30 @@ void drawObjectPBR(Core::RenderContext& context, glm::mat4 modelMatrix, glm::vec
}
*/
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);
float time = glfwGetTime();
//rysowanie planety
glm::mat4 planetScale = glm::scale(glm::vec3(planetSize));
glm::mat4 planetRotate = glm::rotate(time * planetRot, glm::vec3(0, 1, 0));
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 sunTranslate = glm::translate(sunPos);
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);
}
@ -277,6 +307,7 @@ void init(GLFWwindow* window) {
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glEnable(GL_DEPTH_TEST);
//glDisable(GL_DEPTH_TEST);
//initDepthMap();
initHDR();
@ -284,17 +315,22 @@ void init(GLFWwindow* window) {
programDepth = shaderLoader.CreateProgram("shaders/shader_smap.vert", "shaders/shader_smap.frag");
programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.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/cube.obj", cubeContext);
planetTex = Core::LoadTexture(planetTexPaths[std::abs(planetTexIndex % 20)]);
sunTex = Core::LoadTexture(sunTexPaths[std::abs(sunTexIndex % 5)]);
skyBoxTex = Core::LoadSkyBox(skyBoxPaths);
}
void shutdown(GLFWwindow* window) {
shaderLoader.DeleteProgram(programDepth);
shaderLoader.DeleteProgram(programTex);
shaderLoader.DeleteProgram(programSun);
shaderLoader.DeleteProgram(programSkyBox);
}
//obsluga wejscia
@ -356,11 +392,11 @@ void processInput(GLFWwindow* window)
}
//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;
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS && lightPower > 0.5f)
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS && lightPower > 10.f)
lightPower -= powerSpeed;
lightColor = glm::vec3(lightPower, lightPower, lightPower);

View File

@ -29,7 +29,29 @@ GLuint Core::LoadTexture( const char * filepath )
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)
{
@ -37,3 +59,10 @@ void Core::SetActiveTexture(GLuint textureID, const char * shaderVariableName, G
glActiveTexture(GL_TEXTURE0 + textureUnit);
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);
}

View File

@ -6,10 +6,11 @@
namespace Core
{
GLuint LoadTexture(const char * filepath);
GLuint LoadSkyBox(const char ** filepath);
// textureID - identyfikator tekstury otrzymany z funkcji LoadTexture
// shaderVariableName - nazwa zmiennej typu 'sampler2D' w shaderze, z ktora ma zostac powiazana tekstura
// 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.
void SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
void SetActiveSkyBox(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 KiB