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

748 lines
37 KiB
HTML
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<link href='https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet' type='text/css' /><style type='text/css'>html {overflow-x: initial !important;}:root { --bg-color:#ffffff; --text-color:#333333; --select-text-bg-color:#B5D6FC; --select-text-font-color:auto; --monospace:"Lucida Console",Consolas,"Courier",monospace; --title-bar-height:20px; }
.mac-os-11 { --title-bar-height:28px; }
html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; }
body { margin: 0px; padding: 0px; height: auto; inset: 0px; font-size: 1rem; line-height: 1.42857; overflow-x: hidden; background: inherit; tab-size: 4; }
iframe { margin: auto; }
a.url { word-break: break-all; }
a:active, a:hover { outline: 0px; }
.in-text-selection, ::selection { text-shadow: none; background: var(--select-text-bg-color); color: var(--select-text-font-color); }
#write { margin: 0px auto; height: auto; width: inherit; word-break: normal; overflow-wrap: break-word; position: relative; white-space: normal; overflow-x: visible; padding-top: 36px; }
#write.first-line-indent p { text-indent: 2em; }
#write.first-line-indent li p, #write.first-line-indent p * { text-indent: 0px; }
#write.first-line-indent li { margin-left: 2em; }
.for-image #write { padding-left: 8px; padding-right: 8px; }
body.typora-export { padding-left: 30px; padding-right: 30px; }
.typora-export .footnote-line, .typora-export li, .typora-export p { white-space: pre-wrap; }
.typora-export .task-list-item input { pointer-events: none; }
@media screen and (max-width: 500px) {
body.typora-export { padding-left: 0px; padding-right: 0px; }
#write { padding-left: 20px; padding-right: 20px; }
.CodeMirror-sizer { margin-left: 0px !important; }
.CodeMirror-gutters { display: none !important; }
}
#write li > figure:last-child { margin-bottom: 0.5rem; }
#write ol, #write ul { position: relative; }
img { max-width: 100%; vertical-align: middle; image-orientation: from-image; }
button, input, select, textarea { color: inherit; font: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
*, ::after, ::before { box-sizing: border-box; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p, #write pre { width: inherit; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p { position: relative; }
p { line-height: inherit; }
h1, h2, h3, h4, h5, h6 { break-after: avoid-page; break-inside: avoid; orphans: 4; }
p { orphans: 4; }
h1 { font-size: 2rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.4rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1rem; }
.md-math-block, .md-rawblock, h1, h2, h3, h4, h5, h6, p { margin-top: 1rem; margin-bottom: 1rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: 700; font-style: italic; }
a { cursor: pointer; }
sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.7); color: rgb(85, 85, 85); border-radius: 4px; cursor: pointer; }
sup.md-footnote a, sup.md-footnote a:hover { color: inherit; text-transform: inherit; text-decoration: inherit; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; }
figure { overflow-x: auto; margin: 1.2em 0px; max-width: calc(100% + 16px); padding: 0px; }
figure > table { margin: 0px; }
tr { break-inside: avoid; break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; }
table.md-table td { min-width: 32px; }
.CodeMirror-gutters { border-right: 0px; background-color: inherit; }
.CodeMirror-linenumber { user-select: none; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
#write pre { white-space: pre-wrap; }
#write.fences-no-line-wrapping pre { white-space: pre; }
#write pre.ty-contain-cm { white-space: normal; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background: inherit; position: relative !important; }
.md-fences-adv-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; }
#write .md-fences.mock-cm { white-space: pre-wrap; }
.md-fences.md-fences-with-lineno { padding-left: 0px; }
#write.fences-no-line-wrapping .md-fences.mock-cm { white-space: pre; overflow-x: auto; }
.md-fences.mock-cm.md-fences-with-lineno { padding-left: 8px; }
.CodeMirror-line, twitterwidget { break-inside: avoid; }
.footnotes { opacity: 0.8; font-size: 0.9rem; margin-top: 1em; margin-bottom: 1em; }
.footnotes + .footnotes { margin-top: 0px; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; background: 0px 0px; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; -webkit-tap-highlight-color: transparent; line-height: normal; font-weight: 400; text-align: left; box-sizing: content-box; direction: ltr; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li .mathjax-block, li p { margin: 0.5rem 0px; }
li blockquote { margin: 1rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child, li > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; white-space: normal; }
#write .footnote-line { white-space: pre-wrap; }
@media print {
body, html { border: 1px solid transparent; height: 99%; break-after: avoid; break-before: avoid; font-variant-ligatures: no-common-ligatures; }
#write { margin-top: 0px; padding-top: 0px; border-color: transparent !important; }
.typora-export * { -webkit-print-color-adjust: exact; }
.typora-export #write { break-after: avoid; }
.typora-export #write::after { height: 0px; }
.is-mac table { break-inside: avoid; }
.typora-export-show-outline .typora-export-sidebar { display: none; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
pre.md-meta-block { font-size: 0.8rem; min-height: 0.8rem; white-space: pre-wrap; background: rgb(204, 204, 204); display: block; overflow-x: hidden; }
p > .md-image:only-child:not(.md-img-error) img, p > img:only-child { display: block; margin: auto; }
#write.first-line-indent p > .md-image:only-child:not(.md-img-error) img { left: -2em; position: relative; }
p > .md-image:only-child { display: inline-block; width: 100%; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.md-math-block { width: 100%; }
.md-math-block:not(:empty)::after { display: none; }
.MathJax_ref { fill: currentcolor; }
[contenteditable="true"]:active, [contenteditable="true"]:focus, [contenteditable="false"]:active, [contenteditable="false"]:focus { outline: 0px; box-shadow: none; }
.md-task-list-item { position: relative; list-style-type: none; }
.task-list-item.md-task-list-item { padding-left: 0px; }
.md-task-list-item > input { position: absolute; top: 0px; left: 0px; margin-left: -1.2em; margin-top: calc(1em - 10px); border: none; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc-content::after, .md-toc::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); }
.md-toc-item a { text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: 700; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
.md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
.md-toc-h4 .md-toc-inner { margin-left: 5em; }
.md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
.md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
code, pre, samp, tt { font-family: var(--monospace); }
kbd { margin: 0px 0.1em; padding: 0.1em 0.6em; font-size: 0.8em; color: rgb(36, 39, 41); background: rgb(255, 255, 255); border: 1px solid rgb(173, 179, 185); border-radius: 3px; box-shadow: rgba(12, 13, 14, 0.2) 0px 1px 0px, rgb(255, 255, 255) 0px 0px 0px 2px inset; white-space: nowrap; vertical-align: middle; }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: var(--monospace); }
code { text-align: left; vertical-align: initial; }
a.md-print-anchor { white-space: pre !important; border-width: initial !important; border-style: none !important; border-color: initial !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: 0px !important; background: 0px 0px !important; text-decoration: initial !important; text-shadow: initial !important; }
.os-windows.monocolor-emoji .md-emoji { font-family: "Segoe UI Symbol", sans-serif; }
.md-diagram-panel > svg { max-width: 100%; }
[lang="flow"] svg, [lang="mermaid"] svg { max-width: 100%; height: auto; }
[lang="mermaid"] .node text { font-size: 1rem; }
table tr th { border-bottom: 0px; }
video { max-width: 100%; display: block; margin: 0px auto; }
iframe { max-width: 100%; width: 100%; border: none; }
.highlight td, .highlight tr { border: 0px; }
mark { background: rgb(255, 255, 0); color: rgb(0, 0, 0); }
.md-html-inline .md-plain, .md-html-inline strong, mark .md-inline-math, mark strong { color: inherit; }
.md-expand mark .md-meta { opacity: 0.3 !important; }
mark .md-meta { color: rgb(0, 0, 0); }
@media print {
.typora-export h1, .typora-export h2, .typora-export h3, .typora-export h4, .typora-export h5, .typora-export h6 { break-inside: avoid; }
}
.md-diagram-panel .messageText { stroke: none !important; }
.md-diagram-panel .start-state { fill: var(--node-fill); }
.md-diagram-panel .edgeLabel rect { opacity: 1 !important; }
.md-require-zoom-fix { height: auto; margin-top: 16px; margin-bottom: 16px; }
.md-require-zoom-fix foreignobject { font-size: var(--mermaid-font-zoom); }
.md-fences.md-fences-math { font-size: 1em; }
.md-fences-advanced:not(.md-focus) { padding: 0px; white-space: nowrap; border: 0px; }
.md-fences-advanced:not(.md-focus) { background: inherit; }
.typora-export-show-outline .typora-export-content { max-width: 1440px; margin: auto; display: flex; flex-direction: row; }
.typora-export-sidebar { width: 300px; font-size: 0.8rem; margin-top: 80px; margin-right: 18px; }
.typora-export-show-outline #write { --webkit-flex:2; flex: 2 1 0%; }
.typora-export-sidebar .outline-content { position: fixed; top: 0px; max-height: 100%; overflow: hidden auto; padding-bottom: 30px; padding-top: 60px; width: 300px; }
@media screen and (max-width: 1024px) {
.typora-export-sidebar, .typora-export-sidebar .outline-content { width: 240px; }
}
@media screen and (max-width: 800px) {
.typora-export-sidebar { display: none; }
}
.outline-content li, .outline-content ul { margin-left: 0px; margin-right: 0px; padding-left: 0px; padding-right: 0px; list-style: none; }
.outline-content ul { margin-top: 0px; margin-bottom: 0px; }
.outline-content strong { font-weight: 400; }
.outline-expander { width: 1rem; height: 1.42857rem; position: relative; display: table-cell; vertical-align: middle; cursor: pointer; padding-left: 4px; }
.outline-expander::before { content: ""; position: relative; font-family: Ionicons; display: inline-block; font-size: 8px; vertical-align: middle; }
.outline-item { padding-top: 3px; padding-bottom: 3px; cursor: pointer; }
.outline-expander:hover::before { content: ""; }
.outline-h1 > .outline-item { padding-left: 0px; }
.outline-h2 > .outline-item { padding-left: 1em; }
.outline-h3 > .outline-item { padding-left: 2em; }
.outline-h4 > .outline-item { padding-left: 3em; }
.outline-h5 > .outline-item { padding-left: 4em; }
.outline-h6 > .outline-item { padding-left: 5em; }
.outline-label { cursor: pointer; display: table-cell; vertical-align: middle; text-decoration: none; color: inherit; }
.outline-label:hover { text-decoration: underline; }
.outline-item:hover { border-color: rgb(245, 245, 245); background-color: var(--item-hover-bg-color); }
.outline-item:hover { margin-left: -28px; margin-right: -28px; border-left: 28px solid transparent; border-right: 28px solid transparent; }
.outline-item-single .outline-expander::before, .outline-item-single .outline-expander:hover::before { display: none; }
.outline-item-open > .outline-item > .outline-expander::before { content: ""; }
.outline-children { display: none; }
.info-panel-tab-wrapper { display: none; }
.outline-item-open > .outline-children { display: block; }
.typora-export .outline-item { padding-top: 1px; padding-bottom: 1px; }
.typora-export .outline-item:hover { margin-right: -8px; border-right: 8px solid transparent; }
.typora-export .outline-expander::before { content: "+"; font-family: inherit; top: -1px; }
.typora-export .outline-expander:hover::before, .typora-export .outline-item-open > .outline-item > .outline-expander::before { content: ""; }
.typora-export-collapse-outline .outline-children { display: none; }
.typora-export-collapse-outline .outline-item-open > .outline-children, .typora-export-no-collapse-outline .outline-children { display: block; }
.typora-export-no-collapse-outline .outline-expander::before { content: "" !important; }
.typora-export-show-outline .outline-item-active > .outline-item .outline-label { font-weight: 700; }
.md-inline-math-container mjx-container { zoom: 0.95; }
:root {
--side-bar-bg-color: #fafafa;
--control-text-color: #777;
}
@include-when-export url(https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);
/* open-sans-regular - latin-ext_latin */
/* open-sans-italic - latin-ext_latin */
/* open-sans-700 - latin-ext_latin */
/* open-sans-700italic - latin-ext_latin */
html {
font-size: 16px;
-webkit-font-smoothing: antialiased;
}
body {
font-family: "Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, 'Segoe UI Emoji', sans-serif;
color: rgb(51, 51, 51);
line-height: 1.6;
}
#write {
max-width: 860px;
margin: 0 auto;
padding: 30px;
padding-bottom: 100px;
}
@media only screen and (min-width: 1400px) {
#write {
max-width: 1024px;
}
}
@media only screen and (min-width: 1800px) {
#write {
max-width: 1200px;
}
}
#write > ul:first-child,
#write > ol:first-child{
margin-top: 30px;
}
a {
color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
position: relative;
margin-top: 1rem;
margin-bottom: 1rem;
font-weight: bold;
line-height: 1.4;
cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
text-decoration: none;
}
h1 tt,
h1 code {
font-size: inherit;
}
h2 tt,
h2 code {
font-size: inherit;
}
h3 tt,
h3 code {
font-size: inherit;
}
h4 tt,
h4 code {
font-size: inherit;
}
h5 tt,
h5 code {
font-size: inherit;
}
h6 tt,
h6 code {
font-size: inherit;
}
h1 {
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}
h2 {
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}
/*@media print {
.typora-export h1,
.typora-export h2 {
border-bottom: none;
padding-bottom: initial;
}
.typora-export h1::after,
.typora-export h2::after {
content: "";
display: block;
height: 100px;
margin-top: -96px;
border-top: 1px solid #eee;
}
}*/
h3 {
font-size: 1.5em;
line-height: 1.43;
}
h4 {
font-size: 1.25em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 1em;
color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table{
margin: 0.8em 0;
}
li>ol,
li>ul {
margin: 0 0;
}
hr {
height: 2px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
overflow: hidden;
box-sizing: content-box;
}
li p.first {
display: inline-block;
}
ul,
ol {
padding-left: 30px;
}
ul:first-child,
ol:first-child {
margin-top: 0;
}
ul:last-child,
ol:last-child {
margin-bottom: 0;
}
blockquote {
border-left: 4px solid #dfe2e5;
padding: 0 15px;
color: #777777;
}
blockquote blockquote {
padding-right: 0;
}
table {
padding: 0;
word-break: initial;
}
table tr {
border: 1px solid #dfe2e5;
margin: 0;
padding: 0;
}
table tr:nth-child(2n),
thead {
background-color: #f8f8f8;
}
table th {
font-weight: bold;
border: 1px solid #dfe2e5;
border-bottom: 0;
margin: 0;
padding: 6px 13px;
}
table td {
border: 1px solid #dfe2e5;
margin: 0;
padding: 6px 13px;
}
table th:first-child,
table td:first-child {
margin-top: 0;
}
table th:last-child,
table td:last-child {
margin-bottom: 0;
}
.CodeMirror-lines {
padding-left: 4px;
}
.code-tooltip {
box-shadow: 0 1px 1px 0 rgba(0,28,36,.3);
border-top: 1px solid #eef2f2;
}
.md-fences,
code,
tt {
border: 1px solid #e7eaed;
background-color: #f8f8f8;
border-radius: 3px;
padding: 0;
padding: 2px 4px 0px 4px;
font-size: 0.9em;
}
code {
background-color: #f3f4f4;
padding: 0 2px 0 2px;
}
.md-fences {
margin-bottom: 15px;
margin-top: 15px;
padding-top: 8px;
padding-bottom: 6px;
}
.md-task-list-item > input {
margin-left: -1.3em;
}
@media print {
html {
font-size: 13px;
}
table,
pre {
page-break-inside: avoid;
}
pre {
word-wrap: break-word;
}
}
.md-fences {
background-color: #f8f8f8;
}
#write pre.md-meta-block {
padding: 1rem;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border: 0;
border-radius: 3px;
color: #777777;
margin-top: 0 !important;
}
.mathjax-block>.code-tooltip {
bottom: .375rem;
}
.md-mathjax-midline {
background: #fafafa;
}
#write>h3.md-focus:before{
left: -1.5625rem;
top: .375rem;
}
#write>h4.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
#write>h5.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
#write>h6.md-focus:before{
left: -1.5625rem;
top: .285714286rem;
}
.md-image>.md-meta {
/*border: 1px solid #ddd;*/
border-radius: 3px;
padding: 2px 0px 0px 4px;
font-size: 0.9em;
color: inherit;
}
.md-tag {
color: #a7a7a7;
opacity: 1;
}
.md-toc {
margin-top:20px;
padding-bottom:20px;
}
.sidebar-tabs {
border-bottom: none;
}
#typora-quick-open {
border: 1px solid #ddd;
background-color: #f8f8f8;
}
#typora-quick-open-item {
background-color: #FAFAFA;
border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
border-style: solid;
border-width: 1px;
}
/** focus mode */
.on-focus-mode blockquote {
border-left-color: rgba(85, 85, 85, 0.12);
}
header, .context-menu, .megamenu-content, footer{
font-family: "Segoe UI", "Arial", sans-serif;
}
.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state{
visibility: visible;
}
.mac-seamless-mode #typora-sidebar {
background-color: #fafafa;
background-color: var(--side-bar-bg-color);
}
.md-lang {
color: #b4654d;
}
/*.html-for-mac {
--item-hover-bg-color: #E6F0FE;
}*/
#md-notification .btn {
border: 0;
}
.dropdown-menu .divider {
border-color: #e5e5e5;
opacity: 0.4;
}
.ty-preferences .window-content {
background-color: #fafafa;
}
.ty-preferences .nav-group-item.active {
color: white;
background: #999;
}
.menu-item-container a.menu-style-btn {
background-color: #f5f8fa;
background-image: linear-gradient( 180deg , hsla(0, 0%, 100%, 0.8), hsla(0, 0%, 100%, 0));
}
mjx-container[jax="SVG"] {
direction: ltr;
}
mjx-container[jax="SVG"] > svg {
overflow: visible;
min-height: 1px;
min-width: 1px;
}
mjx-container[jax="SVG"] > svg a {
fill: blue;
stroke: blue;
}
mjx-assistive-mml {
position: absolute !important;
top: 0px;
left: 0px;
clip: rect(1px, 1px, 1px, 1px);
padding: 1px 0px 0px 0px !important;
border: 0px !important;
display: block !important;
width: auto !important;
overflow: hidden !important;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
mjx-assistive-mml[display="block"] {
width: 100% !important;
}
mjx-container[jax="SVG"][display="true"] {
display: block;
text-align: center;
margin: 1em 0;
}
mjx-container[jax="SVG"][display="true"][width="full"] {
display: flex;
}
mjx-container[jax="SVG"][justify="left"] {
text-align: left;
}
mjx-container[jax="SVG"][justify="right"] {
text-align: right;
}
g[data-mml-node="merror"] > g {
fill: red;
stroke: red;
}
g[data-mml-node="merror"] > rect[data-background] {
fill: yellow;
stroke: none;
}
g[data-mml-node="mtable"] > line[data-line], svg[data-table] > g > line[data-line] {
stroke-width: 70px;
fill: none;
}
g[data-mml-node="mtable"] > rect[data-frame], svg[data-table] > g > rect[data-frame] {
stroke-width: 70px;
fill: none;
}
g[data-mml-node="mtable"] > .mjx-dashed, svg[data-table] > g > .mjx-dashed {
stroke-dasharray: 140;
}
g[data-mml-node="mtable"] > .mjx-dotted, svg[data-table] > g > .mjx-dotted {
stroke-linecap: round;
stroke-dasharray: 0,140;
}
g[data-mml-node="mtable"] > g > svg {
overflow: visible;
}
[jax="SVG"] mjx-tool {
display: inline-block;
position: relative;
width: 0;
height: 0;
}
[jax="SVG"] mjx-tool > mjx-tip {
position: absolute;
top: 0;
left: 0;
}
mjx-tool > mjx-tip {
display: inline-block;
padding: .2em;
border: 1px solid #888;
font-size: 70%;
background-color: #F8F8F8;
color: black;
box-shadow: 2px 2px 5px #AAAAAA;
}
g[data-mml-node="maction"][data-toggle] {
cursor: pointer;
}
mjx-status {
display: block;
position: fixed;
left: 1em;
bottom: 1em;
min-width: 25%;
padding: .2em .4em;
border: 1px solid #888;
font-size: 90%;
background-color: #F8F8F8;
color: black;
}
foreignObject[data-mjx-xml] {
font-family: initial;
line-height: normal;
overflow: visible;
}
mjx-container[jax="SVG"] path[data-c], mjx-container[jax="SVG"] use[data-c] {
stroke-width: 3;
}
g[data-mml-node="xypic"] path {
stroke-width: inherit;
}
.MathJax g[data-mml-node="xypic"] path {
stroke-width: inherit;
}
:root {--mermaid-font-zoom:1.5em ;}
</style><title>zadania 5</title>
</head>
<body class='typora-export os-windows'><div class='typora-export-content'>
<div id='write' class=''><h1 id='ii-teksturowanie'><span>II Teksturowanie</span></h1><h3 id='ii0-obejrzyj-plik-textureh-aby-zapoznać-się-z-nowym-interfejsem-do-obsługi-tekstur'><span>II.0 Obejrzyj plik </span><strong><span>Texture.h</span></strong><span> aby zapoznać się z nowym interfejsem do obsługi tekstur.</span></h3><h3 id='ii1-przygotuj-shadery-i-załaduj-teksturę'><span>II.1 Przygotuj shadery i załaduj teksturę:</span></h3><p><span>a) W kolejnych zadaniach będziemy potrzebować trzecią parę shaderów: </span><strong><span>shader_4_tex.vert</span></strong><span> i </span><strong><span>shader_4_tex.frag</span></strong><span> są one gotowymi shaderami z poprzednich zadań. </span></p><ul><li><span>Wczytaj shadery i przechowaj adres programu pod zmienną globalną </span><code>programTex</code><span> (tzn. powtórz dla nich punkt 6.a, ale zamiast </span><code>programSun</code><span> nazwij zmienną </span><code>programTex</code><span>).</span></li><li><span>Prześlij globalne </span><em><span>uniformy</span></em><span> do </span><code>programTex</code><span>.</span></li></ul><p><span>b) ładowanie tekstury:</span></p><ul><li><span>Pod </span><code>namespace texture</code><span> znajdują się zmienne globalne typu </span><code>Gluint</code><span>, które będą przechowywać adresy tekstur. W funkcji </span><code>init()</code><span> załaduj tekstury z folderu </span><strong><span>textures</span></strong><span> przy pomocy </span><code>Core::LoadTexture</code><span>. Ta funkcja zwraca adres do wczytanej tekstury, przypisz je do zmiennych z </span><code>namespace texture</code><span>. </span></li><li><span>(odwołanie się do </span><code>namespace</code><span> wykonuje się za pomocą ::, czyli by odwołać się do </span><code>grid</code><span> w </span><code>namespace</code><span> </span><code>texture</code><span> należy napisać </span><code>texture::grid</code><span>)</span></li></ul><h3 id='ii2-stwórz-funkcje-odpowiadająca-za-rysowanie-teksturowanych-obiektów'><span>II.2. Stwórz funkcje odpowiadająca za rysowanie teksturowanych obiektów:</span></h3><ul><li><span>Skopiuj funkcję </span><code>drawObject</code><span>. Nazwij kopię </span><code>drawObjectTexture()</code><span> i zmodyfikują ją tak, aby przyjmowała jako parametr identyfikator tekstury, a nie wektor koloru. (Usuń w niej linijkę odpowiadającą za przesyłanie koloru, żeby uniknąć błędu komunikacji, później dodamy na jej miejsce ładowanie tekstury).</span></li></ul><p>&nbsp;</p><h3 id='ii3-zmodyfikuj-shader-tak-aby-nakładał-teksturę-na-obiekt'><span>II.3. Zmodyfikuj shader tak, aby nakładał teksturę na obiekt:</span></h3><p><span>a) Narysuj jedną z planet za pomocą </span><code>drawObjectTexture()</code><span>, użyj </span><code>programTex</code><span> jako programu.</span></p><p><span>b) Prześlij współrzędne mapowania tekstur z </span><em><span>vertex shadera</span></em><span> do </span><em><span>fragment shadera</span></em></p><ul><li><span>Współrzędne tekstur to kolejny (po pozycjach i wektorach normalnych) atrybut wierzchołków - są dostępne w </span><em><span>vertex shaderze</span></em><span> pod nazwą </span><code>vertexTexCoord</code></li><li><span>Prześlij je znanym już sposobem do </span><em><span>fragment shadera</span></em><span> (zmienna </span><code>out</code><span> w </span><em><span>vertex shaderze</span></em><span> i odpowiadająca jej zmienna </span><code>in</code><span> we </span><em><span>fragment shaderze</span></em><span>)</span></li></ul><p><span>c) Prześlij teksturę do fragment shadera:</span></p><ul><li><span>Stwórz zmienną typu </span><code>uniform sampler2D</code><span> (nazwij ją na przykład </span><code>colorTexture</code><span>) we fragment shaderze - analogicznie do innych zmiennych typu uniform, służy ona do przesyłania informacji bezpośrednio z kodu C++ do shadera</span></li><li><span>Po stronie kodu C++ użyj funkcji </span><code>Core::SetActiveTexture</code><span> wewnątrz </span><code>drawObjectTexture()</code><span> aby ustawić zmienną </span><code>sampler2D</code><span> na wczytaną wcześniej teksturę</span></li></ul><p><span>d) Użyj wartości uzyskanej z tekstury zamiast koloru (</span><code>objectColor</code><span>) do pokolorowania obiektu:</span></p><ul><li><span>Wykonaj próbkowanie tekstury we współrzędnych otrzymanych przez fragment shader: </span><code>vec4 textureColor = texture2D(~nazwaZmiennejSampler2D, ~nazwaZmiennejWspolrzedneTekstury)</code><span>&quot; (</span><code>vec4</code><span> zawiera kolor RGBA)</span></li><li><span>Użyj pierwszych trzech współrzędnych (RGB) uzyskanego wektora jako nowego koloru bazowego piksela</span></li></ul><h3 id='ii4-pobaw-się-mechanizmem-teksturowania'><span>II.4. Pobaw się mechanizmem teksturowania:</span></h3><ul><li><span>Przemnóż jedną lub obie ze współrzędnych mapowania przez 5 i sprawdź co się stanie</span></li><li><span>Wypróbuj pozostałe tekstury: </span><strong><span>grid_color.png</span></strong><span>, </span><strong><span>earth.png</span></strong><span> i </span><strong><span>earth2.png</span></strong><span>.</span></li><li><span>Tekstury Ziemi wyświetlają się &quot;do góry nogami&quot;. Napraw to.</span></li><li><span>Jeśli chcesz mieć kilka planet o różnych teksturach możesz skorzystać z </span><a href='https://www.solarsystemscope.com/textures/'><span>link</span></a><span> lub </span><a href='https://stevealbers.net/albers/sos/sos.html'><span>link2</span></a></li></ul><h3 id='ii5-teksturowanie-proceduralne'><span>II.5*. Teksturowanie proceduralne</span></h3><p><span>a) Stwórz czwartą parę plików z shaderami (np. </span><strong><span>shader_proc_tex.vert</span></strong><span> i </span><strong><span>shader_proc_tex.frag</span></strong><span>). Następnie zainicjalizuj program jak w I.6.a) i II.1.a) (nazwij go np </span><code>programProcTex</code><span>). Do wywołania rysowania wykorzystuj funkcję </span><code>drawObject</code><span> (Żeby nie tracić oteksturowanych planet, możesz rysować za ich pomocą wyłącznie statek).</span></p><p><span>b) Prostym sposobem proceduralnego teksturowania, jest uzależnienie koloru od pozycji piksela w przestrzeni lokalnej (użycie przestrzeni świata spowodowałoby, że wzór na obiekcie zmieniałby się przy poruszaniu go).</span></p><ul><li><span>Prześlij z vertex shadera do fragment shadera pozycję wierzchołka w przestrzeni lokalnej (czyli tej, w której wyrażone są atrybuty wierzchołka - nie trzeba więc wykonywać żadnej transformacji macierzowej)</span></li><li><span>We fragment shaderze oblicz sinus współrzędnej y pozycji piksela</span></li><li><span>Jeżeli sinus jest większy od zera, to ustaw bazowy kolor obiektu na wybrany kolor, a jeśli jest mniejszy od zera, to na inny kolor</span></li><li><span>Możesz przesłać te kolory przy użyciu zmiennych uniform z kodu C++ - pozwoli to rysować różne obiekty z różnymi parami kolorów</span></li><li><span>Poeksperymentuj z innymi metodami teksturowania proceduralnego podanymi na wykładzie</span></li></ul><h1 id='iii-normal-mapping'><span>III Normal Mapping</span></h1><p><span>W tej części będziemy dalej modyfikować shadery </span><strong><span>shader_4_tex</span></strong><span> poprzez implementację normal mappingu</span></p><p><span>Obliczenia dla map normalnych należy wykonywać w przestrzeni stycznych. Przestrzeń styczna jest wyliczana dla każdego punktu w obiekcie. Jej celem jest takie przekształcenie przestrzeni, żeby wektor normalny był wektorem jednostkowym (0,1,0). </span></p><p><span>Do wyliczenia przestrzeni stycznej potrzebujemy dla każdego wierzchołka oprócz wektora normalnego wektor styczny i bistyczny (</span><em><span>tangent</span></em><span> i </span><em><span>bitangent</span></em><span>). Są one wyliczane przez bibliotekę </span><code>Assimp</code><span>. </span></p><h3 id='iii0-wykonaj-kopię-shaderów-shader4texvert-shader4texfrag'><span>III.0 Wykonaj kopię shaderów shader_4_tex.vert shader_4_tex.frag </span></h3><h3 id='iii1-przenieś-obliczenia-światła-do-przestrzeni-stycznej'><span>III.1 Przenieś obliczenia światła do przestrzeni stycznej</span></h3><ol><li><p><span>Oblicz macierz </span><strong><span>TBN</span></strong><span>.</span></p><p><span>Macierz </span><strong><span>TBN</span></strong><span> to macierz 3x3 wyznaczana przez wektory </span><em><span>tangent</span></em><span>, </span><em><span>bitangent</span></em><span> i </span><em><span>normal</span></em><span>, służy do przenoszenia wektorów z przestrzeni świata do przestrzeni stycznej.</span></p><ol start='' ><li><span>W </span><strong><span>vertex shaderze</span></strong><span> przekrztałć wektory </span><code>vertexNormal</code><span>, </span><code>vertexTangent</code><span> i </span><code>vertexBitangent</code><span> do przestrzeni świata (przemnóż macierz modelu przez te wektory, tak jak to robiliśmy wcześniej z wektorem normalnym, z uwzględnieniem zmiennej w=0) i zapisz wyniki odpowiednio w zmiennych </span><code>normal</code><span>, </span><code>tangent</code><span> i </span><code>bitangent</code><span>.</span></li><li><span>Stwórz macierz 3x3 TBN jako transpose(mat3(tangent, bitangent, normal)). Macierz transponujemy, aby szybko uzyskać jej odwrotność (możemy tak zrobić przy założeniu, ze jest ortogonalna).</span></li></ol></li></ol><ol start='2' ><li><p><span>Przenieś wektor światła i wektor widoku do przestrzeni stycznych</span></p><ol><li><p><span>Musimy przekształcić wektor światła (L) i wektor widoku (V) do przestrzeni stycznych. Co ważne, zrobimy to w vertex shaderze. W tym celu przenieś potrzebne dane dotyczące światła i kamery (uniformy </span><code>lightPos</code><span> i </span><code>cameraPos</code><span>) z </span><strong><span>fragment shadera</span></strong><span> do </span><strong><span>vertex shadera.</span></strong></p></li><li><p><span>Oblicz wektor </span><code>viewDir</code><span> jako znormalizowana różnice </span><code>cameraPos</code><span> i </span><code>fragPos</code><span> (tu jeszcze działamy w przestrzeni świata). Analogicznie oblicz </span><code>lightDir</code><span> jako różnicę </span><code>lightPos</code><span> i </span><code>fragPos</code></p></li><li><p><span>Przekształć wektory </span><code>viewDir</code><span> i </span><code>lightDir</code><span> do przestrzeni stycznej mnożąc je przez macierz </span><strong><span>TBN</span></strong><span>. Wynik zapisz w zmiennych</span><code>viewDirTS</code><span> i </span><code>lightDirTS</code><span> odpowiednio.</span></p></li><li><p><span>Przekaż </span><code>viewDirTS</code><span> i </span><code>lightDirTS</code><span> do fragment shadera. (zadeklaruj je jako zmienne </span><code>out</code><span>)</span></p><blockquote><p><span>(Sufiks TS oznacza tangent space. Wazne jest, aby oznaczac (np. dopisujac cos do nazwy zmiennej) w jakiej przestrzeni znajduja sie uzywane wektory, tak aby poprawnie wykonywac obliczenia. Trzeba zawsze zwracac uwage na to, w jakiej przestrzeni dzialamy.)</span></p></blockquote></li></ol></li></ol><ol start='3' ><li><p><span>Przekształć </span><strong><span>fragment shader</span></strong><span>, by obsługiwał </span><strong><span>tangent space</span></strong></p><ol><li><span>Nie potrzebujemy już we </span><strong><span>fragment shaderze</span></strong><span> informacji na temat pozycji fragmentu i wektora normalnego geometrii, skasuj wiec zmienne przekazujące te wektory pomiędzy shaderami.</span></li><li><span>wektora </span><code>lightDir</code><span> powinniśmy użyć wektora </span><code>lightDirTS</code><span> (należy go dodatkowo znormalizować), a jako wektor widoku V powinniśmy użyć wektora </span><code>viewDirTS</code><span> (również należy go znormalizować). Jako wektora N użyj na razie wektora vec3(0,0,1).</span></li></ol></li></ol><p><span>Efekt finalny powinien wyglądać tak samo jak w przed jakąkolwiek zmianą. Następnym krokiem będzie wykorzystanie map normalnych</span></p><h3 id='iii2-wykorzystaj-normalmapy'><span>III.2 Wykorzystaj normalmapy</span></h3><ol start='' ><li><span>Chcemy wczytywać normalne z tekstury, w tym celu dodaj we </span><strong><span>fragment shaderze</span></strong><span> dodatkowy sampler do czytania map normalnych, nazwij go </span><code>normalSampler</code><span>. Pobierz z niego wektor normalny analogicznie, jak czytamy kolor zwykłej tekstury z samplera </span><code>textureSampler</code><span> i zapisz go w zmiennej </span><code>N</code><span>.</span></li><li><span>Ponieważ w teksturze wartości są w przedziale [0,1], musimy jeszcze przekształcić je do przedziału [-1,1]. W tym celu przemnóż wektor N przez 2 i odejmij 1.</span>
<span>Na koniec warto jeszcze znormalizować wektor normalny, aby uniknąć błędów związanych z precyzja lub kompresja tekstury.</span></li><li><span>Wczytaj pliki zawierające mapy normalnych w kodzie C++ W tym celu załaduj przy użyciu funkcji </span><code>Core::LoadTexture</code><span> mapy normalnych dla wszystkich modeli. Maja one taką sama nazwę jak zwykle tekstury, tyle ze z suffiksem &quot;_normals&quot;.</span></li><li><span>Zmodyfikuj na koniec funkcje </span><code>drawObjectTexture</code><span>. Dodaj do niej nowy argument </span><code>GLuint normalmapId</code><span>, który będzie służył do przekazywania id tekstury zawierającej mapę normalnych. Przy użyciu funkcji </span><code>Core::SetActiveTexture</code><span> załaduj </span><code>normalmapId</code><span> jako </span><code>normalSampler</code><span> i ustaw jednostkę teksturowania nr 1.</span>
<span>Argument odpowiadający za normalne w w miejscach wywołania funkcji </span><code>drawObjectTexture</code><span>.</span></li></ol><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p></div></div>
</body>
</html>