pierwsze zmiany widoku i mniejsze zmiany ogólne

This commit is contained in:
Kacper 2024-01-13 22:59:27 +01:00
parent 903bb3eaf8
commit 8afafd933d
87 changed files with 1381 additions and 223 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/grk/.vs/grk-cw/FileContentIndex/1b59ee44-5cea-4c95-9c69-19f8320df4dd.vsidx
/.vs
/grk/.vs/grk-cw/v17

BIN
grk/Debug/Planeta.exe Normal file

Binary file not shown.

BIN
grk/Debug/Planeta.pdb Normal file

Binary file not shown.

273
grk/UpgradeLog.htm Normal file
View File

@ -0,0 +1,273 @@
<!DOCTYPE html>
<!-- saved from url=(0014)about:internet -->
<html xmlns:msxsl="urn:schemas-microsoft-com:xslt"><head><meta content="en-us" http-equiv="Content-Language" /><meta content="text/html; charset=utf-16" http-equiv="Content-Type" /><title _locID="ConversionReport0">
Migration Report
</title><style>
/* Body style, for the entire document */
body
{
background: #F3F3F4;
color: #1E1E1F;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
padding: 0;
margin: 0;
}
/* Header1 style, used for the main title */
h1
{
padding: 10px 0px 10px 10px;
font-size: 21pt;
background-color: #E2E2E2;
border-bottom: 1px #C1C1C2 solid;
color: #201F20;
margin: 0;
font-weight: normal;
}
/* Header2 style, used for "Overview" and other sections */
h2
{
font-size: 18pt;
font-weight: normal;
padding: 15px 0 5px 0;
margin: 0;
}
/* Header3 style, used for sub-sections, such as project name */
h3
{
font-weight: normal;
font-size: 15pt;
margin: 0;
padding: 15px 0 5px 0;
background-color: transparent;
}
/* Color all hyperlinks one color */
a
{
color: #1382CE;
}
/* Table styles */
table
{
border-spacing: 0 0;
border-collapse: collapse;
font-size: 10pt;
}
table th
{
background: #E7E7E8;
text-align: left;
text-decoration: none;
font-weight: normal;
padding: 3px 6px 3px 6px;
}
table td
{
vertical-align: top;
padding: 3px 6px 5px 5px;
margin: 0px;
border: 1px solid #E7E7E8;
background: #F7F7F8;
}
/* Local link is a style for hyperlinks that link to file:/// content, there are lots so color them as 'normal' text until the user mouse overs */
.localLink
{
color: #1E1E1F;
background: #EEEEED;
text-decoration: none;
}
.localLink:hover
{
color: #1382CE;
background: #FFFF99;
text-decoration: none;
}
/* Center text, used in the over views cells that contain message level counts */
.textCentered
{
text-align: center;
}
/* The message cells in message tables should take up all avaliable space */
.messageCell
{
width: 100%;
}
/* Padding around the content after the h1 */
#content
{
padding: 0px 12px 12px 12px;
}
/* The overview table expands to width, with a max width of 97% */
#overview table
{
width: auto;
max-width: 75%;
}
/* The messages tables are always 97% width */
#messages table
{
width: 97%;
}
/* All Icons */
.IconSuccessEncoded, .IconInfoEncoded, .IconWarningEncoded, .IconErrorEncoded
{
min-width:18px;
min-height:18px;
background-repeat:no-repeat;
background-position:center;
}
/* Success icon encoded */
.IconSuccessEncoded
{
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
/* [---XsltValidateInternal-Base64EncodedImage:IconSuccess#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABcElEQVR4Xq2TsUsCURzHv15g8ZJcBWlyiYYgCIWcb9DFRRwMW5TA2c0/QEFwFkxxUQdxVlBwCYWOi6IhWgQhBLHJUCkhLr/BW8S7gvrAg+N+v8/v+x68Z8MGy+XSCyABQAXgBgHGALoASkIIDWSLeLBetdHryMjd5IxQPWT4rn1c/P7+xxp72Cs9m5SZ0Bq2vPnbPFafK2zDvmNHypdC0BPkLlQhxJsCAhQoZwdZU5mwxh720qGo8MzTxTTKZDPCx2HoVzp6lz0Q9tKhyx0kGs8Ny+TkWRKk8lCROwEduhyg9l/6lunOPSfmH3NUH6uQ0KHLAe7JYvJjevm+DAMGJHToKtigE+vwvIidxLamb8IBY9e+C5LiXREkfho3TSd06HJA13/oh6T51MTsfQbHrsMynQ5dDihFjiK8JJAU9AKIWTp76dCVN7HWHrajmUEGvyF9nkbAE6gLIS7kTUyuf2gscLoJrElZo/Mvj+nPz/kLTmfnEwP3tB0AAAAASUVORK5CYII=);
}
/* Information icon encoded */
.IconInfoEncoded
{
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
/* [---XsltValidateInternal-Base64EncodedImage:IconInformation#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR4Xs2TsUoDQRRF7wwoziokjZUKadInhdhukR9YP8DMX1hYW+QvdsXa/QHBbcXC7W0CamWTQnclFutceIQJwwaWNLlwm5k5d94M76mmaeCrrmsLYOocY12FcxZFUeozCqKqqgYA8uevv1H6VuPxcwlfk5N92KHBxfFeCSAxxswlYAW/Xr989x/mv9gkhtyMDhcAxgzRsp7flj8B/HF1RsMXq+NZMkopaHe7lbKxQUEIGbKsYNoGn969060hZBkQex/W8oRQwsQaW2o3Ago2SVcJUzAgY3N0lTCZZm+zPS8HB51gMmS1DEYyOz9acKO1D8JWTlafKIMxdhvlfdyT94Vv5h7P8Ky7nQzACmhvKq3zk3PjW9asz9D/1oigecsioooAAAAASUVORK5CYII=);
}
/* Warning icon encoded */
.IconWarningEncoded
{
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
/* [---XsltValidateInternal-Base64EncodedImage:IconWarning#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAx0lEQVR4XpWSMQ7CMAxFf4xAyBMLCxMrO8dhaBcuwdCJS3RJBw7SA/QGTCxdWJgiQYWKXJWKIXHIlyw5lqr34tQgEOdcBsCOx5yZK3hCCKdYXneQkh4pEfqzLfu+wVDSyyzFoJjfz9NB+pAF+eizx2Vruts0k15mPgvS6GYvpVtQhB61IB/dk6AF6fS4Ben0uIX5odtFe8Q/eW1KvFeH4e8khT6+gm5B+t3juyDt7n0jpe+CANTd+oTUjN/U3yVaABnSUjFz/gFq44JaVSCXeQAAAABJRU5ErkJggg==);
}
/* Error icon encoded */
.IconErrorEncoded
{
/* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */
/* [---XsltValidateInternal-Base64EncodedImage:IconError#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABQElEQVR4XqWTvUoEQRCE6wYPZUA80AfwAQz23uCMjA7MDRQEIzPBVEyNTQUFIw00vcQTTMzuAh/AxEQQT8HF/3G/oGGnEUGuoNnd6qoZuqltyKEsyzVJq5I6rnUp6SjGeGhESikzzlc1eL7opfuVbrqbU1Zw9NCgtQMaZpY0eNnaaL2fHusvTK5vKu7sjSS1Y4y3QUA6K3e3Mau5UFDyMP7tYF9o8cAHZv68vipoIJg971PZIZ5HiwdvYGGvFVFHmGmZ2MxwmQYPXubPl9Up0tfoMQGetXd6mRbvhBw+boZ6WF7Mbv1+GsHRk0fQmPAH1GfmZirbCfDJ61tw3Px8/8pZsPAG4jlVhcPgZ7adwNWBB68lkRQWFiTgFlbnLY3DGGM7izIJIyT/jjIvEJw6fdJTc6krDzh6aMwMP9bvDH4ADSsa9uSWVJkAAAAASUVORK5CYII=);
}
</style><script type="text/javascript" language="javascript">
// Startup
// Hook up the the loaded event for the document/window, to linkify the document content
var startupFunction = function() { linkifyElement("messages"); };
if(window.attachEvent)
{
window.attachEvent('onload', startupFunction);
}
else if (window.addEventListener)
{
window.addEventListener('load', startupFunction, false);
}
else
{
document.addEventListener('load', startupFunction, false);
}
// Toggles the visibility of table rows with the specified name
function toggleTableRowsByName(name)
{
var allRows = document.getElementsByTagName('tr');
for (i=0; i < allRows.length; i++)
{
var currentName = allRows[i].getAttribute('name');
if(!!currentName && currentName.indexOf(name) == 0)
{
var isVisible = allRows[i].style.display == '';
isVisible ? allRows[i].style.display = 'none' : allRows[i].style.display = '';
}
}
}
function scrollToFirstVisibleRow(name)
{
var allRows = document.getElementsByTagName('tr');
for (i=0; i < allRows.length; i++)
{
var currentName = allRows[i].getAttribute('name');
var isVisible = allRows[i].style.display == '';
if(!!currentName && currentName.indexOf(name) == 0 && isVisible)
{
allRows[i].scrollIntoView(true);
return true;
}
}
return false;
}
// Linkifies the specified text content, replaces candidate links with html links
function linkify(text)
{
if(!text || 0 === text.length)
{
return text;
}
// Find http, https and ftp links and replace them with hyper links
var urlLink = /(http|https|ftp)\:\/\/[a-zA-Z0-9\-\.]+(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._\?\,\/\\\+&%\$#\=~;\{\}])*/gi;
return text.replace(urlLink, '<a href="$&">$&</a>') ;
}
// Linkifies the specified element by ID
function linkifyElement(id)
{
var element = document.getElementById(id);
if(!!element)
{
element.innerHTML = linkify(element.innerHTML);
}
}
function ToggleMessageVisibility(projectName)
{
if(!projectName || 0 === projectName.length)
{
return;
}
toggleTableRowsByName("MessageRowClass" + projectName);
toggleTableRowsByName('MessageRowHeaderShow' + projectName);
toggleTableRowsByName('MessageRowHeaderHide' + projectName);
}
function ScrollToFirstVisibleMessage(projectName)
{
if(!projectName || 0 === projectName.length)
{
return;
}
// First try the 'Show messages' row
if(!scrollToFirstVisibleRow('MessageRowHeaderShow' + projectName))
{
// Failed to find a visible row for 'Show messages', try an actual message row
scrollToFirstVisibleRow('MessageRowClass' + projectName);
}
}
</script></head><body><h1 _locID="ConversionReport">
Migration Report - </h1><div id="content"><h2 _locID="OverviewTitle">Overview</h2><div id="overview"><table><tr><th></th><th _locID="ProjectTableHeader">Project</th><th _locID="PathTableHeader">Path</th><th _locID="ErrorsTableHeader">Errors</th><th _locID="WarningsTableHeader">Warnings</th><th _locID="MessagesTableHeader">Messages</th></tr><tr><td class="IconErrorEncoded" /><td><strong><a href="#grk-cw1">grk-cw1</a></strong></td><td>cw 1\grk-cw1.vcxproj</td><td class="textCentered"><a href="#grk-cw1Error">1</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#">0</a></td></tr><tr><td class="IconSuccessEncoded" /><td><strong><a href="#Solution"><span _locID="OverviewSolutionSpan">Solution</span></a></strong></td><td>grk-cw.sln</td><td class="textCentered"><a>0</a></td><td class="textCentered"><a>0</a></td><td class="textCentered"><a href="#" onclick="ScrollToFirstVisibleMessage('Solution'); return false;">1</a></td></tr></table></div><h2 _locID="SolutionAndProjectsTitle">Solution and projects</h2><div id="messages"><a name="grk-cw1" /><h3>grk-cw1</h3><table><tr id="grk-cw1HeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">Message</th></tr><tr name="ErrorRowClassgrk-cw1"><td class="IconErrorEncoded"><a name="grk-cw1Error" /></td><td class="messageCell"><strong>cw 1\grk-cw1.vcxproj:
</strong><span>The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942</span></td></tr></table><a name="Solution" /><h3 _locID="ProjectDisplayNameHeader">Solution</h3><table><tr id="SolutionHeaderRow"><th></th><th class="messageCell" _locID="MessageTableHeader">Message</th></tr><tr name="MessageRowHeaderShowSolution"><td class="IconInfoEncoded" /><td class="messageCell"><a _locID="ShowAdditionalMessages" href="#" name="SolutionMessage" onclick="ToggleMessageVisibility('Solution'); return false;">
Show 1 additional messages
</a></td></tr><tr name="MessageRowClassSolution" style="display: none"><td class="IconInfoEncoded"><a name="SolutionMessage" /></td><td class="messageCell"><strong>grk-cw.sln:
</strong><span>The solution file does not require migration.</span></td></tr><tr style="display: none" name="MessageRowHeaderHideSolution"><td class="IconInfoEncoded" /><td class="messageCell"><a _locID="HideAdditionalMessages" href="#" name="SolutionMessage" onclick="ToggleMessageVisibility('Solution'); return false;">
Hide 1 additional messages
</a></td></tr></table></div></div></body></html>

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>j:\Downloads\grk\Debug\grk-cw6.exe</FullPath>
<FullPath>D:\STUDIA\Planeta\grk\Debug\Planeta.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,10 @@
D:\STUDIA\Planeta\grk\cw 6\src\Box.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\Box.obj
D:\STUDIA\Planeta\grk\cw 6\src\Camera.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\Camera.obj
D:\STUDIA\Planeta\grk\cw 6\src\main.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\main.obj
D:\STUDIA\Planeta\grk\cw 6\src\Render_Utils.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\Render_Utils.obj
D:\STUDIA\Planeta\grk\cw 6\src\Shader_Loader.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\Shader_Loader.obj
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_DXT.c;D:\STUDIA\Planeta\grk\cw 6\Debug\image_DXT.obj
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c;D:\STUDIA\Planeta\grk\cw 6\Debug\image_helper.obj
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\SOIL.c;D:\STUDIA\Planeta\grk\cw 6\Debug\SOIL.obj
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\stb_image_aug.c;D:\STUDIA\Planeta\grk\cw 6\Debug\stb_image_aug.obj
D:\STUDIA\Planeta\grk\cw 6\src\Texture.cpp;D:\STUDIA\Planeta\grk\cw 6\Debug\Texture.obj

View File

@ -0,0 +1,2 @@
PlatformToolSet=v143:VCToolArchitecture=Native32Bit:VCToolsVersion=14.38.33130:TargetPlatformVersion=10.0.22000.0:
Debug|Win32|D:\STUDIA\Planeta\grk\|

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,17 +0,0 @@
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\vc142.pdb
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\vc142.idb
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\shader_loader.obj
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\render_utils.obj
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\main_3_1.obj
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\camera.obj
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\box.obj
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\vcpkg.applocal.log
c:\users\andrzej\desktop\grk\zipy\grk-cw\debug\grk-cw3.exe
c:\users\andrzej\desktop\grk\zipy\grk-cw\debug\grk-cw3.pdb
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\cl.command.1.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\cl.read.1.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\cl.write.1.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\grk-cw3.write.1u.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\link.command.1.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\link.read.1.tlog
c:\users\andrzej\desktop\grk\zipy\grk-cw\cw 3\debug\grk-cw3.tlog\link.write.1.tlog

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\Debug\grk-cw3.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>

View File

@ -1,8 +0,0 @@
 Using triplet "x86-windows" from "C:\Users\Andrzej\Desktop\openvdb\vcpkg\installed\x86-windows\"
main.cpp
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition
C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\dependencies\glfw-3.3.8.bin.WIN32\include\GLFW\glfw3.h(123): message : see previous definition of 'APIENTRY'
C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\cw 3\src\ex_3_1.hpp(76,16): warning C4305: 'initializing': truncation from 'double' to 'float'
Box.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
grk-cw3.vcxproj -> C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\Debug\grk-cw3.exe

View File

@ -1,2 +0,0 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.19041.0:
Debug|Win32|C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\|

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw4.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>

View File

@ -1,10 +0,0 @@
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(491,5): warning MSB8028: The intermediate directory (Debug\) contains files shared from another project (grk-cw3.vcxproj). This can lead to incorrect clean and rebuild behavior.
Using triplet "x86-windows" from "C:\Users\Andrzej\Desktop\openvdb\vcpkg\installed\x86-windows\"
main.cpp
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition
C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\dependencies\glfw-3.3.8.bin.WIN32\include\GLFW\glfw3.h(123): message : see previous definition of 'APIENTRY'
C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\cw 4\src\ex_4_1.hpp(63,16): warning C4305: 'initializing': truncation from 'double' to 'float'
C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\cw 4\src\ex_4_1.hpp(84,13): warning C4244: 'initializing': conversion from 'double' to 'float', possible loss of data
Box.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
grk-cw4.vcxproj -> C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw4.exe

View File

@ -1,2 +0,0 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.19041.0:
Debug|Win32|C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\|

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw5.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>

View File

@ -1,3 +0,0 @@
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(491,5): warning MSB8028: The intermediate directory (Debug\) contains files shared from another project (grk-cw3.vcxproj, grk-cw4.vcxproj). This can lead to incorrect clean and rebuild behavior.
Using triplet "x86-windows" from "C:\Users\Andrzej\Desktop\openvdb\vcpkg\installed\x86-windows\"
grk-cw5.vcxproj -> C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw5.exe

View File

@ -1,2 +0,0 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29333:TargetPlatformVersion=10.0.19041.0:
Debug|Win32|C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\|

View File

@ -1,23 +0,0 @@
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\vc142.pdb
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\vc142.idb
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\texture.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\shader_loader.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\render_utils.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\main.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\camera.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\box.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\stb_image_aug.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\soil.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\image_helper.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\image_dxt.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\vcpkg.applocal.log
c:\users\andrzej\desktop\grk\2021\grk glfw test\debug\grk-cw6.exe
c:\users\andrzej\desktop\grk\2021\grk glfw test\debug\grk-cw6.pdb
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\main_3_1.obj
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\cl.command.1.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\cl.read.1.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\cl.write.1.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\grk-cw6.write.1u.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\link.command.1.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\link.read.1.tlog
c:\users\andrzej\desktop\grk\2021\grk glfw test\cw 6\debug\grk-cw6.tlog\link.write.1.tlog

View File

@ -1,39 +1,44 @@
C:\software\vs19\MSBuild\Microsoft\VC\v160\Microsoft.CppBuild.targets(513,5): warning MSB8028: The intermediate directory (Debug\) contains files shared from another project (grk-cw3.vcxproj, grk-cw4.vcxproj, grk-cw5.vcxproj). This can lead to incorrect clean and rebuild behavior.
 Box.cpp
Camera.cpp
main.cpp
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition
j:\Downloads\grk\dependencies\glfw-3.3.8.bin.WIN32\include\GLFW\glfw3.h(123): message : see previous definition of 'APIENTRY'
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(92,16): warning C4305: 'initializing': truncation from 'double' to 'float'
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(135,13): warning C4244: 'initializing': conversion from 'double' to 'float', possible loss of data
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(139,52): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(143,50): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(147,49): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(151,48): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(155,48): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
j:\Downloads\grk\cw 6\src\ex_6_1.hpp(159,48): warning C4305: 'argument': truncation from 'double' to 'T'
with
[
T=float
]
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\shared\minwindef.h(130,1): warning C4005: 'APIENTRY': macro redefinition
(compiling source file 'src/main.cpp')
D:\STUDIA\Planeta\grk\dependencies\glfw-3.3.8.bin.WIN32\include\GLFW\glfw3.h(123,1):
see previous definition of 'APIENTRY'
D:\STUDIA\Planeta\grk\cw 6\src\Planet.hpp(141,13): warning C4244: 'initializing': conversion from 'double' to 'float', possible loss of data
(compiling source file 'src/main.cpp')
Render_Utils.cpp
Shader_Loader.cpp
Texture.cpp
Generating Code...
image_DXT.c
image_helper.c
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_DXT.c(92,9): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c(325,17): warning C4244: 'initializing': conversion from 'double' to 'float', possible loss of data
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c(366,13): warning C4244: '=': conversion from 'double' to 'float', possible loss of data
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c(373,20): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c(415,13): warning C4244: '=': conversion from 'double' to 'float', possible loss of data
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\image_helper.c(422,20): warning C4244: '=': conversion from 'float' to 'int', possible loss of data
SOIL.c
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\SOIL.c(1719,36): warning C4018: '<=': signed/unsigned mismatch
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\SOIL.c(1729,19): warning C4018: '<': signed/unsigned mismatch
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\SOIL.c(1841,6): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
stb_image_aug.c
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\stbi_DDS_aug_c.h(362,19): warning C4018: '>': signed/unsigned mismatch
(compiling source file 'src/SOIL/stb_image_aug.c')
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\stbi_DDS_aug_c.h(366,19): warning C4018: '>': signed/unsigned mismatch
(compiling source file 'src/SOIL/stb_image_aug.c')
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\stbi_DDS_aug_c.h(390,19): warning C4018: '<': signed/unsigned mismatch
(compiling source file 'src/SOIL/stb_image_aug.c')
D:\STUDIA\Planeta\grk\cw 6\src\SOIL\stbi_DDS_aug_c.h(427,19): warning C4018: '<': signed/unsigned mismatch
(compiling source file 'src/SOIL/stb_image_aug.c')
Generating Code...
Box.obj : warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/INCREMENTAL:NO' specification
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NODEFAULTLIB:library
grk-cw6.vcxproj -> j:\Downloads\grk\Debug\grk-cw6.exe
grk-cw6.vcxproj -> D:\STUDIA\Planeta\grk\Debug\Planeta.exe

View File

@ -1,2 +0,0 @@
PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=10.0.19041.0:
Debug|Win32|j:\Downloads\grk\|

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
grk/cw 6/Debug/vc143.idb Normal file

Binary file not shown.

BIN
grk/cw 6/Debug/vc143.pdb Normal file

Binary file not shown.

144
grk/cw 6/Zadania 2.html Normal file
View File

@ -0,0 +1,144 @@
<!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 2</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" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h2 id="ładowanie-vao-i-vbo">Ładowanie VAO i VBO</h2>
<p>W trakcie tych zajęć przećwiczymy ładowanie danych do pamięci. Tym razem, zamiast korzystać z gotowej funkcji utworzymy je samodzielnie. W openglu wykorzystujemy do tego VBO (Vertex Buffer Object) i VAO (Vertex Array Object). Pierwsza jest buforem, który zawiera dane modeli. Natomiast drugi zawiera informacje jak dane bufory interpretować.</p>
<p>W zadaniu <code>2_1</code> będziemy przesyłać prostopadłościan. Tablica zawierająca jego definicję jest w pliku <code>Box.cpp</code>. Każdy wierzchołek składa się z ośmiu floatów, pierwsze cztery określają jego pozycję, a cztery kolejny określają jego kolor.</p>
<p>Inicjalizacje będziemy wykonywać wewnątrz funkcji <code>init</code>. Pierwszym krokiem jest wygenerowanie jednego VAO i jednego VBO. Wykorzystuje się do tego odpowiednio funkcje <code>glGenVertexArrays</code> i <code>glGenBuffers</code>. Pierwszym argumentem jest liczba buforów czy array object, które tworzymy, drugim jest adres, w którym ma być bufor/array object umieszczony. W naszym przypadku pierwszym argumentem będzie 1, natomiast drugim będzie wskaźnik na zmienną <code>VAO</code> i <code>VBO</code> odpowiednio. Następnie należy aktywować <code>VAO</code> za pomocą funkcji <code>glBindVertexArray</code>, po czym podpiąć do niego bufor <code>VBO</code> za pomocą <code>glBindBuffer(GLenum target, GLuint buffer)</code> nasz target to <code>GL_ARRAY_BUFFER</code>, czyli bufor, który oznacza atrybuty wierzchołków.</p>
<p>Kolejnym krokiem jest umieszczenie danych w buforze za pomocą funkcji <code>glBufferData(GLenum target, GLsizeiptr size, const void * data, GLenum usage)</code>. Pierwszym argumentem jest ponownie <code>GL_ARRAY_BUFFER</code>, drugi to rozmiar tablicy w bajtach, trzecim adres tablicy, a czwartym sposób używania tablicy, w naszym przypadku <code>GL_STATIC_DRAW</code>.</p>
<p>Pozostaje opisanie atrybutów wierzchołków, musimy opisać, gdzie się znajdują, jaką mają strukturę i jak ma się do nich odnieść shader. My mamy 2 atrybuty, jest to pozycja i kolor. Pierwszym krokiem jest aktywacja atrybutów za pomocą <code>glEnableVertexAttribArray(GLuint index)</code>, przy czym po indeksie będą one odnajdywane przez shader. W naszym przypadku będą to odpowiednio 0 i 1. Następnie należy opisać jak GPU ma odczytywać atrybuty z bufora za pomocą funkcji <code>glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * offset)</code>. Jej argumenty to kolejno: * <code>index</code> - indeksy odpowiadające atrybutowi, * <code>size</code> - liczba elementów w atrybucie wierzchołka, może wynosić 1, 2, 3 lub 4, * <code>type</code> - typ danych jako enum, w naszym przypadku <code>GL_FLOAT</code>, * <code>normalized</code> - określa czy wartość ma być znormalizowana, u nas będzie to <code>GL_FALSE</code>, * <code>stride</code> - określa dystans pomiędzy atrybutami w kolejnych wierzchołkach * <code>offset</code> - wskaźnik na pierwszy atrybut w tablicy, licząc względem początku tablicy i typu (void *)</p>
<p>Struktura naszego prostopadłościanu ma na przemian pozycje i kolory, dlatego w obu przypadkach stride będzie wynosił ośmiokrotność rozmiaru <em>floata</em>. Natomiast <em>offest</em> będzie wynosił zero i czterokrotność rozmiaru <em>floata</em>.</p>
<p><img src="./img/stride_offest.jpg" /></p>
<p>Na koniec uwolnij <code>VAO</code> za pomocą instrukcji: <code>glBindVertexArray(0);</code>.</p>
<p>Pozostaje narysować prostopadłościan. W funkcji <code>renderScene</code> wywołaj <code>glBindVertexArray</code> z argumentem <code>VAO</code>. Następnie narysuj za pomocą <code>glDrawArrays(GLenum mode, GLint first, GLsizei count)</code>. Pierwszym argumentem jest typ rysowanego obiektu, w naszym przypadku jest to <code>GL_TRIANGLES</code>, indeks pierwszego wierzchołka, czyli 0 i liczba wierzchołków czyli 36.</p>
<h3 id="zadanie">Zadanie</h3>
<p>podążając za powyższymi instrukcjami zainicjalizuj box, następnie obróć go za pomocą funkcji <code>glm::eulerAngleXYZ</code> tak, żeby było widać trzy ściany prostopadłościany. Dodaj również obrót wokół osi Y w czasie z użyciem funkcji <code>glm::eulerAngleXYZ</code>.</p>
<h3 id="zadanie-1">Zadanie*</h3>
<p>Wykonaj zadania z <code>ex_2_1b.hpp</code>.</p>
<h2 id="shadery">Shadery</h2>
<p>Shadery są programami uruchamianymi na karcie graficznej. W openglu wykorzystujemy język GLSL, który jest bardzo podobny do C++, posiada on liczne słowa kluczowe i funkcje matematyczne. Istnieją różne rodzaje shaderów, w tej sekcji skupimy się na dwóch z nich: shader wierzchołków i shader fragmentów. Pierwszy rodzaj wykonują operacje na wierzchołkach, przykładowo w tym zadaniu odpowiada za przemnożenie macierzy obrotu przez wierzchołki. Natomiast drugi określa kolor konkretnego fragmentu/piksela. Shadery są łączone w <em>pipeline</em>, to znaczy wykonuje się je sekwencyjnie, dane z poprzedniego są wysyłane do następnego. W zadaniu <code>2_1</code> wykorzystujemy następujące shadery</p>
<p>shader wierzchołków</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode glsl"><code class="sourceCode glsl"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#version 430 core</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">layout</span>(<span class="dt">location</span> = <span class="dv">0</span>) <span class="dt">in</span> <span class="dt">vec4</span> vertexPosition;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">layout</span>(<span class="dt">location</span> = <span class="dv">1</span>) <span class="dt">in</span> <span class="dt">vec4</span> vertexColor;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">uniform</span> <span class="dt">mat4</span> transformation;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span>()</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>{</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="bu">gl_Position</span> = transformation * vertexPosition;</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>shader fragmentów</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode glsl"><code class="sourceCode glsl"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="pp">#version 430 core</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="dt">out</span> <span class="dt">vec4</span> out_color;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="fu">main</span>()</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>{</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> out_color = <span class="dt">vec4</span>(<span class="fl">0.8</span>,<span class="fl">0.2</span>,<span class="fl">0.9</span>,<span class="fl">1.0</span>);</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Shader wierzchołków odbiera 2 typy danych. Pierwszym są dane z bufora w liniach.</p>
<pre><code>layout(location = 0) in vec4 vertexPosition;
layout(location = 1) in vec4 vertexColor;</code></pre>
<p>są one różne dla każdego wierzchołka. Zmienną, która ma odebrać te dane deklaruje się globalnie funkcją <code>main</code> i poprzedza się słowem kluczowym <code>in</code>. Prefiks <code>layout(location = ..)</code> jest opcjonalny i służy określeniu indeksu atrybutu, jest to ta sama wartość, którą ustawiliśmy w <code>glVertexAttribPointer</code>. Można je usunąć, wtedy o indeksie będzie decydować kolejność. Drugim typem jest <code>uniform</code>, w przeciwieństwie do danych z bufora, są one takie same dla każdego wierzchołka. W tym przypadku przesyłamy za jej pomocą macierz obrotu.</p>
<p>Shader również wysyła dane. Domyślnie musi wysłać wyjściową pozycję wierzchołka, robi to przez zapisanie w <code>gl_Position</code> wektora 4-wymiarowego w funkcji <code>main</code>. Poza tym może również przesłać inne informacje. Wykonuje się to przez deklaracje zmiennej globalnej, którą poprzedza się słowem kluczowym <code>out</code>. Następnie należy ją wypełnić. W tym przypadku przesyłamy kolor wierzchołka.</p>
<p>Shader fragmentów odbiera kolor z Shadera wierzchołków. Podobnie jak z obieraniem danych z buforu robimy to za pomocą słowa kluczowego <code>in</code>, w przypadku przesyłania zmiennej z jednego shadera do drugiego nazwy zmiennych muszą być <strong>takie same</strong> przy słowie kluczowym <code>out</code> i <code>in</code>. Zmiennej obranej nie można modyfikować.</p>
<p>W najnowszej wersji opengla fragment shader nie ma domyślnego wyjścia na kolor, musimy sami je z definiować. Robimy to instrukcją <code>out vec4 out_color</code> następnie w funkcji <code>main</code> przypisujemy mu jakąś wartość.</p>
<h3 id="zadanie-2">Zadanie</h3>
<p>W tej chwili nasz prostopadłościan jest jednolitego koloru i nie możemy rozróżnić jego ścian. Przesłana przez nas wcześniej informacja o kolorze nie została wykorzystana. Bazując na powyższych informacjach prześlij wartość koloru zapisaną w <code>vertexColor</code> do shadera fragmentu i przypisz ją do wyjściowego koloru. Dodaj zmienną <code>in vec4 color</code> w shaderze fragmentów, następnie w funkcji <code>main</code> przypisz do niej wartość koloru. W shaderze fragmentów odbierz ją za pomocą <code>out</code> i przypisz do wyjściowego koloru.</p>
<p>Zauważ, że kolor ścian nie jest jednolity, zamiast tego przechodzą gradientem od jednego koloru do drugiego. Dzieje się tak, ponieważ na etapie rasteryzacji kolor jest interpolowany. To znaczy: wartość jest uśredniana pomiędzy wierzchołkami trójkąta.</p>
<h3 id="zadanie-3">Zadanie</h3>
<p>Sprawdź, jak będzie wyglądać prostopadłościan z wyłączoną interpolacją. Dodaj przed <code>in</code> i <code>out</code> <code>color</code> słowo kluczowe <code>flat</code>.</p>
<h3 id="zadanie-4">Zadanie</h3>
<p>Prześlij czas od startu aplikacji do shadera fragmentów. Użyj funkcji <code>glfwGetTime</code>, by uzyskać czas. Utwórz zmienną <code>uniform</code> typu <code>float</code> we shaderze fragmentów. Następnie prześlij do niej wynik funkcji <code>glfwGetTime</code>. Aby przesłać czas do shadera, wykorzystaj funkcje <code>glUniform1f</code>. Pierwszym argumentem jest lokacja uniforma, drugim przypisywana wartość. Lokację uzyskamy za pomocą funckji <code>glGetUniformLocation(progam,"time")</code> pierwszym argumentem jest program, którego używamy a drugim nazwa zmiennej uniform. Podziel kolor przez czas, by uzyskać efekt, w którym prostopadłościan robi się czarny.</p>
<h3 id="zadanie-5">Zadanie*</h3>
<p>Wykorzystaj przesłany czas, żeby sprawić, żeby prostopadłościan znikał przez mieszanie go z kolorem tła. Wykorzystaj do tego następujące funkcje GLSL: <code>mix</code>, <code>sin</code>, <code>vec4</code>. Opis ich działania możesz znaleźć w dokumentacji https://docs.gl/.</p>
<h3 id="zadanie-6">Zadanie</h3>
<p>Prześlij pozycję lokalną i globalną pozycję wierzchołków do shadera fragmentów i wyświetl ją.</p>
<p>W shaderze wierzchołków obok deklaracji <code>out vec4 color;</code> dodaj analogiczne o nazwie <code>pos_local</code> i <code>pos_global</code>. Do <code>pos_local</code> przypisz <code>vertexPosition</code>, a do <code>pos_global</code> przypisz <code>transformation * vertexPosition</code>. Podobnie dopisz odebranie ich w shaderze fragmentów. Użyj <code>pos_local</code>, następnie <code>pos_global</code> jako zamiast koloru. Dlaczego otrzymaliśmy taki efekt?</p>
<h3 id="zadanie-7">Zadanie*</h3>
<p>Użyj jednej ze zmiennych z poprzedniego zadania do zrobienia pasków na przynajmniej jednej ze ścian sześcianu. Wykorzystaj czas, żeby paski się przesuwały.</p>
</body>
</html>

105
grk/cw 6/Zadania 2.md Normal file
View File

@ -0,0 +1,105 @@
## Ładowanie VAO i VBO
W trakcie tych zajęć przećwiczymy ładowanie danych do pamięci. Tym razem, zamiast korzystać z gotowej funkcji utworzymy je samodzielnie. W openglu wykorzystujemy do tego VBO (Vertex Buffer Object) i VAO (Vertex Array Object). Pierwsza jest buforem, który zawiera dane modeli. Natomiast drugi zawiera informacje jak dane bufory interpretować.
W zadaniu `2_1` będziemy przesyłać prostopadłościan. Tablica zawierająca jego definicję jest w pliku `Box.cpp`. Każdy wierzchołek składa się z ośmiu floatów, pierwsze cztery określają jego pozycję, a cztery kolejny określają jego kolor.
Inicjalizacje będziemy wykonywać wewnątrz funkcji `init`. Pierwszym krokiem jest wygenerowanie jednego VAO i jednego VBO. Wykorzystuje się do tego odpowiednio funkcje `glGenVertexArrays` i `glGenBuffers`. Pierwszym argumentem jest liczba buforów czy array object, które tworzymy, drugim jest adres, w którym ma być bufor/array object umieszczony.
W naszym przypadku pierwszym argumentem będzie 1, natomiast drugim będzie wskaźnik na zmienną `VAO` i `VBO` odpowiednio. Następnie należy aktywować `VAO` za pomocą funkcji `glBindVertexArray`, po czym podpiąć do niego bufor `VBO` za pomocą `glBindBuffer(GLenum target, GLuint buffer)` nasz target to `GL_ARRAY_BUFFER`, czyli bufor, który oznacza atrybuty wierzchołków.
Kolejnym krokiem jest umieszczenie danych w buforze za pomocą funkcji `glBufferData(GLenum target, GLsizeiptr size, const void * data, GLenum usage)`. Pierwszym argumentem jest ponownie `GL_ARRAY_BUFFER`, drugi to rozmiar tablicy w bajtach, trzecim adres tablicy, a czwartym sposób używania tablicy, w naszym przypadku `GL_STATIC_DRAW`.
Pozostaje opisanie atrybutów wierzchołków, musimy opisać, gdzie się znajdują, jaką mają strukturę i jak ma się do nich odnieść shader. My mamy 2 atrybuty, jest to pozycja i kolor. Pierwszym krokiem jest aktywacja atrybutów za pomocą `glEnableVertexAttribArray(GLuint index)`, przy czym po indeksie będą one odnajdywane przez shader. W naszym przypadku będą to odpowiednio 0 i 1. Następnie należy opisać jak GPU ma odczytywać atrybuty z bufora za pomocą funkcji `glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * offset)`. Jej argumenty to kolejno:
* `index` - indeksy odpowiadające atrybutowi,
* `size` - liczba elementów w atrybucie wierzchołka, może wynosić 1, 2, 3 lub 4,
* `type` - typ danych jako enum, w naszym przypadku `GL_FLOAT`,
* `normalized` - określa czy wartość ma być znormalizowana, u nas będzie to `GL_FALSE`,
* `stride` - określa dystans pomiędzy atrybutami w kolejnych wierzchołkach
* `offset` - wskaźnik na pierwszy atrybut w tablicy, licząc względem początku tablicy i typu (void \*)
Struktura naszego prostopadłościanu ma na przemian pozycje i kolory, dlatego w obu przypadkach stride będzie wynosił ośmiokrotność rozmiaru *floata*. Natomiast *offest* będzie wynosił zero i czterokrotność rozmiaru *floata*.
![](./img/stride_offest.jpg)
Na koniec uwolnij `VAO` za pomocą instrukcji: `glBindVertexArray(0);`.
Pozostaje narysować prostopadłościan. W funkcji `renderScene` wywołaj `glBindVertexArray` z argumentem `VAO`. Następnie narysuj za pomocą `glDrawArrays(GLenum mode, GLint first, GLsizei count)`. Pierwszym argumentem jest typ rysowanego obiektu, w naszym przypadku jest to `GL_TRIANGLES`, indeks pierwszego wierzchołka, czyli 0 i liczba wierzchołków czyli 36.
### Zadanie
podążając za powyższymi instrukcjami zainicjalizuj box, następnie obróć go za pomocą funkcji `glm::eulerAngleXYZ` tak, żeby było widać trzy ściany prostopadłościany. Dodaj również obrót wokół osi Y w czasie z użyciem funkcji `glm::eulerAngleXYZ`.
### Zadanie*
Wykonaj zadania z `ex_2_1b.hpp`.
## Shadery
Shadery są programami uruchamianymi na karcie graficznej. W openglu wykorzystujemy język GLSL, który jest bardzo podobny do C++, posiada on liczne słowa kluczowe i funkcje matematyczne. Istnieją różne rodzaje shaderów, w tej sekcji skupimy się na dwóch z nich: shader wierzchołków i shader fragmentów. Pierwszy rodzaj wykonują operacje na wierzchołkach, przykładowo w tym zadaniu odpowiada za przemnożenie macierzy obrotu przez wierzchołki. Natomiast drugi określa kolor konkretnego fragmentu/piksela. Shadery są łączone w *pipeline*, to znaczy wykonuje się je sekwencyjnie, dane z poprzedniego są wysyłane do następnego.
W zadaniu `2_1` wykorzystujemy następujące shadery
shader wierzchołków
```GLSL
#version 430 core
layout(location = 0) in vec4 vertexPosition;
layout(location = 1) in vec4 vertexColor;
uniform mat4 transformation;
void main()
{
gl_Position = transformation * vertexPosition;
}
```
shader fragmentów
```GLSL
#version 430 core
out vec4 out_color;
void main()
{
out_color = vec4(0.8,0.2,0.9,1.0);
}
```
Shader wierzchołków odbiera 2 typy danych. Pierwszym są dane z bufora w liniach.
```
layout(location = 0) in vec4 vertexPosition;
layout(location = 1) in vec4 vertexColor;
```
są one różne dla każdego wierzchołka. Zmienną, która ma odebrać te dane deklaruje się globalnie funkcją `main` i poprzedza się słowem kluczowym `in`. Prefiks `layout(location = ..)` jest opcjonalny i służy określeniu indeksu atrybutu, jest to ta sama wartość, którą ustawiliśmy w `glVertexAttribPointer`. Można je usunąć, wtedy o indeksie będzie decydować kolejność.
Drugim typem jest `uniform`, w przeciwieństwie do danych z bufora, są one takie same dla każdego wierzchołka. W tym przypadku przesyłamy za jej pomocą macierz obrotu.
Shader również wysyła dane. Domyślnie musi wysłać wyjściową pozycję wierzchołka, robi to przez zapisanie w `gl_Position` wektora 4-wymiarowego w funkcji `main`. Poza tym może również przesłać inne informacje. Wykonuje się to przez deklaracje zmiennej globalnej, którą poprzedza się słowem kluczowym `out`. Następnie należy ją wypełnić. W tym przypadku przesyłamy kolor wierzchołka.
Shader fragmentów odbiera kolor z Shadera wierzchołków. Podobnie jak z obieraniem danych z buforu robimy to za pomocą słowa kluczowego `in`, w przypadku przesyłania zmiennej z jednego shadera do drugiego nazwy zmiennych muszą być **takie same** przy słowie kluczowym `out` i `in`. Zmiennej obranej nie można modyfikować.
W najnowszej wersji opengla fragment shader nie ma domyślnego wyjścia na kolor, musimy sami je z definiować. Robimy to instrukcją `out vec4 out_color` następnie w funkcji `main` przypisujemy mu jakąś wartość.
### Zadanie
W tej chwili nasz prostopadłościan jest jednolitego koloru i nie możemy rozróżnić jego ścian. Przesłana przez nas wcześniej informacja o kolorze nie została wykorzystana. Bazując na powyższych informacjach prześlij wartość koloru zapisaną w `vertexColor` do shadera fragmentu i przypisz ją do wyjściowego koloru. Dodaj zmienną `in vec4 color` w shaderze fragmentów, następnie w funkcji `main` przypisz do niej wartość koloru. W shaderze fragmentów odbierz ją za pomocą `out` i przypisz do wyjściowego koloru.
Zauważ, że kolor ścian nie jest jednolity, zamiast tego przechodzą gradientem od jednego koloru do drugiego. Dzieje się tak, ponieważ na etapie rasteryzacji kolor jest interpolowany. To znaczy: wartość jest uśredniana pomiędzy wierzchołkami trójkąta.
### Zadanie
Sprawdź, jak będzie wyglądać prostopadłościan z wyłączoną interpolacją. Dodaj przed `in` i `out` ` color` słowo kluczowe `flat`.
### Zadanie
Prześlij czas od startu aplikacji do shadera fragmentów. Użyj funkcji `glfwGetTime`, by uzyskać czas. Utwórz zmienną `uniform` typu `float` we shaderze fragmentów. Następnie prześlij do niej wynik funkcji `glfwGetTime`. Aby przesłać czas do shadera, wykorzystaj funkcje `glUniform1f`. Pierwszym argumentem jest lokacja uniforma, drugim przypisywana wartość. Lokację uzyskamy za pomocą funckji `glGetUniformLocation(progam,"time")` pierwszym argumentem jest program, którego używamy a drugim nazwa zmiennej uniform.
Podziel kolor przez czas, by uzyskać efekt, w którym prostopadłościan robi się czarny.
### Zadanie*
Wykorzystaj przesłany czas, żeby sprawić, żeby prostopadłościan znikał przez mieszanie go z kolorem tła. Wykorzystaj do tego następujące funkcje GLSL: `mix`, `sin`, `vec4`. Opis ich działania możesz znaleźć w dokumentacji https://docs.gl/.
### Zadanie
Prześlij pozycję lokalną i globalną pozycję wierzchołków do shadera fragmentów i wyświetl ją.
W shaderze wierzchołków obok deklaracji `out vec4 color;` dodaj analogiczne o nazwie `pos_local` i `pos_global`. Do `pos_local` przypisz `vertexPosition`, a do `pos_global` przypisz `transformation * vertexPosition`. Podobnie dopisz odebranie ich w shaderze fragmentów. Użyj `pos_local`, następnie `pos_global` jako zamiast koloru. Dlaczego otrzymaliśmy taki efekt?
### Zadanie*
Użyj jednej ze zmiennych z poprzedniego zadania do zrobienia pasków na przynajmniej jednej ze ścian sześcianu. Wykorzystaj czas, żeby paski się przesuwały.

101
grk/cw 6/Zadania 4.html Normal file
View File

@ -0,0 +1,101 @@
<!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 4</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;}
</style>
<style>
.code-block {
background-color: #f4f4f4;
border-left: 5px solid #f36d33;
margin: 20px 0;
padding: 10px 20px;
font-family: Consolas, "Courier New", Courier, monospace;
color: #333;
overflow: auto;
}
</style>
<link rel="stylesheet" href="style.css" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h2 id="ładowanie-obiektów-za-pomocą-assimpa">Ładowanie obiektów za pomocą Assimp</h2>
<p>W projekcie zaimplementowano ładowanie modeli przy użyciu biblioteki Assimp. Obiekty są ładowane za pomocą funkcji <code>loadModelToContext(std::string path, Core::RenderContext&amp; context)</code>. Pierwszym argumentem tej funkcji jest ścieżka, pod którą znajduje się model, a drugim jest referencja do <code>RenderContext</code>. Ta struktura przechowuje informacje o modelu, m.in. o jego VAO czy liczbie wierzchołków. Rysowanie obiektu odbywa się za pomocą funkcji <code>Core::DrawContext(Core::RenderContext&amp; context)</code>. Obecnie na przykładzie rysowana jest sfera ładowana z pliku.</p>
<p>Podczas poprzednich zadań zdefiniowaliśmy funkcje tworzące macierze widoku i projekcji. Aby narysować model, należy najpierw zdefiniować macierz modelu, przemnożyć ją przez macierz kamery i macierz widoku, a następnie wysłać ją do GPU i dopiero potem narysować model. Te operacje są bardzo powtarzalne, dlatego można je przenieść do osobnej funkcji. W pliku <code>ex_4_1.hpp</code> znajduje się funkcja <code>drawObjectColor</code>, która przyjmuje rysowany obiekt jako <code>Core::RenderContext&amp;</code>, macierz modelu jako <code>glm::mat4</code> oraz kolor jako <code>glm::vec3</code>. <h3 id="zadanie">Zadanie</h3> Wszystkie obiekty rysowane przez <code>drawObjectColor</code> są w jednym kolorze napraw to. Wewnątrz funkcji przekaż kolor jako <code>uniform</code> do GPU (za pomocą funkcji <code>glUniform3f</code>) i odpowiednio zmodyfikuj shader fragmentów, aby wyznaczyć go jako kolor wyjściowy.</p>
<p>Korzystając z tej funkcji, stwórz układ słoneczny z przynajmniej jedną planetą, która posiada księżyc. Planeta powinna poruszać się wokół słońca, a księżyc wokół planety.</p>
<h3 id="zadanie">Zadanie*</h3>
<p>Rozbuduj układ planetarny do przynajmniej 5 planet i pasa asteroid. Ściągnij z internetu/stwórz kilka prostych modeli asteroid, z których zbudujesz pas asteroid.</p>
<h3 id="zadanie-1">Zadanie</h3>
<p>Celem tego zadania jest dodanie statku, który będzie latać po układzie planetarnym.</p>
<p>Załaduj model statku, który jest w pliku <code>spaceship.obj</code>. Stwórz zmienne globalne <code>spaceshipPos</code> oraz <code>spaceshipDir</code>, które będą określać pozycję i kierunek, w którym statek się porusza. Później będziemy je zmieniać za pomocą przycisków, na razie wewnątrz funkcji <code>processInput</code> przypisz do nich odpowiednio <code>cameraPos+1.5*cameraDir+glm::vec3(0,-0.5f,0)</code> oraz <code>cameraDir</code>. W ten sposób po prawidłowym ustawieniu macierzy statek będzie znajdował się zawsze przed kamerą.</p>
<p>Przesuń i obróć statek w odpowiedni sposób. Przesunięcie zrealizujemy przez translację do <code>spaceshipPos</code> natomiast macierz statku liczy się tak samo, jak macierz kamery, tylko zamiast <code>-cameraDir</code> bierzemy <code>spaceshipDir</code> i na końcu trzeba tę macierz odwrócić (lub transponować, co jest tym samym, ponieważ mówimy o macierzy ortonormalnej).</p>
<h3 id="zadanie-2">Zadanie</h3>
<h3 id="zadanie-3">Zadanie*</h3>
<p>Obecnie klawisze regulują ustawienia kamery, do której jest podpięty statek. Zmodyfikuj aplikację, aby klawisze umożliwiały poruszanie się statkiem, a kamera podążała za nim. W tym celu w obsłudze klawiatury modyfikuj wektory <code>spaceshipPos</code> i <code>spaceshipDir</code>. Następnie dostosuj <code>cameraPos</code> i <code>cameraDir</code> w zależności od wektorów <code>spaceshipPos</code> i <code>spaceshipDir</code>.</p>
<h3 id="zadanie-4">Zadanie*</h3>
<p>Obecnie szybkość ruchu statku lub kamery zależy od liczby klatek, co może powodować różne efekty na różnych komputerach, co nie jest pożądane. Aby to skorygować, musimy obliczyć czas, jaki upłynął między poszczególnymi klatkami i dostosować do niego przesunięcia oraz obroty. Utwórz zmienne globalne <code>float lastFrameTime</code> oraz <code>float deltaTime</code>, następnie w funkcji <code>renderScene</code> dodaj oblicz <code>deltaTime = time-lastFrameTime</code> i przypisz do zmiennej <code>lastFrameTime</code> wartość <code>time</code>. Nie chcemy, żeby wartość <code>deltaTime</code> była zbyt duża, gdy nagle spadnie liczba klatek, dlatego ucinamy ją od góry przez <code>0.1</code>.</p>
<p>Wykorzystaj <code>deltaTime</code> w funkcji <code>processInput</code> aby uniezależnić prędkość poruszania się od liczby klatek na sekundę.</p>
<h3 id="zadanie-5">Zadanie*</h3>
<p>Zastąp model statku innym modelem.</p>
<h2 id="bufor-głębokości">Bufor głębokości</h2>
<p>Bufor głębokości rejestruje odległość danego piksela od kamery. Pozwala to podczas rysowania kolejnych obiektów odrzucić piksele, które znajdowałyby się za już narysowanymi. Ten mechanizm jest automatycznie, żeby go uruchomić, wystarczy dodać instrukcję <code>glEnable(GL_DEPTH_TEST)</code>, poza tym przed rysowaniem klatki należy wyczyścić bufor głębokości, co robimy w instrukcji <code>glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)</code>.</p>
<h3 id="zadanie-7">Zadanie</h3>
<p>Sprawdź, co się stanie, gdy nie włączymy <code>glEnable(GL_DEPTH_TEST)</code> oraz sprawdź co, się dzieje, gdy nie czyścimy żadnego bufora lub gdy czyścimy tylko bufor koloru czy tylko bufor głębokości. Dlaczego dzieje się to, co widzisz?</p>
<h2 id="wizualizacja-bufora-głębokości">Wizualizacja bufora głębokości</h2>
<p>W tej części zwizualizujemy jak wygląda bufor głębokości przy pomocy skali szarości. Zrealizujemy poprzez napisanie odpowiedniego shadera.</p>
<blockquote>
<p><strong>Uwaga</strong> nie jest to faktycznie rysowanie bufora głębokości, to wymagałoby stworzenie FrameBufferObject renderowanie głębokości do niego i narysowanie wyniku na ekranie. Zrobimy to na późniejszych zajęciach przy okazji rysowania cieni.</p>
</blockquote>
<p>Wykorzystamy wbudowaną zmienną <code>gl_FragCoord</code> we fragment shaderze. Zawiera ona informacje o pozycji fragmentu.</p>
<h3 id="zadanie-8">Zadanie</h3>
<p>We fragment shaderze podmień wartości R G B w shaderze fragmentów na <code>gl_FragCoord.z</code>.</p>
<p>Zauważ, że obiekty są bardzo jasne i stają się ciemniejsze, dopiero gdy kamera podjedzie bardzo blisko. Wynika to z tego, że wartości <code>z</code> w <code>gl_FragCoord</code> nie są liniowe ze względu na rzutowanie perspektywiczne omówione na poprzednich zajęciach. Poniższy wykres prezentuje przykładową różnicę między faktyczną wartością a wartością w <code>gl_FragCoord</code>. <img src="./img/z_depth_graph2.jpg" /></p>
<p>My chcielibyśmy wyświetlać je liniowo. W tym celu będziemy musieli wrócić do współrzędnych w przestrzeni świata. Zauważ, że wartości <code>gl_FragCoord.z</code> są z zakresu od <span class="math inline">\([0,1]\)</span> a nie <span class="math inline">\([-1,1]\)</span> jak są zapisane współrzędne w przestrzeni ekranu. Dlatego pierwszym krokiem będzie przekonwertowanie ich (poprzez pomnożenie przez 2 i odjęcie 1). Współrzędne w przestrzeni ekranu obliczamy wzorem <span class="math display">\[z&#39;=-\frac{(n + f)}{(n - f)}- \frac{(2 n f)}{z(n - f)}.\]</span>My chcemy obliczyć <span class="math inline">\(z\)</span> po przekształceniu wzoru otrzymujemy: <span class="math display">\[z=\frac{-2nf}{z&#39;(n-f)+n+f}.\]</span> <h3 id="zadanie-9">Zadanie</h3> We fragment shaderze uwórz funkcję, która oblicza <span class="math inline">\(z\)</span> i wyświetl zlinearyzowaną odległość. Pamiętaj, że wartość <span class="math inline">\(z\)</span> jest z zakresu od <span class="math inline">\(n\)</span> do <span class="math inline">\(f\)</span>, dlatego zmień podziel ją przez <span class="math inline">\(-f\)</span> przed rysowaniem.</p>
<h3 id="zadanie-9">Zadanie</h3>
<p>Wykorzystaj informację o odległości, żeby dodać do sceny efekt mgły. Zmieszaj kolor (funkcja "mix" w glsl) obiektu z kolorem tła, jako współczynnik weź wartość z poprzedniego zadania.</p>
<h2 id="kreatywne-wykorzystanie-bufora-głębokości">Kreatywne wykorzystanie bufora głębokości</h2>
<p>Czasem chcielibyśmy, żeby niektóre wyświetlane elementy były inaczej traktowane przez bufor głębokości. Przykładowo chcielibyśmy stworzyć bardziej złożone tło dla naszej sceny. Chcemy wtedy, żeby to tło było ,,za każdym innym obiektem w scenie. Możemy to osiągnąć poprzez namalowanie tła na początku, a następnie usunięcie zawartości bufora głębokości.</p>
<h3 id="zadanie-10">Zadanie*</h3>
<p>Dodaj jakiś rodzaj tła w sposób opisany powyżej. Mogą być to na przykład małe sfery udające gwiazdy. Prostokąt w przestrzeni ekranu, który będzie zmieniał kolory czy kręcący się prostopadłościan.</p>
<h2 id="kreatywne-wykorzystanie-bufora-głębokości">Implementacja ruchu kamery w symulatorze kosmicznym bez synchronizacji modelu statku</h2>
<h3 id="zadanie-6">Zadanie*</h3>
<p>W tym ćwiczeniu zajmiemy się implementacją systemu kontroli kamery, który pozwoli na interaktywne sterowanie widokiem w symulatorze lotu. Będzie to wymagało obsługi wejścia myszy do kontroli ruchów pitch i yaw. Dodaj nastepujace zmienne globalne do kodu.
<pre class="code-block"><code>
float pitch = 0.0f;
float yaw = -90.0f;
float lastX = 800.0f / 2.0;
float lastY = 600.0 / 2.0;
bool firstMouse = true;
</code></pre></p>
Zaimplementuj w funkcji processinput logikę odpowiedzialną za przetwarzanie wejścia myszy. Użyj funkcji glfwGetCursorPos do uzyskania bieżącej pozycji kursora. Dodaj zmienną sensitivity do regulacji czułości myszy. Na początku sprawdzamy, czy jest to pierwsze uchwycenie pozycji myszy po uruchomieniu aplikacji. Jeśli tak, to zapisujemy bieżącą pozycję myszy jako punkt odniesienia (lastX i lastY) i ustawiamy zmienną firstMouse na false. To zapobiega gwałtownemu skoku kamery, gdybyśmy po raz pierwszy poruszyli myszą. Następnie obliczamy różnicę (xoffset i yoffset) między aktualną pozycją kursora a ostatnią zapisaną pozycją. Zauważ, że wartość yoffset jest odwrócona, ponieważ w systemach okienkowych współrzędna y zwykle rośnie w dół ekranu, a chcemy, aby ruch w górę odpowiadał wzrostowi kąta widzenia kamery. Po obliczeniu przesunięć skalujemy je wartością sensitivity, która pozwala na dostosowanie reakcji kamery na ruch myszy. Mała wartość czułości sprawi, że kamera będzie reagować łagodniej, podczas gdy większa wartość uczyni ruchy bardziej gwałtownymi. Na koniec, dodajemy przeskalowane przesunięcia do naszych kątów orientacji kamery: yaw (odpowiedzialny za obrót wokół osi pionowej) i pitch (odpowiedzialny za obrót wokół osi poziomej). Trzeba tu uważać, aby nie przekroczyć pewnych granic. Na przykład, nie chcemy, aby kamera "przewracała się" do góry nogami, dlatego ograniczamy kąt pitch do wartości pomiędzy -89 a 89 stopni. Dodaj logikę do ograniczenia kąta pitch, aby uniknąć "przewrócenia" kamery.
<pre class="code-block"><code> if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
</code></pre></p>
Zastosuj funkcje trygonometryczne do przeliczenia kątów na wektor kierunku kamery:<pre class="code-block"><code>
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraDir = glm::normalize(front);</code></pre></p>
Na zakończenie ćwiczenia oczekujemy, że symulator będzie poprawnie implementował ruch kamery, lecz dołączony model statku kosmicznego nie będzie jeszcze obracał się razem z kamerą.
</body>
</html>

74
grk/cw 6/Zadania 4.md Normal file
View File

@ -0,0 +1,74 @@
## Ładowanie obiektów za pomocą assimpa
W projekcie zaimplentowane jest ładowanie modeli z użyciem biblioteki assimp. Obiekty ładuje się za pomocą funkcji `loadModelToContext(std::string path, Core::RenderContext& context)` pierwszym jej argumentem jest ścieżka, pod którą znajduje się model, drugim argumentem jest referencja do `RenderContext`. Ta struktura przechowuje informacje o modelu, m.in. jego VAO czy liczba wierzchołku. Rysuje się go za pomocą funkcji `Core::DrawContext(Core::RenderContext& context)`. Teraz przykładowo rysowana jest sfera ładowana z pliku.
W trakcie poprzednich zadań zdefiniowaliśmy funkcje tworzące macierze widoku i projekcji. Aby narysować model, należy najpierw zdefiniować macierz modelu, przemnożyć ją przez macierz kamery i macierz widoku i wysłać ją do GPU i dopiero narysować model. Te operacje są bardzo powtarzalne i można je przenieść do osobnej funkcji. Dlatego w `ex_4_1.hpp` znajduje funkcja `drawObjectColor` która przyjmuje rysowany obiekt jako `Core::RenderContext&`, macierz modelu jako `glm::mat4` i kolor jako `glm::vec3`.
### Zadanie
Wszystkie obiekty rysowane przez `drawObjectColor` rysują się na jeden kolor, napraw to. Wewnątrz funkcji prześlij kolor jako `uniform` do GPU (za pomocą funkcji `glUniform3f`) i tak zmodyfikuj shader fragmentów, żeby ustalić go kolorem wyjściowym.
Korzystając z tej funkcji, stwórz układ słoneczny z przynajmniej jedną planetą, która posiada księżyc. Planeta powinna poruszać się wokół słońca a księżyc wokół planety.
### Zadanie*
Rozbuduj układ planetarny do przynajmniej 5 planet i pasa asteroid. Ściągnij z internetu/stwórz kilka prostych modeli asteroid, z których zbudujesz pas asteroid.
### Zadanie
Celem tego zadania jest dodanie statku, który będzie latać po układzie planetarnym.
Załaduj model statku, który jest w pliku `spaceship.obj`. Stwórz zmienne globalne `spaceshipPos` oraz `spaceshipDir`, które będą określać pozycję i kierunek, w którym statek się porusza. Później będziemy je zmieniać za pomocą przycisków, na razie wewnątrz funkcji `processInput` przypisz do nich odpowiednio `cameraPos+1.5*cameraDir+glm::vec3(0,-0.5f,0)` oraz `cameraDir`. W ten sposób po prawidłowym ustawieniu macierzy statek będzie znajdował się zawsze przed kamerą.
Przesuń i obróć statek w odpowiedni sposób. Przesunięcie zrealizujemy przez translację do `spaceshipPos` natomiast macierz statku liczy się tak samo, jak macierz kamery, tylko zamiast `cameraDir` bierzemy `spaceshipDir` i na końcu trzeba tę macierz odwrócić (lub transponować, co jest tym samym, ponieważ mówimy o macierzy ortonormalnej).
Możliwe, że model nie jest skierowany w stronę tej samej osi, co domyślnie w openGL, w tym wypadku musisz dodać dodatkową rotację o stały kąt, która naprawi ten problem.
### Zadanie
### Zadanie*
W tej chwili klawisze ustawiają kamerę, do której podczepiony jest statek. Zmodyfikuj aplikację, żeby klawisze przesuwały statek, a kamera była do niego podczepiona. Aby to zrobić, wystarczy w obsłudze klawiatury modyfikować wektory `spaceshipPos` i `spaceshipDir`. Natomiast `cameraPos` i `cameraDir` uzależnić od wektorów `spaceshipPos` i `spaceshipDir`.
### Zadanie*
W tej chwili szybkość poruszania się statku/kamery jest uzależniona od liczby klatek, co daje różne efekty na różnych komputerach i jest raczej niepożądane. Aby to naprawić, musimy obliczyć, ile czasu minęło między klatkami i od tego uzależnić przesunięcia oraz obroty. Utwórz zmienne globalne `float lastFrameTime` oraz `float deltaTime`, następnie w funkcji `renderScene` dodaj oblicz `deltaTime = time-lastFrameTime` i przypisz do zmiennej `lastFrameTime` wartość `time`. Nie chcemy, żeby wartość `deltaTime` była zbyt duża, gdy nagle spadnie liczba klatek, dlatego ucinamy ją od góry przez `0.1`.
Wykorzystaj `deltaTime` w funkcji `processInput` aby uniezależnić prędkość poruszania się od liczby klatek na sekundę.
### Zadanie*
Podmień model statku na jakiś inny.
### Zadanie**
dodaj obsługę myszki, która będzie obracać kamerą.
## Bufor głębokości
Bufor głębokości zapisuje, w jakiej odległości od kamery znajduje dany piksel. Dzięki temu przy rysowaniu kolejnych obiektów można odrzucić te piksele, które znajdowałyby się za narysowanymi. Ten mechanizm jest automatycznie, żeby go uruchomić, wystarczy dodać instrukcję `glEnable(GL_DEPTH_TEST)`, poza tym przed rysowaniem klatki należy wyczyścić bufor głębokości, co robimy w instrukcji `glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)`.
### Zadanie
Sprawdź, co się stanie, gdy nie włączymy `glEnable(GL_DEPTH_TEST)` oraz sprawdź co, się dzieje, gdy nie czyścimy żadnego bufora lub gdy czyścimy tylko bufor koloru czy tylko bufor głębokości. Dlaczego dzieje się to, co widzisz?
## Wizualizacja bufora głębokości
W tej części zwizualizujemy jak wygląda bufor głębokości przy pomocy skali szarości. Zrealizujemy poprzez napisanie odpowiedniego shadera.
> **Uwaga** nie jest to faktycznie rysowanie bufora głębokości, to wymagałoby stworzenie FrameBufferObject renderowanie głębokości do niego i narysowanie wyniku na ekranie. Zrobimy to na późniejszych zajęciach przy okazji rysowania cieni.
Wykorzystamy wbudowaną zmienną `gl_FragCoord` we fragment shaderze. Zawiera ona informacje o pozycji fragmentu.
### Zadanie
We fragment shaderze podmień wartości R G B w shaderze fragmentów na `gl_FragCoord.z`.
Zauważ, że obiekty są bardzo jasne i stają się ciemniejsze, dopiero gdy kamera podjedzie bardzo blisko. Wynika to z tego, że wartości `z` w `gl_FragCoord` nie są liniowe ze względu na rzutowanie perspektywiczne omówione na poprzednich zajęciach. Poniższy wykres prezentuje przykładową różnicę między faktyczną wartością a wartością w `gl_FragCoord`.
![](./img/z_depth_graph2.jpg)
My chcielibyśmy wyświetlać je liniowo. W tym celu będziemy musieli wrócić do współrzędnych w przestrzeni świata.
Zauważ, że wartości `gl_FragCoord.z` są z zakresu od $[0,1]$ a nie $[-1,1]$ jak są zapisane współrzędne w przestrzeni ekranu. Dlatego pierwszym krokiem będzie przekonwertowanie ich (poprzez pomnożenie przez 2 i odjęcie 1). Współrzędne w przestrzeni ekranu obliczamy wzorem $$z'=-\frac{(n + f)}{(n - f)}- \frac{(2 n f)}{z(n - f)}.$$My chcemy obliczyć $z$ po przekształceniu wzoru otrzymujemy:
$$z=\frac{-2nf}{z'(n-f)+n+f}.$$
### Zadanie
We fragment shaderze uwórz funkcję, która oblicza $z$ i wyświetl zlinearyzowaną odległość. Pamiętaj, że wartość $z$ jest z zakresu od $n$ do $f$, dlatego zmień podziel ją przez $f$ przed rysowaniem.
### Zadanie*
Wykorzystaj informację o odległości, żeby dodać do sceny efekt mgły. Zmieszaj kolor obiektu z kolorem tła, jako współczynnik weź wartość z poprzedniego zadania.
## Kreatywne wykorzystanie bufora głębokości
Czasem chcielibyśmy, żeby niektóre wyświetlane elementy były inaczej traktowane przez bufor głębokości. Przykładowo chcielibyśmy stworzyć bardziej złożone tło dla naszej sceny. Chcemy wtedy, żeby to tło było ,,za'' każdym innym obiektem w scenie. Możemy to osiągnąć poprzez namalowanie tła na początku, a następnie usunięcie zawartości bufora głębokości.
### Zadanie
Dodaj jakiś rodzaj tła w sposób opisany powyżej. Mogą być to na przykład małe sfery udające gwiazdy. Prostokąt w przestrzeni ekranu, który będzie zmieniał kolory czy kręcący się prostopadłościan.

92
grk/cw 6/Zadania 5.md Normal file
View File

@ -0,0 +1,92 @@
## Oświetlenie Phonga
W trakcie tych zajęć zajmiemy się implementacją modelu oświetlenia Phonga. Na poprzednich zajęciach zbudowaliśmy układ słoneczny. Wykorzystamy go w trakcie tych zajęć. Jeżeli go zrobiłeś, to przekopiuj do `ex_5_1.hpp` kod z poprzednich zajęć. W przeciwnym wypadku wykorzystaj ten, który jest zaimplementowany w `ex_5_1.hpp`. W zadaniu będzie nam potrzebny statek latający przed kamerą, jak nie ma tego w Twojej scenie to skopiuj to z `ex_5_1.hpp`.
## Zadanie - *diffuse*
Oblicz we fragment shaderze oświetlenie obiektu przy użyciu modelu Phonga dla odbicia rozproszonego (*diffuse)
1. Przekaż źródło światła. Na razie przyjmiemy kierunkowy model oświetlenia, dlatego źródło będzie opisane jako wektor kierunkowy:
- Prześlij do shadera fragmentów zmienna typu `uniform vec3` (nazwij ją np. `lightDir`), w której będzie się znajdować wektor kierunkowy.
- Należy to zrobić podobnie do tego, jak przesyłany jest kolor.
- Jako kierunek światła wybierz dowolny wektor jednostkowy. (Możesz wziąć dowolny niezerowy wektor następnie go znormalizować).
* Dodatkowo prześlij drugą zmienną `uniform vec3 lightColor`, w której umieścimy kolor światła. Prześlij tam wartości ze zmiennej `glm::vec3 lightColor`.
2. Oblicz natężenie w shaderze fragmentów:
- prześlij normalne z shadera fragmentów do shadera wierzchołków
- znormalizuj wektor normalny przed użyciem go w obliczeniach (uśrednianie wektorów normalnych wierzchołków może spowodować, że przestaje one być jednostkowe).
- Natężenie to iloczyn skalarny wektora normalnego powierzchni i odwrotnego wektora kierunku padania światła. Skorzystaj z funkcji `dot`.
- Natężenie nie może być ujemne. Przytnij natężenie do zera przy użyciu: `x = max(x, 0.0)`
3. Zastosuj obliczone natężenie, aby zmodyfikować kolor obiektu:
- Przemnóż kolor RGB fragmentu przez obliczone natężenie i przez kolor światła z `lightColor`.
## Zadanie - obsługa obrotów
Dlaczego oświetlenie statku nie zmienia się podczas jego obracania?
(Wektory normalne są w układzie lokalnym modelu, a wektor padania światła w układzie świata)
Należy wykonać transformacje wektorów normalnych do przestrzeni świata:
- Prześlij macierz modelu rysowanego obiektu (_model Matrix_) jako osobna zmienna do vertex shadera (`uniform mat4`).
- Przemnóż przez te macierz wektor normalny wierzchołka przed przesłaniem go do shadera fragmentów.
- Współrzędna **w** dopisana do wektora przed mnożeniem przez macierz powinna być ustawiona na 0. Wynika to z tego, że w przypadku transformacji wektorów reprezentujących kierunki w przestrzeni, nie chcemy dokonywać translacji — np. wektor normalny do powierzchni zależy od orientacji obiektu, ale nie od jego pozycji (przesunięcia) w przestrzeni świata.
## Zadanie - *specular*
Uzupełnił model o czynnik odbicia zwierciadlanego (*specular*). W tym celu:
1. Potrzebny będzie wektor od rysowanego fragmentu do pozycji kamery:
- Wyślij pozycje kamery (`cameraPos`) jako kolejna zmienna do fragment shadera.
- Podobnie jak wektory normalne prześlij z vertex do fragment shadera pozycje wierzchołków (`vertexPosition`) w przestrzeni świata (czyli pomnożone przez macierz **modelMatrix**). Pamiętaj, że tym razem wektory reprezentują punkty, a nie kierunki - współrzędna **w** przed mnożeniem musi być ustawiona na 1. W wyniku rasteryzacji otrzymamy w shaderze fragmentu jego pozycję (nazywaną pozycją fragmentu)
- Oblicz wektor **V** (_view direction_) jako znormalizowaną różnice pozycji kamery i pozycji fragmentu.
2. Oblicz natężenie światła odbitego we _fragment shaderze_:
- Oblicz wektor kierunku odbicia światła **R** przy użyciu funkcji [`reflect`](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/reflect.xhtml). Pamiętaj, żeby przesłać do funkcji odwrócony wektor kierunku światła.
- Oblicz natężenie: iloczyn skalarny **V** i **R**, przycięty do zera ( `max(...,0.0)` ), a następnie podniesiony do wysokiej potęgi (np. 8, 50, 1000), która jest miara połyskliwości powierzchni.
3. Ustal ostateczny kolor piksela na `objectColor * diffuse + lightColor * specular`. Oznacza to najprostszy przypadek, gdy kolor światła odbitego jest biały.
## Zadanie - oświetlenie punktowe
W układzie planetarnym obiektem oświetlającym powinno być słońce, dlatego zamień oświetlenie kierunkowe na punktowe:
- Zamiast przesyłać (w `lightDir`) kierunek światła, prześlij pozycję słońca do fragment shadera (taką jak ustawiłeś w punkcie powyżej) jako uniform vec3 (nazwij go `lightPos`).
- Oblicz kierunek światła odejmując od pozycji fragmentu pozycję światła, znormalizuj wynik. Zapisz wynik w zmiennej `lightDir`.
- Słońce będzie czarne, nie martw się tym, tylko spójrz na punkt następny.
## Zadanie - shader słońca
Źródło światła znajduje się wewnątrz kuli, która reprezentuje słońce, dlatego jest czarna. By to naprawić, utwórz osobny shader, który będzie odpowiadać za renderowanie słońca.
Celem tego zadania jest stworzenie shadera (**shader_4_sun.vert**_ i **shader_4_sun.frag**), który będzie odpowiadał wyłącznie za rysowanie słońca. Poprzednie shadery (**shader_4_1.vert**_ i **shader_4_1.frag**) nadal mają rysować pozostałe obiekty. a) zainicjalizuj _program_ (shadery): - Pliki **shader_4_sun.vert** i **shader_4_sun.frag** są identyczne z 4_1** przed zmianami, będą punktem wyjścia dla _shadera_ słońca.
1. Utwórz zmienną globalną `GLuint programSun` na adres shadera słońca. Stwórz _program_ za pomocą `shaderLoader.CreateProgram` analogicznie jak tworzy się `program` z **shader_4_1.vert** i **shader_4_1.frag** (parametry wejściowe to ścieżka do shadera wierzchołków i fragmentów **shader_4_sun.vert** i **shader_4_sun.frag**).
2. W skomplikowanym projekcie różne typy obiektów rysuje się przy użyciu różnych shaderów, zate potrzebna jest w programie architektura, która na to pozwala. Ustaw odpowiedni _program_ (shadery) do rysowania słońca:
- funkcja `drawObject` korzysta z globalnej zmiennej `program`, żeby wskazywać shadery do rysowania. Dodaj argument do funkcji, który będziesz przekazywać adres _programu_, który ma być wykorzystany do rysowania.
- dodaj odpowiedni _program_ w wywołaniach `drawObject`.
## Osłabienie światła, tone mapping
### Zadanie - Osłabienie światła (attenuation)
Światło pochodzące z punktowego źródła traci na sile wraz z dystansem. Wynika to z tego, że rozprasza się na większą powierzchnię.
Dodaj ten efekt do shadera. Zamiast brać kolor światła bezpośrednio, podziel go przez kwadrat dystansu od źródła świata.
#### Tone mapping
Przez obecną zmianę scena stała się ciemna. Wymaga to od nas zmiany 'koloru' światła na wartości dużo większe niż do tej pory. Jeśli teraz to zrobimy i przesadzimy w drugą stronę, otrzymamy efekt prześwietlenia. Wynika to z ograniczenia zakresu kolorów do $[0,1]$ (obsługą wyższych wartości nazywamy HDR). Rozwiązaniem jest pracowanie na wartościach powyżej 1 wykorzystanie *tone mappingu* do przeniesienia ich w zakres $[0,1]$. Istnieje wiele wzorów, które są wykorzystywane do tego, jeden z nich to:
$$C_{mapped} = 1-e^{-C * E},$$
gdzie C to kolor sceny a E to parametr ekspozycji (z zakresu $(0,\infty)$, który może być dostosowany w zależności od jasności.
### Zadanie - Tone mapping*
Zwiększ siłę słońca przynajmniej stukrotnie. Zaimplementuj powyższą metodę tone mappingu i dodaj możliwość sterowania ekspozycją za pomocą klawiszy 1 i 2.
### Zadanie*
Dodaj drugie źródło oświetlenia w postaci reflektora statku. Reflektor świeci tylko w określonym stożku,dlatego oprócz pozycji `spotPos` posiada również kierunek `spotDir` i kąt świecenia $\phi$. Po obliczeniu dla niego `lightDir` należy sprawdzić, czy iloczyn skalarny pomiędzy `lightDir` a `spodDir` jest większy niż $\cos\phi$ . Jeżeli nie jest, to stożek nie świeci w tym miejscu. Można ułatwić sobie implementację wielu źródeł światła poprzez przeniesienie obliczeń oświetlenia do funkcji, która przyjmuje kierunek światła i siłę naświetlenie.
Zwróć uwagę, że SpotDir to co innego niż light Dir w poprzednich zadaniach
![](./img/spotlight.png)
## Zmień shader słońca na bardziej realistyczny.
### Zadanie*
Na poniższym obrazku jest zdjęcie słońca. Jest ono ciemniejsze na brzegach spróbuj uzyskać podobny efekt. Przydadzą się wektory z poprzednich punktów jak wektor normalny i wektor **V**.
![](./img/sun.png)

View File

@ -24,7 +24,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Camera.h" />
<ClInclude Include="src\ex_6_1.hpp" />
<ClInclude Include="src\Planet.hpp" />
<ClInclude Include="src\objload.h" />
<ClInclude Include="src\Render_Utils.h" />
<ClInclude Include="src\Shader_Loader.h" />
@ -37,33 +37,33 @@
<ClInclude Include="src\Texture.h" />
</ItemGroup>
<ItemGroup>
<None Include="shaders\shader_5_1.frag" />
<None Include="shaders\shader_5_1.vert" />
<None Include="shaders\shader_5_1_tex.frag" />
<None Include="shaders\shader_5_1_tex.vert" />
<None Include="shaders\shader_5_sun.frag" />
<None Include="shaders\shader_5_sun.vert" />
<None Include="shaders\shader.frag" />
<None Include="shaders\shader.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" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{3952C396-B1C6-44CD-96DD-C1AC15D32978}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>grk-cw6</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>grk-cw6</ProjectName>
<WindowsTargetPlatformVersion>10.0.22000.0</WindowsTargetPlatformVersion>
<ProjectName>Planeta</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">

View File

@ -86,27 +86,27 @@
<ClInclude Include="src\SOIL\image_DXT.h">
<Filter>Source Files\SOIL</Filter>
</ClInclude>
<ClInclude Include="src\ex_6_1.hpp">
<ClInclude Include="src\Planet.hpp">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="shaders\shader_5_sun.frag">
<None Include="shaders\shader_sun.frag">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_5_sun.vert">
<None Include="shaders\shader_sun.vert">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_5_1.frag">
<None Include="shaders\shader.frag">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_5_1.vert">
<None Include="shaders\shader.vert">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_5_1_tex.vert">
<None Include="shaders\shader_tex.vert">
<Filter>Shader Files</Filter>
</None>
<None Include="shaders\shader_5_1_tex.frag">
<None Include="shaders\shader_tex.frag">
<Filter>Shader Files</Filter>
</None>
</ItemGroup>

View File

@ -4,15 +4,18 @@ 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 lightDir = normalize(lightPos - worldPos);
vec3 normal = normalize(vecNormal);
float diffuse=max(0,dot(normal,lightDir));
outColor = vec4(color*min(1,AMBIENT+diffuse), 1.0);
float diffuse = max(0, dot(normal, lightDir));
outColor = vec4(color * min(1, AMBIENT + diffuse), 1.0);
}

View File

@ -12,7 +12,7 @@ out vec3 worldPos;
void main()
{
worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz;
vecNormal = (modelMatrix* vec4(vertexNormal,0)).xyz;
worldPos = (modelMatrix * vec4(vertexPosition,1)).xyz;
vecNormal = (modelMatrix * vec4(vertexNormal,0)).xyz;
gl_Position = transformation * vec4(vertexPosition, 1.0);
}

View File

@ -2,8 +2,9 @@
float AMBIENT = 0.1;
uniform vec3 color;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 lightDir;
in vec3 vecNormal;
in vec3 worldPos;
@ -15,10 +16,11 @@ uniform sampler2D colorTexture;
void main()
{
vec3 lightDir = normalize(lightPos-worldPos);
//vec3 lightDir = normalize(lightPos - worldPos);
vec3 normal = normalize(vecNormal);
float diffuse=max(0,dot(normal,lightDir));
float diffuse = max(0.0, dot(normal, -lightDir));
vec4 textureColor = texture2D(colorTexture, vTC);
outColor = vec4(vec3(textureColor)*min(1,AMBIENT+diffuse), 1.0);
outColor = vec4(vec3(textureColor) * min(1, AMBIENT + diffuse), 1.0);
}

View File

@ -14,8 +14,8 @@ out vec2 vTC;
void main()
{
worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz;
vecNormal = (modelMatrix* vec4(vertexNormal,0)).xyz;
worldPos = (modelMatrix * vec4(vertexPosition, 1)).xyz;
vecNormal = (modelMatrix * vec4(vertexNormal, 0)).xyz;
gl_Position = transformation * vec4(vertexPosition, 1.0);
vTC = vertexTexCoord;

View File

@ -38,17 +38,17 @@ GLuint programTex;
Core::Shader_Loader shaderLoader;
Core::RenderContext shipContext;
//Core::RenderContext shipContext;
Core::RenderContext sphereContext;
glm::vec3 cameraPos = glm::vec3(-4.f, 0, 0);
glm::vec3 cameraPos = glm::vec3(-5.f, 0, 0);
glm::vec3 cameraDir = glm::vec3(1.f, 0.f, 0.f);
GLuint VAO, VBO;
glm::vec3 shipPos = glm::vec3(-4.f, 0, 0);
glm::vec3 shipDir = glm::vec3(1.f, 0.f, 0.f);
//glm::vec3 shipPos = glm::vec3(-4.f, 0, 0);
//glm::vec3 shipDir = glm::vec3(1.f, 0.f, 0.f);
float aspectRatio = 1.f;
float aspectRatio = 1.77f;
glm::vec3 lightColor = glm::vec3(0.9, 0.7, 0.8);
@ -70,7 +70,7 @@ glm::mat4 createCameraMatrix()
return cameraMatrix;
}
/*
glm::mat4 createShipMatrix()
{
glm::vec3 cameraSide = glm::normalize(glm::cross(cameraDir, glm::vec3(0.f, 1.f, 0.f)));
@ -87,18 +87,20 @@ glm::mat4 createShipMatrix()
return shipRotationMatrix;
}
*/
glm::mat4 createPerspectiveMatrix()
{
glm::mat4 perspectiveMatrix;
float n = 0.05;
float f = 20.;
float a1 = glm::min(aspectRatio, 1.f);
float a2 = glm::min(1 / aspectRatio, 1.f);
float n = 0.05f;
float f = 20.f;
float fov = 105.f;
float PI = 3.14159265359f;
float S = 1 / (tan((fov / 2) * (PI / 180)));
perspectiveMatrix = glm::mat4({
1,0.,0.,0.,
0.,1,0.,0.,
S,0.,0.,0.,
0.,S * aspectRatio,0.,0.,
0.,0.,(f + n) / (n - f),2 * f * n / (n - f),
0.,0.,-1.,0.,
});
@ -119,7 +121,7 @@ void drawObjectTexture(Core::RenderContext& context, glm::mat4 modelMatrix, GLui
Core::DrawContext(context);
glUseProgram(0);
}
/*
void drawObjectColor(Core::RenderContext& context, glm::mat4 modelMatrix, glm::vec3 color) {
glUseProgram(program);
glUniform3f(glGetUniformLocation(program, "color"), color.x, color.y, color.z);
@ -130,13 +132,15 @@ void drawObjectColor(Core::RenderContext& context, glm::mat4 modelMatrix, glm::v
Core::DrawContext(context);
glUseProgram(0);
}
*/
void renderScene(GLFWwindow* window)
{
glClearColor(0.0f, 0.0f, 0.2f, 1.0f);
glClearColor(0.0f, 0.0f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 transformation;
float time = glfwGetTime();
/*
glm::mat4 sunScale = glm::scale(glm::vec3(1.75));
glm::mat4 mercuryScale = glm::scale(glm::vec3(0.24));
@ -162,15 +166,9 @@ void renderScene(GLFWwindow* window)
glm::mat4 shipScale = glm::scale(glm::vec3(0.3));
glm::mat4 shipRotate = createShipMatrix();
glm::mat4 shipTranslate = glm::translate(shipPos);
*/
glUseProgram(program);
//glUniform3f(glGetUniformLocation(program, "lightDir"), 1.0, -1.0, 0.0);
//glUniform3f(glGetUniformLocation(program, "lightColor"), lightColor.x, lightColor.y, lightColor.z);
//glUniform3f(glGetUniformLocation(program, "cameraPos"), cameraPos.x, cameraPos.y, cameraPos.z);
glUniform3f(glGetUniformLocation(program, "lightPos"), 0.0, 0.0, 0.0);
glUseProgram(0);
/*
drawObjectColor(sphereContext, sunScale, glm::vec3(0.9, 0.9, 0.2)); //sun
drawObjectTexture(sphereContext, mercuryRotate * mercuryTranslate * mercuryScale, texture::mercury); //mercury
@ -184,14 +182,29 @@ void renderScene(GLFWwindow* window)
drawObjectTexture(sphereContext, marsRotate * marsTranslate * marsScale, texture::mars); //mars
drawObjectTexture(shipContext, shipTranslate * shipRotate * shipScale, texture::ship); //ship
*/
glUseProgram(programTex);
glUniform3f(glGetUniformLocation(programTex, "lightColor"), lightColor.x, lightColor.y, lightColor.z);
glUniform3f(glGetUniformLocation(programTex, "lightPos"), cameraPos.x, cameraPos.y, cameraPos.z);
glUniform3f(glGetUniformLocation(programTex, "lightDir"), cameraDir.x, cameraDir.y, cameraDir.z);
glUseProgram(0);
glm::mat4 planetScale = glm::scale(glm::vec3(2));
glm::mat4 planetRotate = glm::rotate(time * 0.2f, glm::vec3(0, 1, 0));
glm::mat4 planetTranslate = glm::translate(glm::vec3(0, 0, 0));
drawObjectTexture(sphereContext, planetRotate * planetTranslate * planetScale, texture::earth);
glfwSwapBuffers(window);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
aspectRatio = width / float(height);
aspectRatio = float(width) / float(height);
glViewport(0, 0, width, height);
}
void loadModelToContext(std::string path, Core::RenderContext& context)
{
Assimp::Importer import;
@ -210,24 +223,12 @@ void init(GLFWwindow* window)
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glEnable(GL_DEPTH_TEST);
program = shaderLoader.CreateProgram("shaders/shader_5_1.vert", "shaders/shader_5_1.frag");
programTex = shaderLoader.CreateProgram("shaders/shader_5_1_tex.vert", "shaders/shader_5_1_tex.frag");
program = shaderLoader.CreateProgram("shaders/shader.vert", "shaders/shader.frag");
programTex = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
loadModelToContext("./models/sphere.obj", sphereContext);
loadModelToContext("./models/spaceship.obj", shipContext);
texture::earth = Core::LoadTexture("./textures/earth2.png");
texture::clouds = Core::LoadTexture("./textures/clouds.jpg");
texture::moon = Core::LoadTexture("./textures/moon.jpg");
texture::ship = Core::LoadTexture("./textures/metal.jpg");
texture::grid = Core::LoadTexture("./textures/grid.png");
texture::mercury = Core::LoadTexture("./textures/mercury.jpg");
texture::venus = Core::LoadTexture("./textures/venus.jpg");
texture::mars = Core::LoadTexture("./textures/mars.jpg");
//texture::earthNormal = Core::LoadTexture("./textures/earth_normalmap.png");
//texture::asteroidNormal = Core::LoadTexture("./textures/moon_normals.png");
//texture::shipNormal = Core::LoadTexture("./textures/spaceship_normal.jpg");
}
void shutdown(GLFWwindow* window)
@ -240,9 +241,9 @@ void processInput(GLFWwindow* window)
{
glm::vec3 cameraSide = glm::normalize(glm::cross(cameraDir, glm::vec3(0.f, 1.f, 0.f)));
float angleSpeed = 0.001f;
float moveSpeed = 0.003f;
float angleSpeed = 0.01f;
float moveSpeed = 0.03f;
/*
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
@ -258,9 +259,9 @@ void processInput(GLFWwindow* window)
cameraDir = glm::vec3(glm::eulerAngleY(angleSpeed) * glm::vec4(cameraDir, 0));
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraDir = glm::vec3(glm::eulerAngleY(-angleSpeed) * glm::vec4(cameraDir, 0));
shipPos = cameraPos + 0.75 * cameraDir + glm::vec3(0, -0.25f, 0);
shipDir = cameraDir;
*/
//shipPos = cameraPos + 0.75 * cameraDir + glm::vec3(0, -0.25f, 0);
//shipDir = cameraDir;
//cameraDir = glm::normalize(-cameraPos);
@ -276,4 +277,3 @@ void renderLoop(GLFWwindow* window) {
glfwPollEvents();
}
}
//}

View File

@ -6,7 +6,7 @@
#include <iostream>
#include <cmath>
#include "ex_6_1.hpp"
#include "Planet.hpp"
@ -23,7 +23,7 @@ int main(int argc, char** argv)
#endif
// tworzenie okna za pomoca glfw
GLFWwindow* window = glfwCreateWindow(500, 500, "FirstWindow", NULL, NULL);
GLFWwindow* window = glfwCreateWindow(960, 540, "Planet Editor", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
@ -34,7 +34,7 @@ int main(int argc, char** argv)
// ladowanie OpenGL za pomoca glew
glewInit();
glViewport(0, 0, 500, 500);
glViewport(0, 0, 960, 540);
init(window);

164
grk/cw 6/zadania 3.html Normal file
View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>zadania 3</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<link rel="stylesheet" href="style.css" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="ćwiczenia-3">Ćwiczenia 3</h1>
<h2 id="przestrzenie-potoku-graficznego">Przestrzenie potoku graficznego</h2>
<p>W trakcie wykładu zostały opisane kolejne przestrzenie potoku graficznego. W tej części zajęć przejdziemy kolejne jego etapy.</p>
<p><img src="./img/coordinate_systems.jpg" /></p>
<p>Pierwszy krok, czyli przejście do <code>World Space</code> już wykonujemy za pomocą macierzy transformacji. Następnym krokiem będzie stworzenie macierzy projekcji i macierzy widoku. Zaczniemy od macierzy projekcji. Będziemy modyfikować macierz, którą wysyła funkcja <code>createPerspectiveMatrix</code> (macierz jest transponowana dalej, więc zapisuj ją tak, jak tu widzisz). Zanim zaczniemy domnóż macierz perspektywy do macierzy transformacji obiektów.</p>
<h2 id="macierz-perspektywy">Macierz perspektywy</h2>
<p>Rozważmy mnożenie dowolnej macierzy przez wektor kolumnowy:</p>
<p><span class="math display">\[\begin{bmatrix} m_{11} &amp; m_{12} &amp; m_{13}&amp; m_{14}\\m_{21} &amp; m_{22} &amp; m_{23}&amp; m_{24}\\m_{31} &amp; m_{32} &amp; m_{33}&amp; m_{34}\\m_{41} &amp; m_{42} &amp; m_{43}&amp; m_{44}\\\end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ w \end{bmatrix}=\begin{bmatrix} x*m_{11}+y*m_{12}+z*m_{13}+m_{14}\\x*m_{21} +y*m_{22} +z*m_{23} +m_{24}\\x*m_{31} +y*m_{32} +z*m_{33} +m_{34}\\x*m_{41} +y*m_{42} +z*m_{43} +m_{44}\\\end{bmatrix}\]</span></p>
<p>Pierwszym krokiem jest wykorzystanie homogenizacji do uzyskania efektu perspektywy. W tym celu musimy ustawić współrzędną <span class="math inline">\(w\)</span> na <span class="math inline">\(-z\)</span> za pomocą macierzy. Jeśli przyjrzymy się obliczeniom powyżej. Zobaczymy, że do tego musimy ustawić <span class="math inline">\(m_{43}\)</span> na <span class="math inline">\(-1\)</span> a pozostałe w tym wierszu na <span class="math inline">\(0\)</span>. Przemnożenie daje nam:</p>
<p><span class="math display">\[\begin{bmatrix} 1 &amp; 0 &amp; 0&amp; 0\\0 &amp; 1 &amp; 0&amp; 0\\0 &amp; 0 &amp; 1&amp; 0\\0 &amp; 0 &amp; -1&amp; 0 \end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}=\begin{bmatrix} x \\ y \\ z \\ -z\end{bmatrix}\]</span></p>
<p>Po homogenizacji otrzymamy wektor:</p>
<p><span class="math display">\[\begin{bmatrix} -\frac{x}{z} \\ -\frac{x}{z} \\ -1 \\ 1\end{bmatrix}\]</span></p>
<hr />
<h3 id="zadanie">Zadanie</h3>
<p>zmodyfikuj macierz perspektywy w taki sposób.</p>
<hr />
<p>Wartość współrzędnej <span class="math inline">\(z\)</span> jest równa -1 dla każdego parametru. Co spowoduje, że nie będzie wiadomo, który wierzchołek bliżej, a który dalej i otrzymam zjawisko znane jako z-fighting. By tego uniknąć. Musimy zmapować współrzędną <span class="math inline">\(z\)</span>. Przypomnijmy, że przy arbitralnej macierzy wartość współrzędnej <span class="math inline">\(z\)</span> będzie następującej postaci:</p>
<p><span class="math display">\[ x*m_{31} +y*m_{32} +z*m_{33} +m_{34} \]</span></p>
<p>więc możemy pracować tylko z parametrami <span class="math inline">\(m_{33}\)</span> i <span class="math inline">\(m_{34}\)</span>, czyli <span class="math inline">\(z*m_{33} +m_{34}\)</span>, po uwzględnieniu dodatkowo homogenizacji otrzymamy ostateczny wzór:</p>
<p><span class="math display">\[ z&#39;=-m_{33} -\frac{m_{34}}{z}.\]</span></p>
<p>Przypomnijmy, że w <code>Clipping Space</code> współrzędna <span class="math inline">\(z\)</span> musi się mapować na wartości od <span class="math inline">\(-1\)</span> do <span class="math inline">\(1\)</span>, żeby znalazły się w bryle kanonicznej (obiekty poza bryłą kanoniczną nie będą wyświetlone). Jak na wykładzie określimy sobie parametry <span class="math inline">\(0 &lt; n &lt; f\)</span>, które będą określać pozycję minimalnej i maksymalnej płaszczyzny osi <span class="math inline">\(z\)</span>. Chcemy, żeby dla <span class="math inline">\(z=n\)</span> wartość <span class="math inline">\(z&#39;\)</span> wynosiła <span class="math inline">\(-1\)</span> oraz dla <span class="math inline">\(z=f\)</span> wartość <span class="math inline">\(z&#39;\)</span> wynosiła <span class="math inline">\(1\)</span>, daje nam to układ równań:</p>
<p><span class="math display">\[\begin{matrix} -m_{33}&amp; -&amp;\frac{m_{34}}{n}&amp;=&amp;-1\\-m_{33} &amp;-&amp;\frac{m_{34}}{f}&amp;=&amp;1\end{matrix}\]</span></p>
<p>co po przekształceniu da nam:</p>
<p><span class="math display">\[\begin{matrix} m_{33}&amp;=&amp;\frac{(n + f)}{(n - f)}\\m_{34} &amp;=&amp;\frac{(2 n f)}{(n - f)}\end{matrix}\]</span></p>
<p>Ostatecznie otrzymujemy:</p>
<p><span class="math display">\[\begin{bmatrix} 1 &amp; 0 &amp; 0&amp; 0\\0 &amp; 1 &amp; 0&amp; 0\\0 &amp; 0 &amp; \frac{(n + f)}{(n - f)}&amp; \frac{(2 n f)}{(n - f)}\\0 &amp; 0 &amp; -1&amp; 0 \end{bmatrix}\]</span></p>
<p>Zauważ, że te wartość zmienia się zgodnie ze wzorem <span class="math inline">\(-\left(\frac{(n + f)}{(n - f)}+ \frac{(2 n f)}{z(n - f)}\right)\)</span> czyli zmienia się to asymptotycznie, co można zobaczyć na wykresie.</p>
<p><img src="./img/z_depth_graph.jpg" /></p>
<h3 id="zadanie-1">Zadanie*</h3>
<p>Rozwiąż samodzielnie ten układ równań.</p>
<h3 id="zadanie-2">Zadanie</h3>
<p>Dodaj zmienne lokalne <code>n</code> i <code>f</code> w funkcji, ustal im jakieś arbitralne wartości i dodaj rzutowanie <span class="math inline">\(z\)</span> zgodnie ze wzorem, który otrzymaliśmy. Spróbuj ustawić taką wartość <code>f</code>, żeby tylna ściana sześcianu zniknęła.</p>
<p>Uzyskana macierz daje nam rzutowanie perspektywiczne, ale możemy ją jeszcze rozbudować o zmianę kąta widzenia, a także naprawić problem z nieprawidłowym skalowaniem się ekranu przy zmianie jego proporcji. Obie te czynności sprowadzają się do tego samego, mianowicie chcemy zmienić kształt bryły widzenia w osiach <span class="math inline">\(x\)</span> i <span class="math inline">\(y\)</span>. By tego dokonać, musimy zmienić wartość parametrów <span class="math inline">\(m_{11}\)</span> i <span class="math inline">\(m_{22}\)</span>, to one odpowiadają za skalowanie w tych osiach. Parametry te ściskają lub rozszerzają przestrzeń w tych osiach, więc zmniejszenie wartości zwiększy kąt widzenia w danej osi.</p>
<p>Zacznijmy od kąta widzenia. Można go zmienić zwyczajnie ustawiając zamiast <span class="math inline">\(1\)</span> dowolną inną wartość <span class="math inline">\(S\)</span> parametrów <span class="math inline">\(m_{11}\)</span> i <span class="math inline">\(m_{22}\)</span>. Jednak jeśli chcemy uzyskać faktyczne parametry oparte na polu widzenia, musimy skorzystać ze wzoru:</p>
<p><span class="math display">\[S=\frac{1}{\tan(\frac{fov}{2}*\frac{\pi}{180})}\]</span></p>
<h3 id="zadanie-3">Zadanie</h3>
<p>Dodaj do <code>createPerspectiveMatrix</code> argument fov, który będzie ustalał kąt widzenia.</p>
<h3 id="zadanie-4">Zadanie</h3>
<p>Prawidłowe skalowanie okna uzyskamy poprzez mnożenie <span class="math inline">\(m_{22}\)</span> przez stosunek szerokości do wysokości ekranu. W zadaniu jest zmienna globalna <code>aspectRatio</code>. W funkcji <code>framebuffer_size_callback</code> nadpisz tą zmienną właściwym stosunkiem (pamiętaj, że dzielenie liczb stałoprzecinkowych w c++ nie uwzględnia ułamków). Następnie prześlij ja do <code>createPerspectiveMatrix</code> jako dodatkowy parametr i wykorzystaj przy renderowaniu sceny.</p>
<hr />
<h3 id="zadanie-5">Zadanie*</h3>
<p>Po dodaniu skalowania okna, poszerzanie kwadratowego okna będzie zmniejszać kąt widzenia na osi pionowej. Natomiast wydłużanie go będzie go zwiększać. Zaproponuj rozwiązanie, które sprawi, że poszerzanie kwadratowego okna będzie zwiększać kąt widzenia w osi poziomej i jednocześnie wydłużanie kwadratowego okna będzie zwiększać kąt widzenia w osi pionowej.</p>
<h2 id="macierz-widoku">Macierz widoku</h2>
<p>Celem macierzy widoku jest wprowadzenie pojęcia kamery, jako obiektu, który możemy ustawić i poruszać nim w przestrzeni. Na taką macierz składa się pozycja kamery kierunek patrzenia oraz jej orientacja: wektory <code>cameraDir</code> oraz <code>cameraUp</code> i <code>cameraSide</code>.  W tym celu potrzebujemy jeden wektor, który będzie określał pozycję początku układu współrzędnych (czyli pozycję kamery). Oraz 3 wektory ortonormalne, które będą rozpinać przestrzeń (odpowiedzialne za kierunek i orientację). Ponieważ te wektory są ortogonalne, możemy je rekonstruować za pomocą dwóch wektorów, jeden będzie nam wskazywać kierunek patrzenia (<code>cameraDir</code>), drugi górę (<code>cameraUp</code>).</p>
<p><img src="./img/camera.jpg" /></p>
<blockquote>
<p>Układ współrzędnych kamery</p>
</blockquote>
<p>W kodzie jest zaimplementowana obsługa klawiatury, klawisze <strong>W</strong> i <strong>S</strong> przesuwają kamerę do przodu i do tyłu, natomiast <strong>A</strong> i <strong>D</strong> obracają ją na boki. Robią to poprzez modyfikacje zmiennych globalnych <code>cameraDir</code> i <code>cameraPos</code>, jednak, żeby kamera faktycznie działała, trzeba uzupełnić funkcję <code>createCameraMatrix</code> i dodać jej wynik do transformacji obiektów.</p>
<h3 id="zadanie-6">Zadanie</h3>
<p>Uzupełnij funkcję <code>createCameraMatrix</code>. Najpierw oblicz wektor skierowany w bok za pomocą iloczynu wektorowego między <code>cameraDir</code> a wektorem <span class="math inline">\([0,1,0]\)</span>. Wektor może być długości innej niż 1, dlatego znormalizuj go. Zapisz wynik do <code>cameraSide</code>. Podobnie oblicz <code>cameraUp</code> jako znormalizowany iloczyn wektorowy między <code>cameraSide</code> i <code>cameraDir</code>.</p>
<blockquote>
<p>Wektor normalizuje się za pomocą funkcji: <code>glm::normalize</code></p>
</blockquote>
<p>Macierz kamery złożona jest z iloczynu macierzy obrotu i macierzy translacji. By otrzymać pierwszą z nich, korzystamy z ortonormalności bazy, dzięki temu wystarczy zapisać wektory <code>cameraSide</code>, <code>cameraUp</code> i <code>-cameraDir</code> wierszami. &gt;Zauważ, że <code>cameraDir</code> musi być odwrócony tak jak na obrazku, ma być zwrócony do kamery, nie od niej. Macierz wygląda następująco:</p>
<p><span class="math display">\[M_{VR}=\begin{bmatrix} cameraSide_x &amp; cameraSide_y &amp; cameraSide_z &amp; 0\\cameraUp_x &amp; cameraUp_y &amp; cameraUp_z &amp; 0\\-cameraDir_x &amp; -cameraDir_y &amp; -cameraDir_z &amp; 0\\0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}\]</span></p>
<p>Macierz translacji <span class="math inline">\(M_{VT}\)</span> otrzymujemy przez translacje o <code>-cameraPos</code>. Ostatecznie macierz widoku jest postaci <span class="math display">\[M_V=M_{VR}*M_{VT}\]</span></p>
<p>W macierzy <code>transformation</code> umieść pomnożone przez siebie macierze perspektywy (wynik funkcji <code>createPerspectiveMatrix</code>) i kamery (wynik funkcji <code>createCameraMatrix</code>) w odpowiedniej kolejności. Jako efektem otrzymamy pełen potok graficzny, czyli kamerę, którą możemy poruszać klawiszami, z poprawnym rzutowaniem perspektywicznym.</p>
<h3 id="zadanie-7">Zadanie</h3>
<p>Wyświetl dwa dodatkowe prostopadłościany w różnych pozycjach i orientacjach.</p>
<h3 id="zadanie-8">Zadanie*</h3>
<p>Zmodyfikuj ustawienia tak, żeby kamera zawsze była zwrócona w punkt wybrany punkt <span class="math inline">\(p\)</span> <span class="math inline">\((0,0,0)\)</span>. W funkcji <code>processInput</code> zakomentuj obsługę klawiszy <strong>A</strong> i <strong>D</strong>. Zamiast tego na końcu tej funkcji ustaw <code>cameraDir</code> jako znormalizowana różnicę między punktem <span class="math inline">\(p\)</span> a <code>cameraPos</code>. Jako obsługę klawiszy <strong>R</strong> i <strong>F</strong> dodaj przesuwanie kamery w górę i w dół.</p>
<h1 id="ładowanie-modeli-z-użyciem-assimp">Ładowanie modeli z użyciem assimp**</h1>
<p>W tym zadaniu przećwiczymy ładowanie modeli z plików, wykorzystamy do tego bibliotekę assimp (The Open Asset Import Library ), która zapewnia wspólny interfejs dla różnych typów plików.</p>
<p>Funkcja <code>loadModelToContext</code> pobiera ścieżkę do pliku z modelem i wczytuje go przy użyciu importera assimp.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="at">const</span> aiScene* scene = <span class="kw">import</span>.ReadFile(path, aiProcess_TriangulateaiProcess_Triangulate | aiProcess_CalcTangentSpace);</span></code></pre></div>
<p>Importer przyjmuje ścieżkę i flagi preprocesingu, które mówią, jakie operacje ma wykonać importer przed przekazaniem nam pliku. W naszym przypadku dokonuje triangularyzacji (zamienia wszystkie wielokąty na trójkąty) i oblicza przestrzeń styczną (o której będzie mowa później).</p>
<blockquote>
<p>Wywołaj funkcję dla ścieżki do statku <strong>./models/spaceship.obj</strong> i zmiennej globalnej <code>Core::RenderContext sphereContext</code>. Dodaj breakpoint po załadowaniu sceny i obejrzyj jak wygląda struktura załadowanego obiektu.</p>
</blockquote>
<p>Załadowany obiekt posiada szereg pól jak na przykład tekstury, oświetlenia, materiały, węzły (<em>Node</em>) czy modele. Węzły odpowiadają za hierarchię elementów w modelu, co ułatwia jego animację, wykorzystamy to w późniejszych zajęciach. Nasze pliki składają się z tylko jednego modelu, dlatego nie musimy się na tym skupiać i wywołujemy tylko pierwszy model, do którego odwołujemy się za pomocą <code>scene-&gt;mMeshes[0]</code>. Wywołaj <code>context.initFromAiMesh</code> z nim jako argumentem.</p>
<h3 id="zadanie-9">Zadanie**</h3>
<p>Jeśli tego nie zrobiłeś wywołaj metodę <code>context.initFromAiMesh</code> z argumentem<code>scene-&gt;mMeshes[0]</code> w funkcji <code>init</code>, po wczytaniu modelu. Metoda nie jest kompletna, uzupełnij ją o ładowanie indeksów, wierzchołków, normalnych i współrzędnych tekstur do bufora. Współrzędne tekstur i indeksy zostały przekonwertowane do odpowiedniego formatu i znajdują się w zmiennych <code>std::vector&lt;aiVector2D&gt; textureCoord</code> i <code>std::vector&lt;unsigned int&gt; indices</code> odpowiednio. Pozostałe są dostępne jako atrybuty <code>aiMesh</code>, mianowicie <code>mesh-&gt;mVertices</code> zawiera wierzchołki a <code>mesh-&gt;mNormals</code> normalne.</p>
<p>Dodatkowo <code>mesh-&gt;mNumVertices</code> zawiera liczbę wierzchołków.</p>
<p>zawierają rozmiary buforów.</p>
<p>Utwórz jedną duża tablicę/vector, która zawiera informacje o wierzchołkach, normalnych i współrzędnych tekstur. Powinna mieć ona format jak na poniższym obrazku:</p>
<p><img src="https://i.imgur.com/WLAQtGH.jpg" /></p>
<p>Gdy załadujesz kontekst, wykorzystaj w <code>renderScene</code> funkcję <code>Core::DrawContext(Core::RenderContext&amp; context)</code> do narysowania obiektów. Rozmieść statek i kulę w przestrzeni za pomocą macierzy transformacji i obrotu.</p>
</body>
</html>

162
grk/cw 6/zadania 3.md Normal file
View File

@ -0,0 +1,162 @@
# Ćwiczenia 3
## Przestrzenie potoku graficznego
W trakcie wykładu zostały opisane kolejne przestrzenie potoku graficznego.
W tej części zajęć przejdziemy kolejne jego etapy.
![](./img/coordinate_systems.jpg)
Pierwszy krok, czyli przejście do `World Space` już wykonujemy za pomocą macierzy transformacji. Następnym krokiem będzie stworzenie macierzy projekcji i macierzy widoku. Zaczniemy od macierzy projekcji. Będziemy modyfikować macierz, którą wysyła funkcja `createPerspectiveMatrix` (macierz jest transponowana dalej, więc zapisuj ją tak, jak tu widzisz). Zanim zaczniemy domnóż macierz perspektywy do macierzy transformacji obiektów.
**Nim przejdziemy dalej odkomentuj rysowanie prostopadłościanu.**
## Macierz perspektywy
Rozważmy mnożenie dowolnej macierzy przez wektor kolumnowy:
$$\begin{bmatrix} m_{11} & m_{12} & m_{13}& m_{14}\\m_{21} & m_{22} & m_{23}& m_{24}\\m_{31} & m_{32} & m_{33}& m_{34}\\m_{41} & m_{42} & m_{43}& m_{44}\\\end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ w \end{bmatrix}=\begin{bmatrix} x*m_{11}+y*m_{12}+z*m_{13}+m_{14}\\x*m_{21} +y*m_{22} +z*m_{23} +m_{24}\\x*m_{31} +y*m_{32} +z*m_{33} +m_{34}\\x*m_{41} +y*m_{42} +z*m_{43} +m_{44}\\\end{bmatrix}$$
Pierwszym krokiem jest wykorzystanie homogenizacji do uzyskania efektu perspektywy. W tym celu musimy ustawić współrzędną $w$ na $-z$ za pomocą macierzy. Jeśli przyjrzymy się obliczeniom powyżej. Zobaczymy, że do tego musimy ustawić $m_{43}$ na $-1$ a pozostałe w tym wierszu na $0$. Przemnożenie daje nam:
$$\begin{bmatrix} 1 & 0 & 0& 0\\0 & 1 & 0& 0\\0 & 0 & 1& 0\\0 & 0 & -1& 0 \end{bmatrix}\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}=\begin{bmatrix} x \\ y \\ z \\ -z\end{bmatrix}$$
Po homogenizacji otrzymamy wektor:
$$\begin{bmatrix} -\frac{x}{z} \\ -\frac{x}{z} \\ -1 \\ 1\end{bmatrix}$$
----
### Zadanie
zmodyfikuj macierz perspektywy w taki sposób.
----
Wartość współrzędnej $z$ jest równa -1 dla każdego parametru. Co spowoduje, że nie będzie wiadomo, który wierzchołek bliżej, a który dalej i otrzymam zjawisko znane jako z-fighting. By tego uniknąć. Musimy zmapować współrzędną $z$.
Przypomnijmy, że przy arbitralnej macierzy wartość współrzędnej $z$ będzie następującej postaci:
$$ x*m_{31} +y*m_{32} +z*m_{33} +m_{34} $$
więc możemy pracować tylko z parametrami $m_{33}$ i $m_{34}$, czyli $z*m_{33} +m_{34}$, po uwzględnieniu dodatkowo homogenizacji otrzymamy ostateczny wzór:
$$ z'=-m_{33} -\frac{m_{34}}{z}.$$
Przypomnijmy, że w `Clipping Space` współrzędna $z$ musi się mapować na wartości od $-1$ do $1$, żeby znalazły się w bryle kanonicznej (obiekty poza bryłą kanoniczną nie będą wyświetlone). Jak na wykładzie określimy sobie parametry $0 < n < f$, które będą określać pozycję minimalnej i maksymalnej płaszczyzny osi $z$. Chcemy, żeby dla $z=n$ wartość $z'$ wynosiła $-1$ oraz dla $z=f$ wartość $z'$ wynosiła $1$, daje nam to układ równań:
$$\begin{matrix} -m_{33}& -&\frac{m_{34}}{n}&=&-1\\-m_{33} &-&\frac{m_{34}}{f}&=&1\end{matrix}$$
co po przekształceniu da nam:
$$\begin{matrix} m_{33}&=&\frac{(n + f)}{(n - f)}\\m_{34} &=&\frac{(2 n f)}{(n - f)}\end{matrix}$$
Ostatecznie otrzymujemy:
$$\begin{bmatrix} 1 & 0 & 0& 0\\0 & 1 & 0& 0\\0 & 0 & \frac{(n + f)}{(n - f)}& \frac{(2 n f)}{(n - f)}\\0 & 0 & -1& 0 \end{bmatrix}$$
Zauważ, że te wartość zmienia się zgodnie ze wzorem $-\left(\frac{(n + f)}{(n - f)}+ \frac{(2 n f)}{z(n - f)}\right)$ czyli zmienia się to asymptotycznie, co można zobaczyć na wykresie.
![](./img/z_depth_graph.jpg)
### Zadanie*
Rozwiąż samodzielnie ten układ równań.
### Zadanie
Dodaj zmienne lokalne `n` i `f` w funkcji, ustal im jakieś arbitralne wartości i dodaj rzutowanie $z$ zgodnie ze wzorem, który otrzymaliśmy. Spróbuj ustawić taką wartość `f`, żeby tylna ściana sześcianu zniknęła.
Uzyskana macierz daje nam rzutowanie perspektywiczne, ale możemy ją jeszcze rozbudować o zmianę kąta widzenia, a także naprawić problem z nieprawidłowym skalowaniem się ekranu przy zmianie jego proporcji. Obie te czynności sprowadzają się do tego samego, mianowicie chcemy zmienić kształt bryły widzenia w osiach $x$ i $y$. By tego dokonać, musimy zmienić wartość parametrów $m_{11}$ i $m_{22}$, to one odpowiadają za skalowanie w tych osiach. Parametry te ściskają lub rozszerzają przestrzeń w tych osiach, więc zmniejszenie wartości zwiększy kąt widzenia w danej osi.
Zacznijmy od kąta widzenia. Można go zmienić zwyczajnie ustawiając zamiast $1$ dowolną inną wartość $S$ parametrów $m_{11}$ i $m_{22}$. Jednak jeśli chcemy uzyskać faktyczne parametry oparte na polu widzenia, musimy skorzystać ze wzoru:
$$S=\frac{1}{\tan(\frac{fov}{2}*\frac{\pi}{180})}$$
### Zadanie
Dodaj do `createPerspectiveMatrix` argument fov, który będzie ustalał kąt widzenia.
### Zadanie
Prawidłowe skalowanie okna uzyskamy poprzez mnożenie $m_{22}$ przez stosunek szerokości do wysokości ekranu. W zadaniu jest zmienna globalna `aspectRatio`. W funkcji `framebuffer_size_callback` nadpisz tą zmienną właściwym stosunkiem (pamiętaj, że dzielenie liczb stałoprzecinkowych w c++ nie uwzględnia ułamków). Następnie prześlij ja do `createPerspectiveMatrix` jako dodatkowy parametr i wykorzystaj przy renderowaniu sceny.
----
### Zadanie*
Po dodaniu skalowania okna, poszerzanie kwadratowego okna będzie zmniejszać kąt widzenia na osi pionowej. Natomiast wydłużanie go będzie go zwiększać. Zaproponuj rozwiązanie, które sprawi, że poszerzanie kwadratowego okna będzie zwiększać kąt widzenia w osi poziomej i jednocześnie wydłużanie kwadratowego okna będzie zwiększać kąt widzenia w osi pionowej.
## Macierz widoku
Celem macierzy widoku jest wprowadzenie pojęcia kamery, jako obiektu, który możemy ustawić i poruszać nim w przestrzeni. Na taką macierz składa się pozycja kamery kierunek patrzenia oraz jej orientacja: wektory `cameraDir` oraz `cameraUp` i `cameraSide`.  W tym celu potrzebujemy jeden wektor, który będzie określał pozycję początku układu współrzędnych (czyli pozycję kamery). Oraz 3 wektory ortonormalne, które będą rozpinać przestrzeń (odpowiedzialne za kierunek i orientację). Ponieważ te wektory są ortogonalne, możemy je rekonstruować za pomocą dwóch wektorów, jeden będzie nam wskazywać kierunek patrzenia (`cameraDir`), drugi górę (`cameraUp`).
![](./img/camera.jpg)
> Układ współrzędnych kamery
W kodzie jest zaimplementowana obsługa klawiatury, klawisze **W** i **S** przesuwają kamerę do przodu i do tyłu, natomiast **A** i **D** obracają ją na boki. Robią to poprzez modyfikacje zmiennych globalnych `cameraDir` i `cameraPos`, jednak, żeby kamera faktycznie działała, trzeba uzupełnić funkcję `createCameraMatrix` i dodać jej wynik do transformacji obiektów.
### Zadanie
Uzupełnij funkcję `createCameraMatrix`. Najpierw oblicz wektor skierowany w bok za pomocą iloczynu wektorowego między `cameraDir` a wektorem $[0,1,0]$. Wektor może być długości innej niż 1, dlatego znormalizuj go. Zapisz wynik do `cameraSide`. Podobnie oblicz `cameraUp` jako znormalizowany iloczyn wektorowy między `cameraSide` i `cameraDir`.
> Wektor normalizuje się za pomocą funkcji: `glm::normalize`
Macierz kamery złożona jest z iloczynu macierzy obrotu i macierzy translacji. By otrzymać pierwszą z nich, korzystamy z ortonormalności bazy, dzięki temu wystarczy zapisać wektory `cameraSide`, `cameraUp` i `-cameraDir` wierszami.
>Zauważ, że `cameraDir` musi być odwrócony tak jak na obrazku, ma być zwrócony do kamery, nie od niej. Macierz wygląda następująco:
$$M_{VR}=\begin{bmatrix} cameraSide_x & cameraSide_y & cameraSide_z & 0\\cameraUp_x & cameraUp_y & cameraUp_z & 0\\-cameraDir_x & -cameraDir_y & -cameraDir_z & 0\\0 & 0 & 0 & 1 \end{bmatrix}$$
Macierz translacji $M_{VT}$ otrzymujemy przez translacje o `-cameraPos`. Ostatecznie macierz widoku jest postaci
$$M_V=M_{VR}*M_{VT}$$
W macierzy `transformation` umieść pomnożone przez siebie macierze perspektywy (wynik funkcji `createPerspectiveMatrix`) i kamery (wynik funkcji `createCameraMatrix`) w odpowiedniej kolejności. Jako efektem otrzymamy pełen potok graficzny, czyli kamerę, którą możemy poruszać klawiszami, z poprawnym rzutowaniem perspektywicznym.
### Zadanie
Wyświetl dwa dodatkowe prostopadłościany w różnych pozycjach i orientacjach.
### Zadanie*
Zmodyfikuj ustawienia tak, żeby kamera zawsze była zwrócona w punkt wybrany punkt $p$ $(0,0,0)$. W funkcji `processInput` zakomentuj obsługę klawiszy **A** i **D**. Zamiast tego na końcu tej funkcji ustaw `cameraDir` jako znormalizowana różnicę między punktem $p$ a `cameraPos`. Jako obsługę klawiszy **R** i **F** dodaj przesuwanie kamery w górę i w dół.
# Ładowanie modeli z użyciem assimp**
W tym zadaniu przećwiczymy ładowanie modeli z plików, wykorzystamy do tego bibliotekę assimp (The Open Asset Import Library ), która zapewnia wspólny interfejs dla różnych typów plików.
Funkcja `loadModelToContext` pobiera ścieżkę do pliku z modelem i wczytuje go przy użyciu importera assimp.
```c++
const aiScene* scene = import.ReadFile(path, aiProcess_TriangulateaiProcess_Triangulate | aiProcess_CalcTangentSpace);
```
Importer przyjmuje ścieżkę i flagi preprocesingu, które mówią, jakie operacje ma wykonać importer przed przekazaniem nam pliku. W naszym przypadku dokonuje triangularyzacji (zamienia wszystkie wielokąty na trójkąty) i oblicza przestrzeń styczną (o której będzie mowa później).
> Wywołaj funkcję dla ścieżki do statku **./models/spaceship.obj** i zmiennej globalnej `Core::RenderContext sphereContext`. Dodaj breakpoint po załadowaniu sceny i obejrzyj jak wygląda struktura załadowanego obiektu.
Załadowany obiekt posiada szereg pól jak na przykład tekstury, oświetlenia, materiały, węzły (*Node*) czy modele. Węzły odpowiadają za hierarchię elementów w modelu, co ułatwia jego animację, wykorzystamy to w późniejszych zajęciach. Nasze pliki składają się z tylko jednego modelu, dlatego nie musimy się na tym skupiać i wywołujemy tylko pierwszy model, do którego odwołujemy się za pomocą `scene->mMeshes[0]`. Wywołaj `context.initFromAiMesh` z nim jako argumentem.
### Zadanie**
Jeśli tego nie zrobiłeś wywołaj metodę `context.initFromAiMesh` z argumentem`scene->mMeshes[0]` w funkcji `init`, po wczytaniu modelu. Metoda nie jest kompletna, uzupełnij ją o ładowanie indeksów, wierzchołków, normalnych i współrzędnych tekstur do bufora. Współrzędne tekstur i indeksy zostały przekonwertowane do odpowiedniego formatu i znajdują się w zmiennych `std::vector<aiVector2D> textureCoord` i ` std::vector<unsigned int> indices` odpowiednio. Pozostałe są dostępne jako atrybuty `aiMesh`, mianowicie `mesh->mVertices` zawiera wierzchołki a `mesh->mNormals` normalne.
Dodatkowo `mesh->mNumVertices` zawiera liczbę wierzchołków.
zawierają rozmiary buforów.
Utwórz jedną duża tablicę/vector, która zawiera informacje o wierzchołkach, normalnych i współrzędnych tekstur. Powinna mieć ona format jak na poniższym obrazku:
![](https://i.imgur.com/WLAQtGH.jpg)
Gdy załadujesz kontekst, wykorzystaj w `renderScene` funkcję `Core::DrawContext(Core::RenderContext& context)` do narysowania obiektów. Rozmieść statek i kulę w przestrzeni za pomocą macierzy transformacji i obrotu.

116
grk/cw 6/zadania 5.html Normal file
View File

@ -0,0 +1,116 @@
<!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 5</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;}
</style>
<link rel="stylesheet" href="style.css" />
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h2 id="oświetlenie-phonga">Oświetlenie Phonga</h2>
<p>W trakcie tych zajęć zajmiemy się implementacją modelu oświetlenia Phonga. Na poprzednich zajęciach zbudowaliśmy układ słoneczny. Wykorzystamy go w trakcie tych zajęć. Jeżeli go zrobiłeś, to przekopiuj do <code>ex_5_1.hpp</code> kod z poprzednich zajęć. W przeciwnym wypadku wykorzystaj ten, który jest zaimplementowany w <code>ex_5_1.hpp</code>. W zadaniu będzie nam potrzebny statek latający przed kamerą, jak nie ma tego w Twojej scenie to skopiuj to z <code>ex_5_1.hpp</code>.</p>
<h2 id="zadanie---diffuse">Zadanie - <em>diffuse</em></h2>
<p>Oblicz we fragment shaderze oświetlenie obiektu przy użyciu modelu Phonga dla odbicia rozproszonego (*diffuse)</p>
<p> 1. Przekaż źródło światła. Na razie przyjmiemy kierunkowy model oświetlenia, dlatego źródło będzie opisane jako wektor kierunkowy:</p>
<ul>
<li><p>Prześlij do shadera fragmentów zmienna typu <code>uniform vec3</code> (nazwij ją np. <code>lightDir</code>), w której będzie się znajdować wektor kierunkowy.</p></li>
<li><p>Należy to zrobić podobnie do tego, jak przesyłany jest kolor.</p></li>
<li><p>Jako kierunek światła wybierz dowolny wektor jednostkowy. (Możesz wziąć dowolny niezerowy wektor następnie go znormalizować).</p></li>
<li><p>Dodatkowo prześlij drugą zmienną <code>uniform vec3 lightColor</code>, w której umieścimy kolor światła. Prześlij tam wartości ze zmiennej <code>glm::vec3 lightColor</code>.</p></li>
</ul>
<ol start="2" type="1">
<li>Oblicz natężenie w shaderze fragmentów:</li>
</ol>
<ul>
<li><p>prześlij normalne z shadera fragmentów do shadera wierzchołków</p></li>
<li><p>znormalizuj wektor normalny przed użyciem go w obliczeniach (uśrednianie wektorów normalnych wierzchołków może spowodować, że przestaje one być jednostkowe).</p></li>
<li><p>Natężenie to iloczyn skalarny wektora normalnego powierzchni i odwrotnego wektora kierunku padania światła. Skorzystaj z funkcji <code>dot</code>.</p></li>
<li><p>Natężenie nie może być ujemne. Przytnij natężenie do zera przy użyciu: <code>x = max(x, 0.0)</code></p></li>
</ul>
<ol start="3" type="1">
<li>Zastosuj obliczone natężenie, aby zmodyfikować kolor obiektu:</li>
</ol>
<ul>
<li>Przemnóż kolor RGB fragmentu przez obliczone natężenie i przez kolor światła z <code>lightColor</code>.</li>
</ul>
<h2 id="zadanie---obsługa-obrotów">Zadanie - obsługa obrotów</h2>
<p>Dlaczego oświetlenie statku nie zmienia się podczas jego obracania?</p>
<p>(Wektory normalne są w układzie lokalnym modelu, a wektor padania światła w układzie świata)</p>
<p>Należy wykonać transformacje wektorów normalnych do przestrzeni świata: - Prześlij macierz modelu rysowanego obiektu (<em>model Matrix</em>) jako osobna zmienna do vertex shadera (<code>uniform mat4</code>).<br />
- Przemnóż przez te macierz wektor normalny wierzchołka przed przesłaniem go do shadera fragmentów. - Współrzędna <strong>w</strong> dopisana do wektora przed mnożeniem przez macierz powinna być ustawiona na 0. Wynika to z tego, że w przypadku transformacji wektorów reprezentujących kierunki w przestrzeni, nie chcemy dokonywać translacji — np. wektor normalny do powierzchni zależy od orientacji obiektu, ale nie od jego pozycji (przesunięcia) w przestrzeni świata.</p>
<h2 id="zadanie---specular">Zadanie - <em>specular</em></h2>
<p>Uzupełnił model o czynnik odbicia zwierciadlanego (<em>specular</em>). W tym celu:</p>
<ol type="1">
<li>Potrzebny będzie wektor od rysowanego fragmentu do pozycji kamery:</li>
</ol>
<ul>
<li>Wyślij pozycje kamery (<code>cameraPos</code>) jako kolejna zmienna do fragment shadera.<br />
</li>
<li>Podobnie jak wektory normalne prześlij z vertex do fragment shadera pozycje wierzchołków (<code>vertexPosition</code>) w przestrzeni świata (czyli pomnożone przez macierz <strong>modelMatrix</strong>). Pamiętaj, że tym razem wektory reprezentują punkty, a nie kierunki - współrzędna <strong>w</strong> przed mnożeniem musi być ustawiona na 1. W wyniku rasteryzacji otrzymamy w shaderze fragmentu jego pozycję (nazywaną pozycją fragmentu)</li>
<li>Oblicz wektor <strong>V</strong> (<em>view direction</em>) jako znormalizowaną różnice pozycji kamery i pozycji fragmentu.</li>
</ul>
<ol start="2" type="1">
<li>Oblicz natężenie światła odbitego we <em>fragment shaderze</em>:</li>
</ol>
<ul>
<li>Oblicz wektor kierunku odbicia światła <strong>R</strong> przy użyciu funkcji <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/reflect.xhtml"><code>reflect</code></a>. Pamiętaj, żeby przesłać do funkcji odwrócony wektor kierunku światła.</li>
<li>Oblicz natężenie: iloczyn skalarny <strong>V</strong> i <strong>R</strong>, przycięty do zera ( <code>max(...,0.0)</code> ), a następnie podniesiony do wysokiej potęgi (np. 8, 50, 1000), która jest miara połyskliwości powierzchni.</li>
</ul>
<ol start="3" type="1">
<li>Ustal ostateczny kolor piksela na <code>objectColor * diffuse + lightColor * specular</code>. Oznacza to najprostszy przypadek, gdy kolor światła odbitego jest biały.</li>
</ol>
<h2 id="zadanie---oświetlenie-punktowe">Zadanie - oświetlenie punktowe</h2>
<p>W układzie planetarnym obiektem oświetlającym powinno być słońce, dlatego zamień oświetlenie kierunkowe na punktowe:</p>
<ul>
<li>Zamiast przesyłać (w <code>lightDir</code>) kierunek światła, prześlij pozycję słońca do fragment shadera (taką jak ustawiłeś w punkcie powyżej) jako uniform vec3 (nazwij go <code>lightPos</code>).</li>
<li>Oblicz kierunek światła odejmując od pozycji światła pozycję fragmentu, znormalizuj wynik. Zapisz wynik w zmiennej <code>lightDir</code>.<br />
</li>
<li>Słońce będzie czarne, nie martw się tym, tylko spójrz na punkt następny.</li>
</ul>
<h2 id="zadanie---shader-słońca">Zadanie - shader słońca</h2>
<p>Źródło światła znajduje się wewnątrz kuli, która reprezentuje słońce, dlatego jest czarna. By to naprawić, utwórz osobny shader, który będzie odpowiadać za renderowanie słońca.</p>
<p>Celem tego zadania jest stworzenie shadera (<strong>shader_5_sun.vert</strong>_ i <strong>shader_5_sun.frag</strong>), który będzie odpowiadał wyłącznie za rysowanie słońca. Poprzednie shadery (<strong>shader_4_1.vert</strong>_ i <strong>shader_5_1.frag</strong>) nadal mają rysować pozostałe obiekty. a) zainicjalizuj <em>program</em> (shadery): - Pliki <strong>shader_5_sun.vert</strong> i <strong>shader_5_sun.frag</strong> są identyczne z 5_1** przed zmianami, będą punktem wyjścia dla <em>shadera</em> słońca.</p>
<ol type="1">
<li><p>Utwórz zmienną globalną <code>GLuint programSun</code> na adres shadera słońca. Stwórz <em>program</em> za pomocą <code>shaderLoader.CreateProgram</code> analogicznie jak tworzy się <code>program</code> z <strong>shader_5_1.vert</strong> i <strong>shader_5_1.frag</strong> (parametry wejściowe to ścieżka do shadera wierzchołków i fragmentów <strong>shader_5_sun.vert</strong> i <strong>shader_5_sun.frag</strong>).</p></li>
<li><p>W skomplikowanym projekcie różne typy obiektów rysuje się przy użyciu różnych shaderów, zate potrzebna jest w programie architektura, która na to pozwala. Ustaw odpowiedni <em>program</em> (shadery) do rysowania słońca:</p></li>
</ol>
<ul>
<li>funkcja <code>drawObject</code> korzysta z globalnej zmiennej <code>program</code>, żeby wskazywać shadery do rysowania. Dodaj argument do funkcji, który będziesz przekazywać adres <em>programu</em>, który ma być wykorzystany do rysowania.</li>
<li>dodaj odpowiedni <em>program</em> w wywołaniach <code>drawObject</code>.</li>
</ul>
<h2 id="zadanie---osłabienie-światła-attenuation"> Zadanie - Zmień shader słońca na bardziej realistyczny </h2>
<p>Na poniższym obrazku jest zdjęcie słońca. Jest ono ciemniejsze na brzegach spróbuj uzyskać podobny efekt. Przydadzą się wektory normalnych i wektor <strong>V</strong> jak i funkcja mix.</p>
<p><img src="./img/sun.png" /></p>
<h2 id="osłabienie-światła-tone-mapping">Osłabienie światła, tone mapping</h2>
<h3 id="zadanie---osłabienie-światła-attenuation">Zadanie - Osłabienie światła (attenuation)</h3>
<p>Światło pochodzące z punktowego źródła traci na sile wraz z dystansem. Wynika to z tego, że rozprasza się na większą powierzchnię. Dodaj ten efekt do shadera. Zamiast brać kolor światła bezpośrednio, podziel go przez kwadrat dystansu od źródła świata. Przed kwadratowaniem przemnoz diystans przez 10.0.</p>
<h4 id="tone-mapping">Tone mapping</h4>
<p>Przez obecną zmianę scena stała się ciemna. Wymaga to od nas zmiany koloru światła na wartości dużo większe niż do tej pory. Jeśli teraz to zrobimy i przesadzimy w drugą stronę, otrzymamy efekt prześwietlenia. Wynika to z ograniczenia zakresu kolorów do <span class="math inline">\([0,1]\)</span> (obsługą wyższych wartości nazywamy HDR). Rozwiązaniem jest pracowanie na wartościach powyżej 1 wykorzystanie <em>tone mappingu</em> do przeniesienia ich w zakres <span class="math inline">\([0,1]\)</span>. Istnieje wiele wzorów, które są wykorzystywane do tego, jeden z nich to:</p>
<p><span class="math display">\[C_{mapped} = 1-e^{-C * E},\]</span> gdzie C to kolor sceny a E to parametr ekspozycji (z zakresu <span class="math inline">\((0,\infty)\)</span>, który może być dostosowany w zależności od jasności.
<h3 id="zadanie">Zadanie - Tone mapping</h3>
Zwiększ siłę słońca przynajmniej stukrotnie. Zaimplementuj powyższą metodę tone mappingu i dodaj możliwość sterowania ekspozycją za pomocą klawiszy 1 i 2.</p>
<h3 id="zadanie">Zadanie*</h3>
<p>Dodaj drugie źródło oświetlenia w postaci reflektora statku. Reflektor świeci tylko w określonym stożku,dlatego oprócz pozycji <code>spotPos</code> posiada również kierunek <code>spotDir</code> i kąt świecenia <span class="math inline">\(\phi\)</span>. Po obliczeniu dla niego <code>lightDir</code> należy sprawdzić, czy iloczyn skalarny pomiędzy <code>lightDir</code> a <code>spodDir</code> jest większy niż <span class="math inline">\(\cos\phi\)</span> . Jeżeli nie jest, to stożek nie świeci w tym miejscu. Można ułatwić sobie implementację wielu źródeł światła poprzez przeniesienie obliczeń oświetlenia do funkcji, która przyjmuje kierunek światła i siłę naświetlenie.</p>
Zwróć uwagę, że SpotDir to co innego niż light Dir w poprzednich zadaniach.
<p><img src="./img/spotlight.png" /> </p>
</body>
</html>

View File

@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.852
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grk-cw1", "cw 1\grk-cw1.vcxproj", "{1B448102-E76C-4347-BDC7-40D02A567DB6}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grk-cw6", "cw 6\grk-cw6.vcxproj", "{3952C396-B1C6-44CD-96DD-C1AC15D32978}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -11,10 +11,10 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1B448102-E76C-4347-BDC7-40D02A567DB6}.Debug|x86.ActiveCfg = Debug|Win32
{1B448102-E76C-4347-BDC7-40D02A567DB6}.Debug|x86.Build.0 = Debug|Win32
{1B448102-E76C-4347-BDC7-40D02A567DB6}.Release|x86.ActiveCfg = Release|Win32
{1B448102-E76C-4347-BDC7-40D02A567DB6}.Release|x86.Build.0 = Release|Win32
{3952C396-B1C6-44CD-96DD-C1AC15D32978}.Debug|x86.ActiveCfg = Debug|Win32
{3952C396-B1C6-44CD-96DD-C1AC15D32978}.Debug|x86.Build.0 = Debug|Win32
{3952C396-B1C6-44CD-96DD-C1AC15D32978}.Release|x86.ActiveCfg = Release|Win32
{3952C396-B1C6-44CD-96DD-C1AC15D32978}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE