diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..15fa89e --- /dev/null +++ b/.gitignore @@ -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 diff --git a/grk/Debug/Planeta.exe b/grk/Debug/Planeta.exe new file mode 100644 index 0000000..91cb7d0 Binary files /dev/null and b/grk/Debug/Planeta.exe differ diff --git a/grk/Debug/Planeta.pdb b/grk/Debug/Planeta.pdb new file mode 100644 index 0000000..bdb7c38 Binary files /dev/null and b/grk/Debug/Planeta.pdb differ diff --git a/grk/UpgradeLog.htm b/grk/UpgradeLog.htm new file mode 100644 index 0000000..73e0d14 --- /dev/null +++ b/grk/UpgradeLog.htm @@ -0,0 +1,273 @@ + + + + Migration Report +

+ Migration Report -

Overview

ProjectPathErrorsWarningsMessages
grk-cw1cw 1\grk-cw1.vcxproj100
Solutiongrk-cw.sln001

Solution and projects

grk-cw1

Message
cw 1\grk-cw1.vcxproj: + The application which this project type is based on was not found. Please try this link for further information: 8bc9ceb8-8b4a-11d0-8d11-00a0c91bc942

Solution

Message
+ Show 1 additional messages +
grk-cw.sln: + The solution file does not require migration.
+ Hide 1 additional messages +
\ No newline at end of file diff --git a/grk/cw 6/Debug/Box.obj b/grk/cw 6/Debug/Box.obj index f3f7c75..1acbcf7 100644 Binary files a/grk/cw 6/Debug/Box.obj and b/grk/cw 6/Debug/Box.obj differ diff --git a/grk/cw 6/Debug/Camera.obj b/grk/cw 6/Debug/Camera.obj index 66bd87a..e74c02c 100644 Binary files a/grk/cw 6/Debug/Camera.obj and b/grk/cw 6/Debug/Camera.obj differ diff --git a/grk/cw 6/Debug/grk-cw6.exe.recipe b/grk/cw 6/Debug/Planeta.exe.recipe similarity index 71% rename from grk/cw 6/Debug/grk-cw6.exe.recipe rename to grk/cw 6/Debug/Planeta.exe.recipe index 3b7366c..28eb0c8 100644 --- a/grk/cw 6/Debug/grk-cw6.exe.recipe +++ b/grk/cw 6/Debug/Planeta.exe.recipe @@ -2,7 +2,7 @@ - j:\Downloads\grk\Debug\grk-cw6.exe + D:\STUDIA\Planeta\grk\Debug\Planeta.exe diff --git a/grk/cw 6/Debug/Planeta.tlog/CL.command.1.tlog b/grk/cw 6/Debug/Planeta.tlog/CL.command.1.tlog new file mode 100644 index 0000000..c6eee64 Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/CL.command.1.tlog differ diff --git a/grk/cw 6/Debug/Planeta.tlog/CL.read.1.tlog b/grk/cw 6/Debug/Planeta.tlog/CL.read.1.tlog new file mode 100644 index 0000000..f9908c0 Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/CL.read.1.tlog differ diff --git a/grk/cw 6/Debug/Planeta.tlog/CL.write.1.tlog b/grk/cw 6/Debug/Planeta.tlog/CL.write.1.tlog new file mode 100644 index 0000000..658cdc0 Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/CL.write.1.tlog differ diff --git a/grk/cw 6/Debug/Planeta.tlog/Cl.items.tlog b/grk/cw 6/Debug/Planeta.tlog/Cl.items.tlog new file mode 100644 index 0000000..ee8075f --- /dev/null +++ b/grk/cw 6/Debug/Planeta.tlog/Cl.items.tlog @@ -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 diff --git a/grk/cw 6/Debug/Planeta.tlog/Planeta.lastbuildstate b/grk/cw 6/Debug/Planeta.tlog/Planeta.lastbuildstate new file mode 100644 index 0000000..69579af --- /dev/null +++ b/grk/cw 6/Debug/Planeta.tlog/Planeta.lastbuildstate @@ -0,0 +1,2 @@ +PlatformToolSet=v143:VCToolArchitecture=Native32Bit:VCToolsVersion=14.38.33130:TargetPlatformVersion=10.0.22000.0: +Debug|Win32|D:\STUDIA\Planeta\grk\| diff --git a/grk/cw 6/Debug/Planeta.tlog/link.command.1.tlog b/grk/cw 6/Debug/Planeta.tlog/link.command.1.tlog new file mode 100644 index 0000000..4300346 Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/link.command.1.tlog differ diff --git a/grk/cw 6/Debug/Planeta.tlog/link.read.1.tlog b/grk/cw 6/Debug/Planeta.tlog/link.read.1.tlog new file mode 100644 index 0000000..823467f Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/link.read.1.tlog differ diff --git a/grk/cw 6/Debug/Planeta.tlog/link.write.1.tlog b/grk/cw 6/Debug/Planeta.tlog/link.write.1.tlog new file mode 100644 index 0000000..2839405 Binary files /dev/null and b/grk/cw 6/Debug/Planeta.tlog/link.write.1.tlog differ diff --git a/grk/cw 6/Debug/Render_Utils.obj b/grk/cw 6/Debug/Render_Utils.obj index 5fdf5b0..7dc4902 100644 Binary files a/grk/cw 6/Debug/Render_Utils.obj and b/grk/cw 6/Debug/Render_Utils.obj differ diff --git a/grk/cw 6/Debug/SOIL.obj b/grk/cw 6/Debug/SOIL.obj index 2c349d4..72ce3f1 100644 Binary files a/grk/cw 6/Debug/SOIL.obj and b/grk/cw 6/Debug/SOIL.obj differ diff --git a/grk/cw 6/Debug/Shader_Loader.obj b/grk/cw 6/Debug/Shader_Loader.obj index e0a87ee..db63012 100644 Binary files a/grk/cw 6/Debug/Shader_Loader.obj and b/grk/cw 6/Debug/Shader_Loader.obj differ diff --git a/grk/cw 6/Debug/Texture.obj b/grk/cw 6/Debug/Texture.obj index 6803a0f..1091c90 100644 Binary files a/grk/cw 6/Debug/Texture.obj and b/grk/cw 6/Debug/Texture.obj differ diff --git a/grk/cw 6/Debug/grk-cw3.Build.CppClean.log b/grk/cw 6/Debug/grk-cw3.Build.CppClean.log deleted file mode 100644 index 06872b5..0000000 --- a/grk/cw 6/Debug/grk-cw3.Build.CppClean.log +++ /dev/null @@ -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 diff --git a/grk/cw 6/Debug/grk-cw3.exe.recipe b/grk/cw 6/Debug/grk-cw3.exe.recipe deleted file mode 100644 index f66ba49..0000000 --- a/grk/cw 6/Debug/grk-cw3.exe.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\Andrzej\Desktop\grk\2021\rozwiązania\Debug\grk-cw3.exe - - - - - - \ No newline at end of file diff --git a/grk/cw 6/Debug/grk-cw3.log b/grk/cw 6/Debug/grk-cw3.log deleted file mode 100644 index b03afe7..0000000 --- a/grk/cw 6/Debug/grk-cw3.log +++ /dev/null @@ -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 diff --git a/grk/cw 6/Debug/grk-cw3.tlog/CL.command.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/CL.command.1.tlog deleted file mode 100644 index e584920..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/CL.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/CL.read.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/CL.read.1.tlog deleted file mode 100644 index 0dbded6..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/CL.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/CL.write.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/CL.write.1.tlog deleted file mode 100644 index 478d3b2..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/CL.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.lastbuildstate b/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.lastbuildstate deleted file mode 100644 index 7e95d8b..0000000 --- a/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.lastbuildstate +++ /dev/null @@ -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\| diff --git a/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.write.1u.tlog b/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.write.1u.tlog deleted file mode 100644 index 9d80848..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/grk-cw3.write.1u.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/link.command.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/link.command.1.tlog deleted file mode 100644 index b6bfacc..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/link.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/link.read.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/link.read.1.tlog deleted file mode 100644 index 6f984c1..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/link.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.tlog/link.write.1.tlog b/grk/cw 6/Debug/grk-cw3.tlog/link.write.1.tlog deleted file mode 100644 index b971317..0000000 Binary files a/grk/cw 6/Debug/grk-cw3.tlog/link.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw3.vcxproj.FileListAbsolute.txt b/grk/cw 6/Debug/grk-cw3.vcxproj.FileListAbsolute.txt deleted file mode 100644 index e69de29..0000000 diff --git a/grk/cw 6/Debug/grk-cw4.exe.recipe b/grk/cw 6/Debug/grk-cw4.exe.recipe deleted file mode 100644 index 9ec3c3b..0000000 --- a/grk/cw 6/Debug/grk-cw4.exe.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw4.exe - - - - - - \ No newline at end of file diff --git a/grk/cw 6/Debug/grk-cw4.log b/grk/cw 6/Debug/grk-cw4.log deleted file mode 100644 index edc4f8e..0000000 --- a/grk/cw 6/Debug/grk-cw4.log +++ /dev/null @@ -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 diff --git a/grk/cw 6/Debug/grk-cw4.tlog/CL.command.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/CL.command.1.tlog deleted file mode 100644 index c605d4e..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/CL.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/CL.read.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/CL.read.1.tlog deleted file mode 100644 index 1116532..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/CL.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/CL.write.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/CL.write.1.tlog deleted file mode 100644 index 1b0b0f3..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/CL.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.lastbuildstate b/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.lastbuildstate deleted file mode 100644 index 2aaec4b..0000000 --- a/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.lastbuildstate +++ /dev/null @@ -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\| diff --git a/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.write.1u.tlog b/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.write.1u.tlog deleted file mode 100644 index e258b01..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/grk-cw4.write.1u.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/link.command.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/link.command.1.tlog deleted file mode 100644 index c706302..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/link.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/link.read.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/link.read.1.tlog deleted file mode 100644 index a89d648..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/link.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw4.tlog/link.write.1.tlog b/grk/cw 6/Debug/grk-cw4.tlog/link.write.1.tlog deleted file mode 100644 index b10da31..0000000 Binary files a/grk/cw 6/Debug/grk-cw4.tlog/link.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.exe.recipe b/grk/cw 6/Debug/grk-cw5.exe.recipe deleted file mode 100644 index 4e04f82..0000000 --- a/grk/cw 6/Debug/grk-cw5.exe.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\Andrzej\Desktop\grk\2021\grk glfw test\Debug\grk-cw5.exe - - - - - - \ No newline at end of file diff --git a/grk/cw 6/Debug/grk-cw5.log b/grk/cw 6/Debug/grk-cw5.log deleted file mode 100644 index 2319662..0000000 --- a/grk/cw 6/Debug/grk-cw5.log +++ /dev/null @@ -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 diff --git a/grk/cw 6/Debug/grk-cw5.tlog/CL.command.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/CL.command.1.tlog deleted file mode 100644 index ff3e206..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/CL.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/CL.read.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/CL.read.1.tlog deleted file mode 100644 index b061b9f..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/CL.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/CL.write.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/CL.write.1.tlog deleted file mode 100644 index 96c69de..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/CL.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.lastbuildstate b/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.lastbuildstate deleted file mode 100644 index 2aaec4b..0000000 --- a/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.lastbuildstate +++ /dev/null @@ -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\| diff --git a/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.write.1u.tlog b/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.write.1u.tlog deleted file mode 100644 index 14a693b..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/grk-cw5.write.1u.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/link.command.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/link.command.1.tlog deleted file mode 100644 index c3793a7..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/link.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/link.read.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/link.read.1.tlog deleted file mode 100644 index 2c93f61..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/link.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw5.tlog/link.write.1.tlog b/grk/cw 6/Debug/grk-cw5.tlog/link.write.1.tlog deleted file mode 100644 index 254dd3c..0000000 Binary files a/grk/cw 6/Debug/grk-cw5.tlog/link.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.Build.CppClean.log b/grk/cw 6/Debug/grk-cw6.Build.CppClean.log deleted file mode 100644 index 0df61fb..0000000 --- a/grk/cw 6/Debug/grk-cw6.Build.CppClean.log +++ /dev/null @@ -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 diff --git a/grk/cw 6/Debug/grk-cw6.log b/grk/cw 6/Debug/grk-cw6.log index e312cc0..eafb246 100644 --- a/grk/cw 6/Debug/grk-cw6.log +++ b/grk/cw 6/Debug/grk-cw6.log @@ -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 diff --git a/grk/cw 6/Debug/grk-cw6.tlog/CL.command.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/CL.command.1.tlog deleted file mode 100644 index 6088b04..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/CL.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/CL.read.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/CL.read.1.tlog deleted file mode 100644 index 6859103..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/CL.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/CL.write.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/CL.write.1.tlog deleted file mode 100644 index c626fad..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/CL.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.lastbuildstate b/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.lastbuildstate deleted file mode 100644 index 8b180b4..0000000 --- a/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.29.30133:TargetPlatformVersion=10.0.19041.0: -Debug|Win32|j:\Downloads\grk\| diff --git a/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.write.1u.tlog b/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.write.1u.tlog deleted file mode 100644 index 70896e5..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/grk-cw6.write.1u.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/link.command.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/link.command.1.tlog deleted file mode 100644 index 5874b07..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/link.command.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/link.read.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/link.read.1.tlog deleted file mode 100644 index 54e81ce..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/link.read.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.tlog/link.write.1.tlog b/grk/cw 6/Debug/grk-cw6.tlog/link.write.1.tlog deleted file mode 100644 index 9cbc2aa..0000000 Binary files a/grk/cw 6/Debug/grk-cw6.tlog/link.write.1.tlog and /dev/null differ diff --git a/grk/cw 6/Debug/grk-cw6.vcxproj.FileListAbsolute.txt b/grk/cw 6/Debug/grk-cw6.vcxproj.FileListAbsolute.txt deleted file mode 100644 index e69de29..0000000 diff --git a/grk/cw 6/Debug/image_DXT.obj b/grk/cw 6/Debug/image_DXT.obj index 6487825..743968f 100644 Binary files a/grk/cw 6/Debug/image_DXT.obj and b/grk/cw 6/Debug/image_DXT.obj differ diff --git a/grk/cw 6/Debug/image_helper.obj b/grk/cw 6/Debug/image_helper.obj index 467954c..d45bec0 100644 Binary files a/grk/cw 6/Debug/image_helper.obj and b/grk/cw 6/Debug/image_helper.obj differ diff --git a/grk/cw 6/Debug/main.obj b/grk/cw 6/Debug/main.obj index 6f0f2cf..2e61dda 100644 Binary files a/grk/cw 6/Debug/main.obj and b/grk/cw 6/Debug/main.obj differ diff --git a/grk/cw 6/Debug/stb_image_aug.obj b/grk/cw 6/Debug/stb_image_aug.obj index 772e88f..56be77d 100644 Binary files a/grk/cw 6/Debug/stb_image_aug.obj and b/grk/cw 6/Debug/stb_image_aug.obj differ diff --git a/grk/cw 6/Debug/vc143.idb b/grk/cw 6/Debug/vc143.idb new file mode 100644 index 0000000..038c8a7 Binary files /dev/null and b/grk/cw 6/Debug/vc143.idb differ diff --git a/grk/cw 6/Debug/vc143.pdb b/grk/cw 6/Debug/vc143.pdb new file mode 100644 index 0000000..b86ccc2 Binary files /dev/null and b/grk/cw 6/Debug/vc143.pdb differ diff --git a/grk/cw 6/Zadania 2.html b/grk/cw 6/Zadania 2.html new file mode 100644 index 0000000..89c9d92 --- /dev/null +++ b/grk/cw 6/Zadania 2.html @@ -0,0 +1,144 @@ + + + + + + + Zadania 2 + + + + + +

Ł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.

+

+

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

+
#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

+
#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.

+ + diff --git a/grk/cw 6/Zadania 2.md b/grk/cw 6/Zadania 2.md new file mode 100644 index 0000000..6b2051e --- /dev/null +++ b/grk/cw 6/Zadania 2.md @@ -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. + diff --git a/grk/cw 6/Zadania 4.html b/grk/cw 6/Zadania 4.html new file mode 100644 index 0000000..acf3662 --- /dev/null +++ b/grk/cw 6/Zadania 4.html @@ -0,0 +1,101 @@ + + + + + + + Zadania 4 + + + + + + + + + +

Ładowanie obiektów za pomocą Assimp

+

W projekcie zaimplementowano ładowanie modeli przy użyciu biblioteki Assimp. Obiekty są ładowane za pomocą funkcji loadModelToContext(std::string path, Core::RenderContext& context). Pierwszym argumentem tej funkcji jest ścieżka, pod którą znajduje się model, a drugim jest referencja do RenderContext. Ta struktura przechowuje informacje o modelu, m.in. o jego VAO czy liczbie wierzchołków. Rysowanie obiektu odbywa się za pomocą funkcji Core::DrawContext(Core::RenderContext& context). Obecnie na przykładzie rysowana jest sfera ładowana z pliku.

+

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 ex_4_1.hpp znajduje się funkcja drawObjectColor, która przyjmuje rysowany obiekt jako Core::RenderContext&, macierz modelu jako glm::mat4 oraz kolor jako glm::vec3.

Zadanie

Wszystkie obiekty rysowane przez drawObjectColor są w jednym kolorze – napraw to. Wewnątrz funkcji przekaż kolor jako uniform do GPU (za pomocą funkcji glUniform3f) i odpowiednio zmodyfikuj shader fragmentów, aby wyznaczyć go jako kolor wyjściowy.

+

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).

+

Zadanie

+

Zadanie*

+

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 spaceshipPos i spaceshipDir. Następnie dostosuj cameraPos i cameraDir w zależności od wektorów spaceshipPos i spaceshipDir.

+

Zadanie*

+

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 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*

+

Zastąp model statku innym modelem.

+ +

Bufor głębokości

+

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ę 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.

+

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 (funkcja "mix" w glsl) 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.

+

Implementacja ruchu kamery w symulatorze kosmicznym bez synchronizacji modelu statku

+

Zadanie*

+

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. +


+float pitch = 0.0f;
+float yaw = -90.0f;
+float lastX = 800.0f / 2.0;
+float lastY = 600.0 / 2.0;
+bool firstMouse = true;
+

+ 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. +
 if (pitch > 89.0f)
+	pitch = 89.0f;
+if (pitch < -89.0f)
+	pitch = -89.0f;
+

+ Zastosuj funkcje trygonometryczne do przeliczenia kątów na wektor kierunku kamery:

+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);

+ +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ą. + + + \ No newline at end of file diff --git a/grk/cw 6/Zadania 4.md b/grk/cw 6/Zadania 4.md new file mode 100644 index 0000000..04d0de0 --- /dev/null +++ b/grk/cw 6/Zadania 4.md @@ -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. diff --git a/grk/cw 6/Zadania 5.md b/grk/cw 6/Zadania 5.md new file mode 100644 index 0000000..8f8d0b4 --- /dev/null +++ b/grk/cw 6/Zadania 5.md @@ -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) diff --git a/grk/cw 6/grk-cw6.vcxproj b/grk/cw 6/grk-cw6.vcxproj index 3573bc1..bd7bfd4 100644 --- a/grk/cw 6/grk-cw6.vcxproj +++ b/grk/cw 6/grk-cw6.vcxproj @@ -24,7 +24,7 @@ - + @@ -37,33 +37,33 @@ - - - - - - + + + + + + {3952C396-B1C6-44CD-96DD-C1AC15D32978} Win32Proj grk-cw6 - 10.0 - grk-cw6 + 10.0.22000.0 + Planeta Application true Unicode - v142 + v143 Application false true Unicode - v142 + v143 diff --git a/grk/cw 6/grk-cw6.vcxproj.filters b/grk/cw 6/grk-cw6.vcxproj.filters index 85fe689..afa41ad 100644 --- a/grk/cw 6/grk-cw6.vcxproj.filters +++ b/grk/cw 6/grk-cw6.vcxproj.filters @@ -86,27 +86,27 @@ Source Files\SOIL - + Source Files - + Shader Files - + Shader Files - + Shader Files - + Shader Files - + Shader Files - + Shader Files diff --git a/grk/cw 6/shaders/shader_5_1.frag b/grk/cw 6/shaders/shader.frag similarity index 51% rename from grk/cw 6/shaders/shader_5_1.frag rename to grk/cw 6/shaders/shader.frag index 951c43e..7c64436 100644 --- a/grk/cw 6/shaders/shader_5_1.frag +++ b/grk/cw 6/shaders/shader.frag @@ -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); } diff --git a/grk/cw 6/shaders/shader_5_1.vert b/grk/cw 6/shaders/shader.vert similarity index 74% rename from grk/cw 6/shaders/shader_5_1.vert rename to grk/cw 6/shaders/shader.vert index 1b569f5..d42abef 100644 --- a/grk/cw 6/shaders/shader_5_1.vert +++ b/grk/cw 6/shaders/shader.vert @@ -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); } diff --git a/grk/cw 6/shaders/shader_5_sun.frag b/grk/cw 6/shaders/shader_sun.frag similarity index 100% rename from grk/cw 6/shaders/shader_5_sun.frag rename to grk/cw 6/shaders/shader_sun.frag diff --git a/grk/cw 6/shaders/shader_5_sun.vert b/grk/cw 6/shaders/shader_sun.vert similarity index 100% rename from grk/cw 6/shaders/shader_5_sun.vert rename to grk/cw 6/shaders/shader_sun.vert diff --git a/grk/cw 6/shaders/shader_5_1_tex.frag b/grk/cw 6/shaders/shader_tex.frag similarity index 55% rename from grk/cw 6/shaders/shader_5_1_tex.frag rename to grk/cw 6/shaders/shader_tex.frag index 99d90fd..f7bdbe2 100644 --- a/grk/cw 6/shaders/shader_5_1_tex.frag +++ b/grk/cw 6/shaders/shader_tex.frag @@ -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); } diff --git a/grk/cw 6/shaders/shader_5_1_tex.vert b/grk/cw 6/shaders/shader_tex.vert similarity index 76% rename from grk/cw 6/shaders/shader_5_1_tex.vert rename to grk/cw 6/shaders/shader_tex.vert index 5c2ea01..2dc9e83 100644 --- a/grk/cw 6/shaders/shader_5_1_tex.vert +++ b/grk/cw 6/shaders/shader_tex.vert @@ -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; diff --git a/grk/cw 6/src/ex_6_1.hpp b/grk/cw 6/src/Planet.hpp similarity index 80% rename from grk/cw 6/src/ex_6_1.hpp rename to grk/cw 6/src/Planet.hpp index 128d9c7..9db7177 100644 --- a/grk/cw 6/src/ex_6_1.hpp +++ b/grk/cw 6/src/Planet.hpp @@ -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(); } } -//} \ No newline at end of file diff --git a/grk/cw 6/src/main.cpp b/grk/cw 6/src/main.cpp index 130671d..a6429ff 100644 --- a/grk/cw 6/src/main.cpp +++ b/grk/cw 6/src/main.cpp @@ -6,7 +6,7 @@ #include #include -#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); diff --git a/grk/cw 6/zadania 3.html b/grk/cw 6/zadania 3.html new file mode 100644 index 0000000..161020c --- /dev/null +++ b/grk/cw 6/zadania 3.html @@ -0,0 +1,164 @@ + + + + + + + zadania 3 + + + + + + +

Ć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.

+

+

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.

+

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.

+

+

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).

+

+
+

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.

+
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 argumentemscene->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:

+

+

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.

+ + diff --git a/grk/cw 6/zadania 3.md b/grk/cw 6/zadania 3.md new file mode 100644 index 0000000..719b4ac --- /dev/null +++ b/grk/cw 6/zadania 3.md @@ -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 textureCoord` i ` std::vector 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. \ No newline at end of file diff --git a/grk/cw 6/zadania 5.html b/grk/cw 6/zadania 5.html new file mode 100644 index 0000000..f9f678a --- /dev/null +++ b/grk/cw 6/zadania 5.html @@ -0,0 +1,116 @@ + + + + + + + Zadania 5 + + + + + + +

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.

  • +
+
    +
  1. Oblicz natężenie w shaderze fragmentów:
  2. +
+
    +
  • 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)

  • +
+
    +
  1. Zastosuj obliczone natężenie, aby zmodyfikować kolor obiektu:
  2. +
+
    +
  • 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:
  2. +
+
    +
  • 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.
  • +
+
    +
  1. Oblicz natężenie światła odbitego we fragment shaderze:
  2. +
+
    +
  • Oblicz wektor kierunku odbicia światła R przy użyciu funkcji reflect. 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.
  • +
+
    +
  1. Ustal ostateczny kolor piksela na objectColor * diffuse + lightColor * specular. Oznacza to najprostszy przypadek, gdy kolor światła odbitego jest biały.
  2. +
+

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 światła pozycję fragmentu, 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_5_sun.vert_ i shader_5_sun.frag), który będzie odpowiadał wyłącznie za rysowanie słońca. Poprzednie shadery (shader_4_1.vert_ i shader_5_1.frag) nadal mają rysować pozostałe obiekty. a) zainicjalizuj program (shadery): - Pliki shader_5_sun.vert i shader_5_sun.frag są identyczne z 5_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_5_1.vert i shader_5_1.frag (parametry wejściowe to ścieżka do shadera wierzchołków i fragmentów shader_5_sun.vert i shader_5_sun.frag).

  2. +
  3. 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:

  4. +
+
    +
  • 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.
  • +
+ + +

Zadanie - Zmień shader słońca na bardziej realistyczny

+ +

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 V jak i funkcja mix.

+

+ +

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. Przed kwadratowaniem przemnoz diystans przez 10.0.

+ +

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. +

+ + diff --git a/grk/grk-cw.sln b/grk/grk-cw.sln index b9ce046..c316d43 100644 --- a/grk/grk-cw.sln +++ b/grk/grk-cw.sln @@ -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