├── .gitignore ├── README.md ├── data_prep ├── pop2018.tsv ├── population_2018.json ├── process_data.py └── value_labels.json ├── gtag_fix.py ├── images ├── bumpy.jpeg ├── dd.jpeg ├── dnb_land_ocean_ice.2012.3600x1800.jpg ├── dot.png ├── europe.png ├── f.png ├── fathom.png ├── fathom_w_guides.png ├── home.jpg ├── nasa_blue_marble.4096.jpg ├── rust.jpg ├── trianglefan.png ├── trianglestrip.png └── world.png ├── index.html ├── server.tool ├── shader_01 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_02.0 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_02.1 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_02.2 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_02.3 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_03.0 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_03.1 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_03.2 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_03.3 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_03.4 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_04.0 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_04.1 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_04.2 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_04.3 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_04.4 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_04.5 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_04.6 ├── frag.glsl ├── index.html ├── main.js └── vert.glsl ├── shader_05.0 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_05.1 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_05.2 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_05.3 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_05.4 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_06.0 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js └── vert.glsl ├── shader_06.1 ├── index.html ├── main.js └── population_2018.json └── shader_06.2 ├── frag.glsl ├── gl-matrix-min.js ├── index.html ├── main.js ├── population_2018.json └── vert.glsl /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Intro to Shaders 2 | 3 | This repository is a light introduction to the capabilities of WebGL shaders, as well as some of the complexities of working with them. This set of examples was initially developed for an internal workshop at Fathom Information Design, and is tailored for an audience with a wide range of coding experience. Learn more here. 4 | 5 | The examples get progressively more complex, starting with the basics of textures and images, and evolving to 3D shapes and representing data. As the examples progress, changes are flagged with a comment that reads "New:". 6 | 7 | Browsing and reading the examples can help you appreciate shaders, but if you are comfortable with some light code editing, you are strongly encouraged to edit each of them as you go. They are set up so that you can comment out and uncomment in different features and behaviors as you go. 8 | 9 | Also included is a little python webserver. If you have python on your system, you should be able to run the server.tool. It will launch a little webserver and show the examples in your browser of choice. Assuming that browser is WebGL enabled, you should be good to go. 10 | 11 | 12 | ## License 13 | ``` 14 | The MIT License (MIT) 15 | 16 | Copyright (c) 2018 Fathom Information Design 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy 19 | of this software and associated documentation files (the "Software"), to deal 20 | in the Software without restriction, including without limitation the rights 21 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | copies of the Software, and to permit persons to whom the Software is 23 | furnished to do so, subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in all 26 | copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | SOFTWARE. 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /data_prep/pop2018.tsv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Index Region, subregion, country or area Urban Rural Total ISO3 6 | 15 Burundi 1 462 9 755 11 216 BDI 7 | 16 Comoros 241 591 832 COM 8 | 17 Djibouti 756 216 971 DJI 9 | 18 Eritrea 2 079 3 109 5 188 ERI 10 | 19 Ethiopia 22 328 85 207 107 535 ETH 11 | 20 Kenya 13 772 37 179 50 951 KEN 12 | 21 Madagascar 9 767 16 496 26 263 MDG 13 | 22 Malawi 3 246 15 919 19 165 MWI 14 | 23 Mauritius 517 751 1 268 MUS 15 | 24 Mayotte 120 140 260 MYT 16 | 25 Mozambique 10 987 19 542 30 529 MOZ 17 | 26 Réunion 879 4 883 REU 18 | 27 Rwanda 2 152 10 350 12 501 RWA 19 | 28 Seychelles 54 41 95 SYC 20 | 29 Somalia 6 827 8 355 15 182 SOM 21 | 30 South Sudan 2 534 10 385 12 919 SSD 22 | 31 Uganda 10 525 33 745 44 271 UGA 23 | 32 United Republic of Tanzania 19 959 39 133 59 091 TZA 24 | 33 Zambia 7 664 9 946 17 609 ZMB 25 | 34 Zimbabwe 5 448 11 466 16 913 ZWE 26 | 36 Angola 20 162 10 613 30 774 AGO 27 | 37 Cameroon 13 912 10 766 24 678 CMR 28 | 38 Central African Republic 1 960 2 778 4 737 CAF 29 | 39 Chad 3 540 11 813 15 353 TCD 30 | 40 Congo 3 613 1 786 5 400 COG 31 | 41 Democratic Republic of the Congo 37 349 46 656 84 005 COD 32 | 42 Equatorial Guinea 948 366 1 314 GNQ 33 | 43 Gabon 1 848 220 2 068 GAB 34 | 44 Sao Tome and Principe 152 57 209 STP 35 | 46 Algeria 30 510 11 498 42 008 DZA 36 | 47 Egypt 42 438 56 938 99 376 EGY 37 | 48 Libya 5 183 1 288 6 471 LBY 38 | 49 Morocco 22 603 13 589 36 192 MAR 39 | 50 Sudan 14 380 27 131 41 512 SDN 40 | 51 Tunisia 8 038 3 621 11 659 TUN 41 | 52 Western Sahara 492 76 567 ESH 42 | 54 Botswana 1 620 713 2 333 BWA 43 | 55 Lesotho 637 1 626 2 263 LSO 44 | 56 Namibia 1 295 1 293 2 588 NAM 45 | 57 South Africa 38 087 19 312 57 398 ZAF 46 | 58 Swaziland 331 1 060 1 391 SWZ 47 | 60 Benin 5 434 6 052 11 486 BEN 48 | 61 Burkina Faso 5 799 13 953 19 752 BFA 49 | 62 Cabo Verde 364 190 553 CPV 50 | 63 Côte d'Ivoire 12 647 12 259 24 906 CIV 51 | 64 Gambia 1 326 838 2 164 GMB 52 | 65 Ghana 16 517 12 946 29 464 GHA 53 | 66 Guinea 4 717 8 335 13 053 GIN 54 | 67 Guinea-Bissau 827 1 080 1 907 GNB 55 | 68 Liberia 2 483 2 371 4 854 LBR 56 | 69 Mali 8 093 11 014 19 108 MLI 57 | 70 Mauritania 2 437 2 103 4 540 MRT 58 | 71 Niger 3 665 18 647 22 311 NER 59 | 72 Nigeria 98 611 97 264 195 875 NGA 60 | 73 Saint Helena 2 2 4 SHN 61 | 74 Senegal 7 690 8 605 16 294 SEN 62 | 75 Sierra Leone 3 247 4 473 7 720 SLE 63 | 76 Togo 3 332 4 659 7 991 TGO 64 | 79 China 837 022 578 024 1 415 046 CHN 65 | 80 China, Hong Kong SAR 7 429 0 7 429 HKG 66 | 81 China, Macao SAR 632 0 632 MAC 67 | 82 China, Taiwan Province of China 18 518 5 176 23 694 TWN 68 | 83 Dem. People's Republic of Korea 15 853 9 758 25 611 PRK 69 | 84 Japan 116 522 10 664 127 185 JPN 70 | 85 Mongolia 2 137 985 3 122 MNG 71 | 86 Republic of Korea 41 678 9 486 51 164 KOR 72 | 89 Kazakhstan 10 569 7 835 18 404 KAZ 73 | 90 Kyrgyzstan 2 229 3 904 6 133 KGZ 74 | 91 Tajikistan 2 471 6 636 9 107 TJK 75 | 92 Turkmenistan 3 019 2 832 5 851 TKM 76 | 93 Uzbekistan 16 337 16 028 32 365 UZB 77 | 95 Afghanistan 9 273 27 100 36 373 AFG 78 | 96 Bangladesh 60 944 105 424 166 368 BGD 79 | 97 Bhutan 334 483 817 BTN 80 | 98 India 460 780 893 272 1 354 052 IND 81 | 99 Iran (Islamic Republic of) 61 425 20 587 82 012 IRN 82 | 100 Maldives 177 267 444 MDV 83 | 101 Nepal 5 848 23 776 29 624 NPL 84 | 102 Pakistan 73 630 127 183 200 814 PAK 85 | 103 Sri Lanka 3 871 17 079 20 950 LKA 86 | 105 Brunei Darussalam 337 97 434 BRN 87 | 106 Cambodia 3 800 12 446 16 246 KHM 88 | 107 Indonesia 147 603 119 192 266 795 IDN 89 | 108 Lao People's Democratic Republic 2 437 4 524 6 961 LAO 90 | 109 Malaysia 24 364 7 679 32 042 MYS 91 | 110 Myanmar 16 468 37 387 53 856 MMR 92 | 111 Philippines 49 962 56 550 106 512 PHL 93 | 112 Singapore 5 792 0 5 792 SGP 94 | 113 Thailand 34 556 34 627 69 183 THA 95 | 114 Timor-Leste 405 919 1 324 TLS 96 | 115 Viet Nam 34 659 61 832 96 491 VNM 97 | 117 Armenia 1 853 1 081 2 934 ARM 98 | 118 Azerbaijan 5 526 4 398 9 924 AZE 99 | 119 Bahrain 1 399 168 1 567 BHR 100 | 120 Cyprus 794 395 1 189 CYP 101 | 121 Georgia 2 291 1 616 3 907 GEO 102 | 122 Iraq 27 724 11 616 39 340 IRQ 103 | 123 Israel 7 812 641 8 453 ISR 104 | 124 Jordan 9 010 893 9 904 JOR 105 | 125 Kuwait 4 197 0 4 197 KWT 106 | 126 Lebanon 5 398 695 6 094 LBN 107 | 127 Oman 4 083 747 4 830 OMN 108 | 128 Qatar 2 672 23 2 695 QAT 109 | 129 Saudi Arabia 28 133 5 421 33 554 SAU 110 | 130 State of Palestine 3 848 1 204 5 053 PSE 111 | 131 Syrian Arab Republic 9 903 8 381 18 284 SYR 112 | 132 Turkey 61 555 20 362 81 917 TUR 113 | 133 United Arab Emirates 8 256 1 286 9 542 ARE 114 | 134 Yemen 10 595 18 320 28 915 YEM 115 | 137 Belarus 7 429 2 023 9 452 BLR 116 | 138 Bulgaria 5 278 1 759 7 037 BGR 117 | 139 Czechia 7 841 2 785 10 625 CZE 118 | 140 Hungary 6 913 2 776 9 689 HUN 119 | 141 Poland 22 885 15 220 38 105 POL 120 | 142 Republic of Moldova 1 723 2 318 4 041 MDA 121 | 143 Romania 10 573 9 008 19 581 ROU 122 | 144 Russian Federation 107 157 36 808 143 965 RUS 123 | 145 Slovakia 2 928 2 522 5 450 SVK 124 | 146 Ukraine 30 521 13 488 44 009 UKR 125 | 148 Channel Islands 51 115 166 CHI 126 | 149 Denmark 5 057 698 5 754 DNK 127 | 150 Estonia 900 407 1 307 EST 128 | 151 Faeroe Islands 21 29 49 FRO 129 | 152 Finland 4 732 810 5 543 FIN 130 | 153 Iceland 317 21 338 ISL 131 | 154 Ireland 3 035 1 769 4 804 IRL 132 | 155 Isle of Man 45 40 85 IMN 133 | 156 Latvia 1 315 615 1 930 LVA 134 | 157 Lithuania 1 947 930 2 876 LTU 135 | 158 Norway 4 403 950 5 353 NOR 136 | 159 Sweden 8 728 1 255 9 983 SWE 137 | 160 United Kingdom 55 521 11 052 66 574 GBR 138 | 162 Albania 1 770 1 164 2 934 ALB 139 | 163 Andorra 68 9 77 AND 140 | 164 Bosnia and Herzegovina 1 690 1 813 3 504 BIH 141 | 165 Croatia 2 372 1 793 4 165 HRV 142 | 166 Gibraltar 35 0 35 GIB 143 | 167 Greece 8 809 2 333 11 142 GRC 144 | 168 Holy See 1 0 1 VAT 145 | 169 Italy 41 763 17 528 59 291 ITA 146 | 170 Malta 409 23 432 MLT 147 | 171 Montenegro 420 209 629 MNE 148 | 172 Portugal 6 711 3 580 10 291 PRT 149 | 173 San Marino 33 1 34 SMR 150 | 174 Serbia 4 915 3 847 8 762 SRB 151 | 175 Slovenia 1 135 946 2 081 SVN 152 | 176 Spain 37 267 9 130 46 397 ESP 153 | 177 TFYR Macedonia 1 209 876 2 085 MKD 154 | 179 Austria 5 102 3 650 8 752 AUT 155 | 180 Belgium 11 269 230 11 499 BEL 156 | 181 France 52 476 12 757 65 233 FRA 157 | 182 Germany 63 622 18 671 82 293 DEU 158 | 183 Liechtenstein 5 33 38 LIE 159 | 184 Luxembourg 537 53 590 LUX 160 | 185 Monaco 39 0 39 MCO 161 | 186 Netherlands 15 631 1 454 17 084 NLD 162 | 187 Switzerland 6 305 2 239 8 544 CHE 163 | 190 Anguilla 15 0 15 AIA 164 | 191 Antigua and Barbuda 25 78 103 ATG 165 | 192 Aruba 46 60 106 ABW 166 | 193 Bahamas 332 68 399 BHS 167 | 194 Barbados 89 197 286 BRB 168 | 195 British Virgin Islands 15 17 32 VGB 169 | 196 Caribbean Netherlands 19 6 26 BES 170 | 197 Cayman Islands 62 0 62 CYM 171 | 198 Cuba 8 851 2 638 11 489 CUB 172 | 199 Curaçao 144 18 162 CUW 173 | 200 Dominica 52 22 74 DMA 174 | 201 Dominican Republic 8 823 2 060 10 883 DOM 175 | 202 Grenada 39 69 108 GRD 176 | 203 Guadeloupe 442 7 449 GLP 177 | 204 Haiti 6 143 4 970 11 113 HTI 178 | 205 Jamaica 1 614 1 285 2 899 JAM 179 | 206 Martinique 343 42 385 MTQ 180 | 207 Montserrat 0 5 5 MSR 181 | 208 Puerto Rico 3 424 235 3 659 PRI 182 | 209 Saint Kitts and Nevis 17 39 56 KNA 183 | 210 Saint Lucia 34 146 180 LCA 184 | 211 Saint Vincent and the Grenadines 58 53 110 VCT 185 | 212 Sint Maarten (Dutch part) 41 0 41 SXM 186 | 213 Trinidad and Tobago 730 643 1 373 TTO 187 | 214 Turks and Caicos Islands 33 2 36 TCA 188 | 215 United States Virgin Islands 100 4 105 VIR 189 | 217 Belize 175 208 382 BLZ 190 | 218 Costa Rica 3 930 1 023 4 953 CRI 191 | 219 El Salvador 4 618 1 794 6 412 SLV 192 | 220 Guatemala 8 804 8 441 17 245 GTM 193 | 221 Honduras 5 377 4 040 9 417 HND 194 | 222 Mexico 104 811 25 948 130 759 MEX 195 | 223 Nicaragua 3 678 2 607 6 285 NIC 196 | 224 Panama 2 818 1 344 4 163 PAN 197 | 226 Argentina 41 056 3 633 44 689 ARG 198 | 227 Bolivia (Plurinational State of) 7 786 3 429 11 216 BOL 199 | 228 Brazil 182 546 28 321 210 868 BRA 200 | 229 Chile 15 934 2 263 18 197 CHL 201 | 230 Colombia 39 956 9 508 49 465 COL 202 | 231 Ecuador 10 762 6 101 16 863 ECU 203 | 232 Falkland Islands (Malvinas) 2 1 3 FLK 204 | 233 French Guiana 247 43 290 GUF 205 | 234 Guyana 208 574 782 GUY 206 | 235 Paraguay 4 247 2 649 6 897 PRY 207 | 236 Peru 25 360 7 192 32 552 PER 208 | 237 Suriname 375 193 568 SUR 209 | 238 Uruguay 3 308 162 3 470 URY 210 | 239 Venezuela (Bolivarian Republic of) 28 563 3 819 32 381 VEN 211 | 241 Bermuda 61 0 61 BMU 212 | 242 Canada 30 084 6 869 36 954 CAN 213 | 243 Greenland 49 7 57 GRL 214 | 244 Saint Pierre and Miquelon 6 1 6 SPM 215 | 245 United States of America 268 787 57 980 326 767 USA 216 | 248 Australia 21 307 3 465 24 772 AUS 217 | 249 New Zealand 4 110 639 4 750 NZL 218 | 251 Fiji 513 399 912 FJI 219 | 252 New Caledonia 198 82 280 NCL 220 | 253 Papua New Guinea 1 109 7 310 8 418 PNG 221 | 254 Solomon Islands 148 475 623 SLB 222 | 255 Vanuatu 71 211 282 VUT 223 | 257 Guam 157 9 166 GUM 224 | 258 Kiribati 64 54 118 KIR 225 | 259 Marshall Islands 41 12 53 MHL 226 | 260 Micronesia (Fed. States of) 24 82 106 FSM 227 | 261 Nauru 11 0 11 NRU 228 | 262 Northern Mariana Islands 51 5 55 MNP 229 | 263 Palau 18 4 22 PLW 230 | 265 American Samoa 49 7 56 ASM 231 | 266 Cook Islands 13 4 17 COK 232 | 267 French Polynesia 177 109 286 PYF 233 | 268 Niue 1 1 2 NIU 234 | 269 Samoa 36 162 198 WSM 235 | 270 Tokelau 0 1 1 TKL 236 | 271 Tonga 25 84 109 TON 237 | 272 Tuvalu 7 4 11 TUV 238 | 273 Wallis and Futuna Islands 0 12 12 WLF 239 | -------------------------------------------------------------------------------- /data_prep/process_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import json 4 | 5 | f = open('pop2018.tsv', 'r') 6 | lookup = {} 7 | for line in f.readlines(): 8 | tokens = line.strip().split("\t") 9 | if len(tokens) > 4: 10 | name = tokens[1].strip() 11 | try: 12 | urban = int(tokens[2].replace(' ', '')) 13 | rural = int(tokens[3].replace(' ', '')) 14 | total = int(tokens[4].replace(' ', '')) 15 | iso3 = tokens[5].strip() 16 | # print(iso3, total, name) 17 | lookup[iso3] = [total, urban, rural, name] 18 | except ValueError: 19 | print("Error: ", line.strip()) 20 | 21 | 22 | 23 | f = open('value_labels.json', 'r') 24 | jj = json.loads(f.read()) 25 | seq = jj['country'] 26 | labels = jj['countries'] 27 | backup_lookup = {} 28 | for item in labels: 29 | iso3 = item['iso3'] 30 | name = item['name'] 31 | if len(iso3) > 0: 32 | backup_lookup[iso3] = name 33 | 34 | countries_in_order = [] 35 | for code in seq: 36 | name = '' 37 | total = -1 38 | urban = -1 39 | rural = -1 40 | if code in lookup: 41 | item = lookup[code] 42 | name = item[3] 43 | total = item[0] 44 | urban = item[1] 45 | rural = item[2] 46 | elif code in backup_lookup: 47 | name = backup_lookup[code] 48 | countries_in_order.append({ 49 | "name" : name, 50 | "total" : total, 51 | "urban" : urban, 52 | "rural" : rural 53 | }) 54 | 55 | s = json.dumps(countries_in_order) 56 | f = open('population_2018.json', 'w') 57 | f.write(s) 58 | f.close() -------------------------------------------------------------------------------- /gtag_fix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | import os 4 | 5 | SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 6 | 7 | TAG = """ 8 | 9 | 10 | 17 | """ 18 | 19 | # def find_all(name, path): 20 | # result = [] 21 | # for root, dirs, files in os.walk(path): 22 | # if name in files: 23 | # result.append(os.path.join(root, name)) 24 | # return result 25 | 26 | 27 | 28 | indices = os.popen('find %s -name index.html' % (SCRIPT_DIR)).readlines() 29 | indices = [f.strip() for f in indices] 30 | 31 | for fname in indices: 32 | f = open(fname) 33 | lines = f.readlines() 34 | f.close() 35 | 36 | needs_analytics = True 37 | style_end_tag_line = -1 38 | for i, l in enumerate(lines): 39 | if "www.googletagmanager.com" in l: 40 | needs_analytics = False 41 | elif "" in l: 42 | style_end_tag_line = i 43 | 44 | if needs_analytics: 45 | print("tagging %s" % (fname)) 46 | lines.insert(style_end_tag_line + 1, TAG) 47 | f = open(fname, 'w') 48 | f.write("".join(lines)) 49 | f.close() 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /images/bumpy.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/bumpy.jpeg -------------------------------------------------------------------------------- /images/dd.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/dd.jpeg -------------------------------------------------------------------------------- /images/dnb_land_ocean_ice.2012.3600x1800.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/dnb_land_ocean_ice.2012.3600x1800.jpg -------------------------------------------------------------------------------- /images/dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/dot.png -------------------------------------------------------------------------------- /images/europe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/europe.png -------------------------------------------------------------------------------- /images/f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/f.png -------------------------------------------------------------------------------- /images/fathom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/fathom.png -------------------------------------------------------------------------------- /images/fathom_w_guides.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/fathom_w_guides.png -------------------------------------------------------------------------------- /images/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/home.jpg -------------------------------------------------------------------------------- /images/nasa_blue_marble.4096.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/nasa_blue_marble.4096.jpg -------------------------------------------------------------------------------- /images/rust.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/rust.jpg -------------------------------------------------------------------------------- /images/trianglefan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/trianglefan.png -------------------------------------------------------------------------------- /images/trianglestrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/trianglestrip.png -------------------------------------------------------------------------------- /images/world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fathominfo/intro-to-shaders/d0fe9f2d2cc02d5911e76eeaa67f40e573083821/images/world.png -------------------------------------------------------------------------------- /server.tool: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | import os 4 | import sys 5 | 6 | from random import randint 7 | 8 | from BaseHTTPServer import HTTPServer 9 | from SimpleHTTPServer import SimpleHTTPRequestHandler 10 | from SocketServer import ThreadingMixIn 11 | 12 | class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 13 | pass 14 | 15 | port = randint(8000, 9000) 16 | dir = os.path.dirname(os.path.realpath(__file__)) 17 | os.chdir(dir) 18 | 19 | url = 'http://localhost:%s/%s' % (port, 'index.html') 20 | print "serving at %s" % (url) 21 | os.system('open ' + url) 22 | 23 | server_address = ('', port) 24 | httpd = ThreadedHTTPServer(server_address, SimpleHTTPRequestHandler) 25 | httpd.serve_forever() 26 | -------------------------------------------------------------------------------- /shader_01/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | // this function gets called for each pixel within the shape we set up 6 | // in the vertex shader 7 | void main(){ 8 | // assigning to gl_FragColor sets the color for this pixel 9 | gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); 10 | } -------------------------------------------------------------------------------- /shader_01/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_01/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | frameCount = 0, 8 | 9 | positionLocation; 10 | 11 | // make the canvas fill the window 12 | canvas.width = W; 13 | canvas.height = H; 14 | 15 | 16 | 17 | function initGLData() { 18 | // now we can get some config info 19 | gl.viewport(0, 0, W, H); 20 | // Even though we aren't drawing anything really fancy, 21 | // we have to tell the GL Context how much of the screen we are drawing 22 | positionLocation = gl.getAttribLocation(program, "a_position"); 23 | gl.enableVertexAttribArray(positionLocation); 24 | var buffer = gl.createBuffer(); 25 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 26 | gl.bufferData( 27 | gl.ARRAY_BUFFER, 28 | /** 29 | note that unlike processing or canvas.getContext('2d'), 30 | the screen coordinates are 31 | -1, 1 left to right 32 | 1, -1 top to bottom 33 | and 0, 0 is the center 34 | and because GL is finicky, you have to specify them as floats, 35 | not ints, so add that '.0' to the end 36 | */ 37 | new Float32Array([ 38 | -1.0, 1.0, 39 | 1.0, 1.0, 40 | -1.0, -1.0, 41 | 1.0, -1.0]), 42 | gl.STATIC_DRAW 43 | ); 44 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 45 | } 46 | 47 | 48 | 49 | 50 | function draw() { 51 | // Set clear color to black, fully opaque 52 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 53 | // Clear the color buffer with specified clear color 54 | gl.clear(gl.COLOR_BUFFER_BIT); 55 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 56 | } 57 | 58 | 59 | 60 | 61 | 62 | 63 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 64 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 65 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 66 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 67 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 68 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 69 | 70 | 71 | // load files 72 | fetch('frag.glsl') 73 | .then(function(response) { 74 | return response.text(); 75 | }).then(fragShaderText=>{ 76 | // console.log(fragShaderText) 77 | fetch('vert.glsl') 78 | .then(function(response) { 79 | return response.text(); 80 | }).then(vertShaderText=>{ 81 | // console.log(vertShaderText); 82 | compileGL(fragShaderText, vertShaderText); 83 | initGLData(); 84 | requestDraw(); 85 | }); 86 | }); 87 | 88 | 89 | 90 | // build our program 91 | function compileGL(fragShaderText, vertShaderText) { 92 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 93 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 94 | program = gl.createProgram(); 95 | gl.attachShader(program, vert); 96 | gl.attachShader(program, frag); 97 | gl.linkProgram(program); 98 | gl.useProgram(program); 99 | } 100 | 101 | function requestDraw() { 102 | requestAnimationFrame(draw); 103 | } 104 | 105 | // straight outta mozilla 106 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 107 | function loadShader(gl, type, source) { 108 | const shader = gl.createShader(type); 109 | // Send the source to the shader object 110 | gl.shaderSource(shader, source); 111 | // Compile the shader program 112 | gl.compileShader(shader); 113 | // See if it compiled successfully 114 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 115 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 116 | gl.deleteShader(shader); 117 | return null; 118 | } 119 | return shader; 120 | } 121 | 122 | 123 | })(); 124 | 125 | -------------------------------------------------------------------------------- /shader_01/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_02.0/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | 7 | // this function gets called for each pixel within the shape we set up 8 | // in the vertex shader 9 | void main(){ 10 | // instead of raw time, we will make a nice loop by taking the sine 11 | // of the elapsed time. Keep it above 0 with abs() 12 | float t = abs(sin(u_time / 1000.0)); 13 | gl_FragColor = vec4(t, 0.0, 1.0, 1.0); 14 | } -------------------------------------------------------------------------------- /shader_02.0/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_02.0/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | // New: our shader will change over time, so we need to know when it starts 8 | startTime, 9 | 10 | // New: we will pass the elapsed time to the shader 11 | // so we need to know where the shader wants us to put it. 12 | timeUniformLocation, 13 | positionLocation; 14 | 15 | // make the canvas fill the window 16 | canvas.width = W; 17 | canvas.height = H; 18 | 19 | function initGLData() { 20 | // now we can get some config info 21 | gl.viewport(0, 0, W, H); 22 | // New: so this is where we will put the elpased time in our draw function 23 | timeUniformLocation = gl.getUniformLocation(program, "u_time"); 24 | 25 | // Even though we aren't drawing anything really fancy, 26 | // we have to tell the GL Context how much of the screen we are drawing 27 | positionLocation = gl.getAttribLocation(program, "a_position"); 28 | gl.enableVertexAttribArray(positionLocation); 29 | var buffer = gl.createBuffer(); 30 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 31 | gl.bufferData( 32 | gl.ARRAY_BUFFER, 33 | /** 34 | note that unlike processing or canvas.getContext('2d'), 35 | the screen coordinates are 36 | -1, 1 left to right 37 | 1, -1 top to bottom 38 | and 0, 0 is the center 39 | and because GL is finicky, you have to specify them as floats, 40 | not ints, so add that '.0' to the end 41 | */ 42 | new Float32Array([ 43 | -1.0, 1.0, 44 | 1.0, 1.0, 45 | -1.0, -1.0, 46 | 1.0, -1.0]), 47 | gl.STATIC_DRAW 48 | ); 49 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 50 | } 51 | 52 | 53 | function draw() { 54 | // Set clear color to black, fully opaque 55 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 56 | // Clear the color buffer with specified clear color 57 | gl.clear(gl.COLOR_BUFFER_BIT); 58 | // New: calculate how much time has passed, and pass it to the shader 59 | var elapsed = Date.now() - startTime; 60 | gl.uniform1f(timeUniformLocation, elapsed); 61 | // console.log(elapsed / 100.0) 62 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 63 | } 64 | 65 | 66 | 67 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 68 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 69 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 70 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 71 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 72 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 73 | 74 | 75 | // load files 76 | fetch('frag.glsl') 77 | .then(function(response) { 78 | return response.text(); 79 | }).then(fragShaderText=>{ 80 | // console.log(fragShaderText) 81 | fetch('vert.glsl') 82 | .then(function(response) { 83 | return response.text(); 84 | }).then(vertShaderText=>{ 85 | // console.log(vertShaderText); 86 | compileGL(fragShaderText, vertShaderText); 87 | initGLData(); 88 | // New: instead of just drawing once, 89 | // we track the start time and call the draw loop every 30 milliseconds 90 | // roughly 30 times a second 91 | startTime = Date.now(); 92 | setInterval(requestDraw, 33); 93 | }); 94 | }); 95 | 96 | 97 | 98 | // build our program 99 | function compileGL(fragShaderText, vertShaderText) { 100 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 101 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 102 | program = gl.createProgram(); 103 | gl.attachShader(program, vert); 104 | gl.attachShader(program, frag); 105 | gl.linkProgram(program); 106 | gl.useProgram(program); 107 | } 108 | 109 | function requestDraw() { 110 | requestAnimationFrame(draw); 111 | } 112 | 113 | // straight outta mozilla 114 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 115 | function loadShader(gl, type, source) { 116 | const shader = gl.createShader(type); 117 | // Send the source to the shader object 118 | gl.shaderSource(shader, source); 119 | // Compile the shader program 120 | gl.compileShader(shader); 121 | // See if it compiled successfully 122 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 123 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 124 | gl.deleteShader(shader); 125 | return null; 126 | } 127 | return shader; 128 | } 129 | 130 | 131 | 132 | })(); 133 | 134 | -------------------------------------------------------------------------------- /shader_02.0/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_02.1/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | // New: the screen resolution 6 | uniform vec2 u_resolution; 7 | 8 | // this function gets called for each pixel within the shape we set up 9 | // in the vertex shader 10 | void main(){ 11 | // assigning to gl_FragColor sets the color for this pixel 12 | // New: the screen resolution 13 | // the shader space is in 0-1, but we want to color each pixel according to a gradient. 14 | // So we need to rescale the coordinate space by the screen resolution 15 | vec2 st = gl_FragCoord.xy/u_resolution; 16 | gl_FragColor = vec4(0.0, st.x, st.y, 1.0); 17 | } -------------------------------------------------------------------------------- /shader_02.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_02.1/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | // New: we have a new global variable that represents the screen size 9 | resolutionUniformLocation, 10 | positionLocation; 11 | 12 | // make the canvas fill the window 13 | canvas.width = W; 14 | canvas.height = H; 15 | 16 | function initGLData() { 17 | // now we can get some config info 18 | gl.viewport(0, 0, W, H); 19 | // New: just where does the shader store the information about screen resolution? 20 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 21 | // New: pass in the width and height of the canvas so we can use it in the shader 22 | gl.uniform2f(resolutionUniformLocation, W, H); 23 | 24 | // Even though we aren't drawing anything really fancy, 25 | // we have to tell the GL Context how much of the screen we are drawing 26 | positionLocation = gl.getAttribLocation(program, "a_position"); 27 | gl.enableVertexAttribArray(positionLocation); 28 | var buffer = gl.createBuffer(); 29 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 30 | gl.bufferData( 31 | gl.ARRAY_BUFFER, 32 | /** 33 | note that unlike processing or canvas.getContext('2d'), 34 | the screen coordinates are 35 | -1, 1 left to right 36 | 1, -1 top to bottom 37 | and 0, 0 is the center 38 | and because GL is finicky, you have to specify them as floats, 39 | not ints, so add that '.0' to the end 40 | */ 41 | new Float32Array([ 42 | -1.0, 1.0, 43 | 1.0, 1.0, 44 | -1.0, -1.0, 45 | 1.0, -1.0]), 46 | gl.STATIC_DRAW 47 | ); 48 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 49 | } 50 | 51 | 52 | function draw() { 53 | // Set clear color to black, fully opaque 54 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 55 | // Clear the color buffer with specified clear color 56 | gl.clear(gl.COLOR_BUFFER_BIT); 57 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 58 | } 59 | 60 | 61 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 62 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 63 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 64 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 65 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 66 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 67 | 68 | 69 | // load files 70 | fetch('frag.glsl') 71 | .then(function(response) { 72 | return response.text(); 73 | }).then(fragShaderText=>{ 74 | // console.log(fragShaderText) 75 | fetch('vert.glsl') 76 | .then(function(response) { 77 | return response.text(); 78 | }).then(vertShaderText=>{ 79 | // console.log(vertShaderText); 80 | compileGL(fragShaderText, vertShaderText); 81 | initGLData(); 82 | startTime = Date.now(); 83 | setInterval(requestDraw, 33); 84 | }); 85 | }); 86 | 87 | 88 | 89 | // build our program 90 | function compileGL(fragShaderText, vertShaderText) { 91 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 92 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 93 | program = gl.createProgram(); 94 | gl.attachShader(program, vert); 95 | gl.attachShader(program, frag); 96 | gl.linkProgram(program); 97 | gl.useProgram(program); 98 | } 99 | 100 | function requestDraw() { 101 | requestAnimationFrame(draw); 102 | } 103 | 104 | // straight outta mozilla 105 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 106 | function loadShader(gl, type, source) { 107 | const shader = gl.createShader(type); 108 | // Send the source to the shader object 109 | gl.shaderSource(shader, source); 110 | // Compile the shader program 111 | gl.compileShader(shader); 112 | // See if it compiled successfully 113 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 114 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 115 | gl.deleteShader(shader); 116 | return null; 117 | } 118 | return shader; 119 | } 120 | 121 | 122 | })(); 123 | 124 | -------------------------------------------------------------------------------- /shader_02.1/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_02.2/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform vec2 u_resolution; 6 | // New: the mouse position 7 | uniform vec2 u_mouse; 8 | 9 | void main(){ 10 | vec2 st = gl_FragCoord.xy/u_resolution; 11 | // New: the mouse position 12 | vec2 mouse = u_mouse/u_resolution; 13 | // draw something differnt on the left and right sides of the mouse 14 | if (st.x < mouse.x) { 15 | gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); 16 | } else { 17 | gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /shader_02.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_02.2/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | // New: track the mouse position, and pass it to the shader 9 | mouseX, mouseY, 10 | mouseUniformLocation, 11 | 12 | resolutionUniformLocation, 13 | positionLocation; 14 | 15 | // make the canvas fill the window 16 | canvas.width = W; 17 | canvas.height = H; 18 | 19 | 20 | function initGLData() { 21 | // now we can get some config info 22 | gl.viewport(0, 0, W, H); 23 | // New: just where does the shader track the mouse position? 24 | mouseUniformLocation = gl.getUniformLocation(program, "u_mouse"); 25 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 26 | 27 | gl.uniform2f(resolutionUniformLocation, W, H); 28 | 29 | // Even though we aren't drawing anything really fancy, 30 | // we have to tell the GL Context how much of the screen we are drawing 31 | positionLocation = gl.getAttribLocation(program, "a_position"); 32 | gl.enableVertexAttribArray(positionLocation); 33 | var buffer = gl.createBuffer(); 34 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 35 | gl.bufferData( 36 | gl.ARRAY_BUFFER, 37 | /** 38 | note that unlike processing or canvas.getContext('2d'), 39 | the screen coordinates are 40 | -1, 1 left to right 41 | 1, -1 top to bottom 42 | and 0, 0 is the center 43 | and because GL is finicky, you have to specify them as floats, 44 | not ints, so add that '.0' to the end 45 | */ 46 | new Float32Array([ 47 | -1.0, 1.0, 48 | 1.0, 1.0, 49 | -1.0, -1.0, 50 | 1.0, -1.0]), 51 | gl.STATIC_DRAW 52 | ); 53 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 54 | } 55 | 56 | 57 | function draw() { 58 | // Set clear color to black, fully opaque 59 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 60 | // Clear the color buffer with specified clear color 61 | gl.clear(gl.COLOR_BUFFER_BIT); 62 | gl.uniform2f(mouseUniformLocation, mouseX, mouseY); 63 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 64 | } 65 | 66 | 67 | 68 | 69 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 70 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 71 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 72 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 73 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 74 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 75 | 76 | 77 | // load files 78 | fetch('frag.glsl') 79 | .then(function(response) { 80 | return response.text(); 81 | }).then(fragShaderText=>{ 82 | // console.log(fragShaderText) 83 | fetch('vert.glsl') 84 | .then(function(response) { 85 | return response.text(); 86 | }).then(vertShaderText=>{ 87 | // console.log(vertShaderText); 88 | compileGL(fragShaderText, vertShaderText); 89 | initGLData(); 90 | // New: track the mouse 91 | canvas.addEventListener('mousemove',(event) => { 92 | mouseX = event.offsetX; 93 | mouseY = event.offsetY; 94 | }); 95 | startTime = Date.now(); 96 | setInterval(requestDraw, 33); 97 | }); 98 | }); 99 | 100 | 101 | 102 | // build our program 103 | function compileGL(fragShaderText, vertShaderText) { 104 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 105 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 106 | program = gl.createProgram(); 107 | gl.attachShader(program, vert); 108 | gl.attachShader(program, frag); 109 | gl.linkProgram(program); 110 | gl.useProgram(program); 111 | } 112 | 113 | function requestDraw() { 114 | requestAnimationFrame(draw); 115 | } 116 | 117 | // straight outta mozilla 118 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 119 | function loadShader(gl, type, source) { 120 | const shader = gl.createShader(type); 121 | // Send the source to the shader object 122 | gl.shaderSource(shader, source); 123 | // Compile the shader program 124 | gl.compileShader(shader); 125 | // See if it compiled successfully 126 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 127 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 128 | gl.deleteShader(shader); 129 | return null; 130 | } 131 | return shader; 132 | } 133 | 134 | 135 | })(); 136 | 137 | -------------------------------------------------------------------------------- /shader_02.2/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_02.3/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | uniform vec2 u_resolution; 7 | uniform vec2 u_mouse; 8 | 9 | void main(){ 10 | vec2 st = gl_FragCoord.xy/u_resolution; 11 | // instead of raw time, we will make a nice loop by taking the sine 12 | // of the elapsed time. Keep it above 0 with abs() 13 | float t = u_time / 1000.0; 14 | vec2 mouse = u_mouse/u_resolution; 15 | // draw something different on the left and right sides of the mouse 16 | if (st.x < mouse.x) { 17 | gl_FragColor = vec4(abs(sin(t)), st.x, st.y, 1.0); 18 | } else { 19 | gl_FragColor = vec4(st.y, abs(sin(st.x)), abs(cos(t)), 1.0); 20 | } 21 | } -------------------------------------------------------------------------------- /shader_02.3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_02.3/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | mouseX, mouseY, 9 | 10 | mouseUniformLocation, 11 | resolutionUniformLocation, 12 | timeUniformLocation, 13 | positionLocation; 14 | 15 | // make the canvas fill the window 16 | canvas.width = W; 17 | canvas.height = H; 18 | 19 | function initGLData() { 20 | // now we can get some config info 21 | gl.viewport(0, 0, W, H); 22 | // New: just where does the shader track the mouse position? 23 | mouseUniformLocation = gl.getUniformLocation(program, "u_mouse"); 24 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 25 | timeUniformLocation = gl.getUniformLocation(program, "u_time"); 26 | 27 | gl.uniform2f(resolutionUniformLocation, W, H); 28 | 29 | // Even though we aren't drawing anything really fancy, 30 | // we have to tell the GL Context how much of the screen we are drawing 31 | positionLocation = gl.getAttribLocation(program, "a_position"); 32 | gl.enableVertexAttribArray(positionLocation); 33 | var buffer = gl.createBuffer(); 34 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 35 | gl.bufferData( 36 | gl.ARRAY_BUFFER, 37 | /** 38 | note that unlike processing or canvas.getContext('2d'), 39 | the screen coordinates are 40 | -1, 1 left to right 41 | 1, -1 top to bottom 42 | and 0, 0 is the center 43 | and because GL is finicky, you have to specify them as floats, 44 | not ints, so add that '.0' to the end 45 | */ 46 | new Float32Array([ 47 | -1.0, 1.0, 48 | 1.0, 1.0, 49 | -1.0, -1.0, 50 | 1.0, -1.0]), 51 | gl.STATIC_DRAW 52 | ); 53 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 54 | } 55 | 56 | 57 | function draw() { 58 | // Set clear color to black, fully opaque 59 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 60 | // Clear the color buffer with specified clear color 61 | gl.clear(gl.COLOR_BUFFER_BIT); 62 | var elapsed = Date.now() - startTime; 63 | gl.uniform1f(timeUniformLocation, elapsed); 64 | gl.uniform2f(mouseUniformLocation, mouseX, mouseY); 65 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 66 | } 67 | 68 | 69 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 70 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 71 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 72 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 73 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 74 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 75 | 76 | 77 | // load files 78 | fetch('frag.glsl') 79 | .then(function(response) { 80 | return response.text(); 81 | }).then(fragShaderText=>{ 82 | // console.log(fragShaderText) 83 | fetch('vert.glsl') 84 | .then(function(response) { 85 | return response.text(); 86 | }).then(vertShaderText=>{ 87 | // console.log(vertShaderText); 88 | compileGL(fragShaderText, vertShaderText); 89 | initGLData(); 90 | startTime = Date.now(); 91 | canvas.addEventListener('mousemove',(event) => { 92 | mouseX = event.offsetX; 93 | mouseY = event.offsetY; 94 | }); 95 | setInterval(requestDraw, 30); 96 | 97 | }); 98 | }); 99 | 100 | 101 | 102 | // build our program 103 | function compileGL(fragShaderText, vertShaderText) { 104 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 105 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 106 | program = gl.createProgram(); 107 | gl.attachShader(program, vert); 108 | gl.attachShader(program, frag); 109 | gl.linkProgram(program); 110 | gl.useProgram(program); 111 | } 112 | 113 | function requestDraw() { 114 | requestAnimationFrame(draw); 115 | } 116 | 117 | // straight outta mozilla 118 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 119 | function loadShader(gl, type, source) { 120 | const shader = gl.createShader(type); 121 | // Send the source to the shader object 122 | gl.shaderSource(shader, source); 123 | // Compile the shader program 124 | gl.compileShader(shader); 125 | // See if it compiled successfully 126 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 127 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 128 | gl.deleteShader(shader); 129 | return null; 130 | } 131 | return shader; 132 | } 133 | 134 | 135 | })(); 136 | 137 | -------------------------------------------------------------------------------- /shader_02.3/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_03.0/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | // New: the screen resolution 7 | uniform vec2 u_resolution; 8 | 9 | // this function gets called for each pixel within the shape we set up 10 | // in the vertex shader 11 | void main(){ 12 | // assigning to gl_FragColor sets the color for this pixel 13 | // New: the screen resolution 14 | // the shader space is in 0-1, but we want to color each pixel according to a gradient. 15 | // So we need to rescale the coordinate space by the screen resolution 16 | vec2 st = gl_FragCoord.xy/u_resolution; 17 | vec2 st2 = st * 10.0; 18 | st2 = fract(st2); 19 | // st2 = fract(st2) * 1.0/st; 20 | // if (mod(floor(st.x * 10.0),2.0) == 0.0) { 21 | // st2 = st * 30.0; 22 | // st2 = fract(st2); 23 | // // st2 = 1.0 - st2; 24 | // } 25 | gl_FragColor = vec4(0.0, st2.x, st2.y, 1.0); 26 | } -------------------------------------------------------------------------------- /shader_03.0/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_03.0/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | // we have a new global variable that represents the screen size 9 | resolutionUniformLocation, 10 | positionLocation; 11 | 12 | // make the canvas fill the window 13 | canvas.width = W; 14 | canvas.height = H; 15 | 16 | 17 | function initGLData() { 18 | // now we can get some config info 19 | gl.viewport(0, 0, W, H); 20 | // New: just where does the shader store the information about screen resolution? 21 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 22 | 23 | // New: pass in the width and height of the canvas so we can use it in the shader 24 | gl.uniform2f(resolutionUniformLocation, W, H); 25 | 26 | // Even though we aren't drawing anything really fancy, 27 | // we have to tell the GL Context how much of the screen we are drawing 28 | positionLocation = gl.getAttribLocation(program, "a_position"); 29 | gl.enableVertexAttribArray(positionLocation); 30 | var buffer = gl.createBuffer(); 31 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 32 | gl.bufferData( 33 | gl.ARRAY_BUFFER, 34 | /** 35 | note that unlike processing or canvas.getContext('2d'), 36 | the screen coordinates are 37 | -1, 1 left to right 38 | 1, -1 top to bottom 39 | and 0, 0 is the center 40 | and because GL is finicky, you have to specify them as floats, 41 | not ints, so add that '.0' to the end 42 | */ 43 | new Float32Array([ 44 | -1.0, 1.0, 45 | 1.0, 1.0, 46 | -1.0, -1.0, 47 | 1.0, -1.0]), 48 | gl.STATIC_DRAW 49 | ); 50 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 51 | } 52 | 53 | 54 | function draw() { 55 | // Set clear color to black, fully opaque 56 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 57 | // Clear the color buffer with specified clear color 58 | gl.clear(gl.COLOR_BUFFER_BIT); 59 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 60 | } 61 | 62 | 63 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 64 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 65 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 66 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 67 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 68 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 69 | 70 | 71 | // load files 72 | fetch('frag.glsl') 73 | .then(function(response) { 74 | return response.text(); 75 | }).then(fragShaderText=>{ 76 | // console.log(fragShaderText) 77 | fetch('vert.glsl') 78 | .then(function(response) { 79 | return response.text(); 80 | }).then(vertShaderText=>{ 81 | // console.log(vertShaderText); 82 | compileGL(fragShaderText, vertShaderText); 83 | initGLData(); 84 | requestDraw(); 85 | }); 86 | }); 87 | 88 | 89 | 90 | // build our program 91 | function compileGL(fragShaderText, vertShaderText) { 92 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 93 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 94 | program = gl.createProgram(); 95 | gl.attachShader(program, vert); 96 | gl.attachShader(program, frag); 97 | gl.linkProgram(program); 98 | gl.useProgram(program); 99 | } 100 | 101 | function requestDraw() { 102 | requestAnimationFrame(draw); 103 | } 104 | 105 | // straight outta mozilla 106 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 107 | function loadShader(gl, type, source) { 108 | const shader = gl.createShader(type); 109 | // Send the source to the shader object 110 | gl.shaderSource(shader, source); 111 | // Compile the shader program 112 | gl.compileShader(shader); 113 | // See if it compiled successfully 114 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 115 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 116 | gl.deleteShader(shader); 117 | return null; 118 | } 119 | return shader; 120 | } 121 | 122 | 123 | 124 | })(); 125 | 126 | -------------------------------------------------------------------------------- /shader_03.0/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_03.1/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | uniform vec2 u_resolution; 7 | 8 | float circle(in vec2 st, in float radius ) { 9 | vec2 l = st - vec2(0.5); 10 | return 1.0 - smoothstep( 11 | radius - radius * 0.01, 12 | radius + radius * 0.01, 13 | dot(l,l) * 4.0 14 | ); 15 | 16 | } 17 | 18 | 19 | void main() { 20 | vec2 st = gl_FragCoord.xy/min(u_resolution.x,u_resolution.y); 21 | vec3 rgb = vec3(0.0); 22 | // vec2 st2 = st * 10.0; 23 | vec2 st2 = st * 5.0; 24 | // float t = u_time / 1000.0; 25 | // st2 *= 0.1 + (sin(t) + 1.0) * 10.0 ; 26 | // st2 *= (1.1 + cos(t) ) * 10.0; 27 | // st2 *= (1.1 + cos(t) * sin(st2.y)*cos(st2.x)) * 10.0; 28 | st2 = fract(st2); 29 | // st2 *= st2; 30 | // rgb = vec3(st2,0.0); 31 | // float c = min(st2.x, st2.y); 32 | // rgb = vec3(c); 33 | 34 | float c = circle(st2,0.5); 35 | // // rgb = vec3(c, 0.5 + 0.5*c, 1.0); 36 | rgb = vec3(c); 37 | // rgb = vec3(c, 1.0-st.x, st.y); 38 | // float c2 = circle(st2,0.15); 39 | // if (c2 > 0.5) { 40 | // rgb = vec3(0.0, 0.0, 0.0); 41 | // // rgb = vec3(c2, 1.0-st.x, st.y); 42 | // } 43 | // rgb = vec3(c, 1.0-st.x, st.y); 44 | gl_FragColor = vec4(rgb,1.0); 45 | } -------------------------------------------------------------------------------- /shader_03.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_03.1/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | 9 | // we have a new global variable that represents the screen size 10 | timeUniformLocation, 11 | resolutionUniformLocation, 12 | positionLocation; 13 | 14 | // make the canvas fill the window 15 | canvas.width = W; 16 | canvas.height = H; 17 | 18 | function initGLData() { 19 | // now we can get some config info 20 | gl.viewport(0, 0, W, H); 21 | timeUniformLocation = gl.getUniformLocation(program, "u_time"); 22 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 23 | gl.uniform2f(resolutionUniformLocation, W, H); 24 | 25 | // Even though we aren't drawing anything really fancy, 26 | // we have to tell the GL Context how much of the screen we are drawing 27 | positionLocation = gl.getAttribLocation(program, "a_position"); 28 | gl.enableVertexAttribArray(positionLocation); 29 | var buffer = gl.createBuffer(); 30 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 31 | gl.bufferData( 32 | gl.ARRAY_BUFFER, 33 | /** 34 | note that unlike processing or canvas.getContext('2d'), 35 | the screen coordinates are 36 | -1, 1 left to right 37 | 1, -1 top to bottom 38 | and 0, 0 is the center 39 | and because GL is finicky, you have to specify them as floats, 40 | not ints, so add that '.0' to the end 41 | */ 42 | new Float32Array([ 43 | -1.0, 1.0, 44 | 1.0, 1.0, 45 | -1.0, -1.0, 46 | 1.0, -1.0]), 47 | gl.STATIC_DRAW 48 | ); 49 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 50 | } 51 | 52 | 53 | function draw() { 54 | // Set clear color to black, fully opaque 55 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 56 | // Clear the color buffer with specified clear color 57 | gl.clear(gl.COLOR_BUFFER_BIT); 58 | var elapsed = Date.now() - startTime; 59 | gl.uniform1f(timeUniformLocation, elapsed); 60 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 61 | } 62 | 63 | 64 | 65 | 66 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 67 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 68 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 69 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 70 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 71 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 72 | 73 | 74 | 75 | // load files 76 | fetch('frag.glsl') 77 | .then(function(response) { 78 | return response.text(); 79 | }).then(fragShaderText=>{ 80 | // console.log(fragShaderText) 81 | fetch('vert.glsl') 82 | .then(function(response) { 83 | return response.text(); 84 | }).then(vertShaderText=>{ 85 | // console.log(vertShaderText); 86 | compileGL(fragShaderText, vertShaderText); 87 | initGLData(); 88 | startTime = Date.now(); 89 | setInterval(requestDraw, 33); 90 | }); 91 | }); 92 | 93 | 94 | 95 | // build our program 96 | function compileGL(fragShaderText, vertShaderText) { 97 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 98 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 99 | program = gl.createProgram(); 100 | gl.attachShader(program, vert); 101 | gl.attachShader(program, frag); 102 | gl.linkProgram(program); 103 | gl.useProgram(program); 104 | } 105 | 106 | function requestDraw() { 107 | requestAnimationFrame(draw); 108 | } 109 | 110 | // straight outta mozilla 111 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 112 | function loadShader(gl, type, source) { 113 | const shader = gl.createShader(type); 114 | // Send the source to the shader object 115 | gl.shaderSource(shader, source); 116 | // Compile the shader program 117 | gl.compileShader(shader); 118 | // See if it compiled successfully 119 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 120 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 121 | gl.deleteShader(shader); 122 | return null; 123 | } 124 | return shader; 125 | } 126 | 127 | 128 | 129 | 130 | })(); 131 | 132 | -------------------------------------------------------------------------------- /shader_03.1/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | void main() { 4 | gl_Position = vec4(a_position, 0, 1); 5 | } -------------------------------------------------------------------------------- /shader_03.2/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform vec2 u_resolution; 6 | 7 | // New: the image 8 | uniform sampler2D u_image; 9 | 10 | // New: the image coordinate, passed from the vertex shader 11 | varying vec2 v_imagePosition; 12 | 13 | void main(){ 14 | vec4 color = texture2D(u_image, v_imagePosition); 15 | // copy the color from the image, and use it for the current pixel 16 | gl_FragColor = color; 17 | // You could also write that as: 18 | // gl_FragColor = color.rgba; 19 | 20 | // And here's where it gets fun. GLSL makes it really easy to switch up the colors 21 | // instead of Roy G Biv, let's Ruth Bader Ginsburg! 22 | // that is swap the blue and green values 23 | // gl_FragColor = color.rbga; 24 | // or we can swap to blue, red, and green 25 | // gl_FragColor = color.brga; 26 | 27 | // it's also trivial to make it negative 28 | // gl_FragColor = vec4(1.0 - color.rgb, 1.0); 29 | 30 | // or grayscale 31 | // float grayscale = max(max(color.r, color.g), color.b); 32 | // gl_FragColor = vec4(vec3(grayscale), 1.0); 33 | 34 | // and we can add a threshold to that to make it black and white 35 | // float bw = step(0.5, grayscale); 36 | 37 | // or instead we can add contrast but not a harsh black and white 38 | // float bw = smoothstep(0.1, 0.8, grayscale); 39 | // gl_FragColor = vec4(vec3(bw), 1.0); 40 | 41 | // or replace white with red 42 | // gl_FragColor = vec4(bw, 0.0, 0.0, 1.0); 43 | 44 | // or replace black with red 45 | // gl_FragColor = vec4(1.0, bw, bw, 1.0); 46 | 47 | 48 | 49 | } -------------------------------------------------------------------------------- /shader_03.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_03.2/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | resolutionUniformLocation, 9 | positionLocation, 10 | 11 | // New: let's mess with an image 12 | img, 13 | // and we will need to pass in image coordinates separate from 14 | // the general vertex positions 15 | imagePositionLocation 16 | ; 17 | 18 | // make the canvas fill the window 19 | canvas.width = W; 20 | canvas.height = H; 21 | 22 | 23 | 24 | 25 | function initGLData() { 26 | // now we can get some config info 27 | gl.viewport(0, 0, W, H); 28 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 29 | gl.uniform2f(resolutionUniformLocation, W, H); 30 | 31 | // Even though we aren't drawing anything really fancy, 32 | // we have to tell the GL Context how much of the screen we are drawing 33 | positionLocation = gl.getAttribLocation(program, "a_position"); 34 | imagePositionLocation = gl.getAttribLocation(program, "a_imagePosition"); 35 | gl.enableVertexAttribArray(positionLocation); 36 | var buffer = gl.createBuffer(); 37 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 38 | gl.bufferData( 39 | gl.ARRAY_BUFFER, 40 | /** 41 | note that unlike processing or canvas.getContext('2d'), 42 | the screen coordinates are 43 | -1, 1 left to right 44 | 1, -1 top to bottom 45 | and 0, 0 is the center 46 | and because GL is finicky, you have to specify them as floats, 47 | not ints, so add that '.0' to the end 48 | */ 49 | new Float32Array([ 50 | -1.0, 1.0, 51 | 1.0, 1.0, 52 | -1.0, -1.0, 53 | 1.0, -1.0]), 54 | gl.STATIC_DRAW ); 55 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 56 | 57 | 58 | // scale the image up to cover 59 | var aspect = W/H, 60 | imgAspect = img.width / img.height, 61 | imgW, imgH, 62 | imgL, imgR, 63 | imgT, imgB; 64 | if (imgAspect == aspect) { 65 | imgH = 1.0; 66 | imgW = 1.0; 67 | imgL = 0.0; 68 | imgT = 0.0; 69 | } else if (imgAspect > aspect) { 70 | imgT = 0.0; 71 | imgH = 1.0; 72 | imgW = aspect / imgAspect; 73 | imgL = (imgW - 1.0) * -.5; 74 | } else { 75 | imgW = 1.0; 76 | imgL = 0.0; 77 | imgH = imgAspect / aspect; 78 | imgT = (imgH - 1.0) * -.5; 79 | imgT = 0.0; 80 | } 81 | imgR = imgL + imgW; 82 | imgB = imgT + imgH; 83 | 84 | 85 | var texCoordBuffer = gl.createBuffer(); 86 | gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); 87 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 88 | imgL, imgT, 89 | imgR, imgT, 90 | imgL, imgB, 91 | imgR, imgB]), gl.STATIC_DRAW); 92 | gl.enableVertexAttribArray(imagePositionLocation); 93 | gl.vertexAttribPointer(imagePositionLocation, 2, gl.FLOAT, false, 0, 0); 94 | 95 | // Images are referred to as textures, and setting one up 96 | // is a bureaucratic operation. 97 | // Create a texture, and tell the shader that it is the one you want 98 | // to work with. Note that it is not yet attached to our image. 99 | var texture = gl.createTexture(); 100 | gl.bindTexture(gl.TEXTURE_2D, texture); 101 | 102 | // Set up texture so we can render any size image and so we are 103 | // working with pixels. 104 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 105 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 106 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 107 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 108 | 109 | // Upload the image into the texture. 110 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); 111 | } 112 | 113 | 114 | function draw() { 115 | // Set clear color to black, fully opaque 116 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 117 | // Clear the color buffer with specified clear color 118 | gl.clear(gl.COLOR_BUFFER_BIT); 119 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 120 | } 121 | 122 | 123 | 124 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 125 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 126 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 127 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 128 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 129 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 130 | 131 | 132 | 133 | 134 | img = new Image(); 135 | img.addEventListener('load', ()=> { 136 | // new: fetch the shaders after the image is loaded 137 | fetch('frag.glsl') 138 | .then(function(response) { 139 | return response.text(); 140 | }).then(fragShaderText=>{ 141 | // console.log(fragShaderText) 142 | fetch('vert.glsl') 143 | .then(function(response) { 144 | return response.text(); 145 | }).then(vertShaderText=>{ 146 | // console.log(vertShaderText); 147 | compileGL(fragShaderText, vertShaderText); 148 | initGLData(); 149 | requestDraw(); 150 | }); 151 | }); 152 | }); 153 | img.src = "../images/home.jpg"; 154 | // img.src = "../images/dd.jpeg"; 155 | 156 | 157 | 158 | 159 | // build our program 160 | function compileGL(fragShaderText, vertShaderText) { 161 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 162 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 163 | program = gl.createProgram(); 164 | gl.attachShader(program, vert); 165 | gl.attachShader(program, frag); 166 | gl.linkProgram(program); 167 | gl.useProgram(program); 168 | } 169 | 170 | function requestDraw() { 171 | requestAnimationFrame(draw); 172 | } 173 | 174 | // straight outta mozilla 175 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 176 | function loadShader(gl, type, source) { 177 | const shader = gl.createShader(type); 178 | // Send the source to the shader object 179 | gl.shaderSource(shader, source); 180 | // Compile the shader program 181 | gl.compileShader(shader); 182 | // See if it compiled successfully 183 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 184 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 185 | gl.deleteShader(shader); 186 | return null; 187 | } 188 | return shader; 189 | } 190 | 191 | 192 | 193 | })(); 194 | 195 | -------------------------------------------------------------------------------- /shader_03.2/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | // New: the image coordinates 4 | // the attribute gets it from the js program 5 | attribute vec2 a_imagePosition; 6 | // and stashes it in the varying version, which allows 7 | // it to pass to the fragment shader 8 | varying vec2 v_imagePosition; 9 | 10 | void main() { 11 | v_imagePosition = a_imagePosition; 12 | gl_Position = vec4(a_position, 0, 1); 13 | } -------------------------------------------------------------------------------- /shader_03.3/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | uniform vec2 u_resolution; 7 | uniform vec2 u_mouse; 8 | 9 | // New: the image 10 | uniform sampler2D u_image; 11 | 12 | // New: the image coordinate, passed from the vertex shader 13 | varying vec2 v_imagePosition; 14 | 15 | void main(){ 16 | vec4 color = texture2D(u_image, v_imagePosition); 17 | 18 | // vec2 xy = fract(v_imagePosition.st * 10.0); 19 | // vec4 color = texture2D(u_image, xy); 20 | 21 | float grayscale = max(max(color.r, color.g), color.b); 22 | // float bw = step(0.5, grayscale); 23 | // or we can soften the edges a bit 24 | float bw = smoothstep(0.3, 0.5, grayscale); 25 | 26 | // we can use that B&W to mask the original color 27 | gl_FragColor = vec4(vec3(bw) * color.rgb, 1.0); 28 | 29 | // or we can use some other color based on pixel position 30 | vec2 st = gl_FragCoord.xy/u_resolution; 31 | float t = u_time / 1000.0; 32 | vec2 mouse = u_mouse/u_resolution; 33 | 34 | vec3 fillColor; 35 | if (st.x < mouse.x) { 36 | fillColor = vec3(abs(sin(t)), st.x, st.y); 37 | } else { 38 | fillColor = vec3(st.y, abs(sin(st.x)), abs(cos(t))); 39 | } 40 | 41 | gl_FragColor = vec4(bw * fillColor, 1.0); 42 | } -------------------------------------------------------------------------------- /shader_03.3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_03.3/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | vert, 5 | frag, 6 | program, 7 | W = window.innerWidth, 8 | H = window.innerHeight, 9 | startTime, 10 | 11 | mouseX, mouseY, 12 | mouseUniformLocation, 13 | resolutionUniformLocation, 14 | timeUniformLocation, 15 | positionLocation, 16 | 17 | img, 18 | imagePositionLocation 19 | ; 20 | 21 | // make the canvas fill the window 22 | canvas.width = W; 23 | canvas.height = H; 24 | 25 | 26 | function initGLData() { 27 | // now we can get some config info 28 | gl.viewport(0, 0, W, H); 29 | mouseUniformLocation = gl.getUniformLocation(program, "u_mouse"); 30 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 31 | timeUniformLocation = gl.getUniformLocation(program, "u_time"); 32 | 33 | gl.uniform2f(resolutionUniformLocation, W, H); 34 | 35 | // Even though we aren't drawing anything really fancy, 36 | // we have to tell the GL Context how much of the screen we are drawing 37 | positionLocation = gl.getAttribLocation(program, "a_position"); 38 | imagePositionLocation = gl.getAttribLocation(program, "a_imagePosition"); 39 | gl.enableVertexAttribArray(positionLocation); 40 | var buffer = gl.createBuffer(); 41 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 42 | gl.bufferData( 43 | gl.ARRAY_BUFFER, 44 | /** 45 | note that unlike processing or canvas.getContext('2d'), 46 | the screen coordinates are 47 | -1, 1 left to right 48 | 1, -1 top to bottom 49 | and 0, 0 is the center 50 | and because GL is finicky, you have to specify them as floats, 51 | not ints, so add that '.0' to the end 52 | */ 53 | new Float32Array([ 54 | -1.0, 1.0, 55 | 1.0, 1.0, 56 | -1.0, -1.0, 57 | 1.0, -1.0]), 58 | gl.STATIC_DRAW ); 59 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 60 | 61 | 62 | // scale the image up to cover 63 | var aspect = W/H, 64 | imgAspect = img.width / img.height, 65 | imgW, imgH, 66 | imgL, imgR, 67 | imgT, imgB; 68 | if (imgAspect == aspect) { 69 | imgH = 1.0; 70 | imgW = 1.0; 71 | imgL = 0.0; 72 | imgT = 0.0; 73 | } else if (imgAspect > aspect) { 74 | imgT = 0.0; 75 | imgH = 1.0; 76 | imgW = aspect / imgAspect; 77 | imgL = (imgW - 1.0) * -.5; 78 | } else { 79 | imgW = 1.0; 80 | imgL = 0.0; 81 | imgH = imgAspect / aspect; 82 | imgT = (imgH - 1.0) * -.5; 83 | imgT = 0.0; 84 | } 85 | imgR = imgL + imgW; 86 | imgB = imgT + imgH; 87 | 88 | 89 | var texCoordBuffer = gl.createBuffer(); 90 | gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); 91 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 92 | imgL, imgT, 93 | imgR, imgT, 94 | imgL, imgB, 95 | imgR, imgB]), gl.STATIC_DRAW); 96 | gl.enableVertexAttribArray(imagePositionLocation); 97 | gl.vertexAttribPointer(imagePositionLocation, 2, gl.FLOAT, false, 0, 0); 98 | 99 | var texture = gl.createTexture(); 100 | gl.bindTexture(gl.TEXTURE_2D, texture); 101 | 102 | // Set the parameters so we can render any size image. 103 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 104 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 105 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 106 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 107 | 108 | // Upload the image into the texture. 109 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); 110 | } 111 | 112 | 113 | function draw() { 114 | // Set clear color to black, fully opaque 115 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 116 | // Clear the color buffer with specified clear color 117 | gl.clear(gl.COLOR_BUFFER_BIT); 118 | var elapsed = Date.now() - startTime; 119 | gl.uniform1f(timeUniformLocation, elapsed); 120 | gl.uniform2f(mouseUniformLocation, mouseX, mouseY); 121 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 122 | } 123 | 124 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 125 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 126 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 127 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 128 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 129 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 130 | 131 | 132 | 133 | 134 | img = new Image(); 135 | img.addEventListener('load', ()=> { 136 | // new: fetch the shaders after the image is loaded 137 | fetch('frag.glsl') 138 | .then(function(response) { 139 | return response.text(); 140 | }).then(fragShaderText=>{ 141 | // console.log(fragShaderText) 142 | fetch('vert.glsl') 143 | .then(function(response) { 144 | return response.text(); 145 | }).then(vertShaderText=>{ 146 | // console.log(vertShaderText); 147 | compileGL(fragShaderText, vertShaderText); 148 | initGLData(); 149 | startTime = Date.now(); 150 | canvas.addEventListener('mousemove',(event) => { 151 | mouseX = event.offsetX; 152 | mouseY = event.offsetY; 153 | }); 154 | setInterval(requestDraw, 30); 155 | }); 156 | }); 157 | }); 158 | img.src = "../images/home.jpg"; 159 | // img.src = "../images/dd.jpeg"; 160 | 161 | 162 | 163 | 164 | 165 | // build our program 166 | function compileGL(fragShaderText, vertShaderText) { 167 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 168 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 169 | program = gl.createProgram(); 170 | gl.attachShader(program, vert); 171 | gl.attachShader(program, frag); 172 | gl.linkProgram(program); 173 | gl.useProgram(program); 174 | } 175 | 176 | function requestDraw() { 177 | requestAnimationFrame(draw); 178 | } 179 | 180 | // straight outta mozilla 181 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 182 | function loadShader(gl, type, source) { 183 | const shader = gl.createShader(type); 184 | // Send the source to the shader object 185 | gl.shaderSource(shader, source); 186 | // Compile the shader program 187 | gl.compileShader(shader); 188 | // See if it compiled successfully 189 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 190 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 191 | gl.deleteShader(shader); 192 | return null; 193 | } 194 | return shader; 195 | } 196 | 197 | 198 | })(); 199 | 200 | -------------------------------------------------------------------------------- /shader_03.3/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | 4 | // New: the image coordinates 5 | // the attribute gets it from the js program 6 | attribute vec2 a_imagePosition; 7 | // and stashes it in the varying version, which allows 8 | // it to pass to the fragment shader 9 | varying vec2 v_imagePosition; 10 | 11 | void main() { 12 | v_imagePosition = a_imagePosition; 13 | gl_Position = vec4(a_position, 0, 1); 14 | } -------------------------------------------------------------------------------- /shader_03.4/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | uniform float u_time; 6 | uniform vec2 u_resolution; 7 | uniform vec2 u_mouse; 8 | uniform float u_matrix[9]; 9 | 10 | 11 | // New: the image 12 | uniform sampler2D u_image; 13 | 14 | // New: the image coordinate, passed from the vertex shader 15 | varying vec2 v_imagePosition; 16 | 17 | void main(){ 18 | vec4 color = vec4(vec3(0.0), 1.0); 19 | for ( float i=0.0;i < 9.0;i++) { 20 | float xoff = mod(i, 3.0) - 1.0; 21 | float yoff = floor(i / 3.0) - 1.0; 22 | vec2 coord = vec2(xoff, yoff) / u_resolution; 23 | vec4 c = texture2D(u_image, v_imagePosition.st + coord); 24 | float matVal = u_matrix[int(i)]; 25 | color += matVal * c; 26 | } 27 | float gray = max(max(color.r, color.g), color.b); 28 | // gray = pow(gray, .25); 29 | color = texture2D(u_image, v_imagePosition); 30 | color.rgb = vec3(gray); 31 | // color.rgb = vec3(pow(color.r, .5), pow(color.g, .5), pow(color.b, .5)); 32 | gl_FragColor = color; 33 | } -------------------------------------------------------------------------------- /shader_03.4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_03.4/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | frameCount = 0, 9 | 10 | mouseX, mouseY, 11 | mouseUniformLocation, 12 | resolutionUniformLocation, 13 | timeUniformLocation, 14 | matrixUniformLocation, 15 | positionLocation, 16 | 17 | // New: let's mess with an image 18 | img, 19 | // and we will need to pass in image coordinates separate from 20 | // the general vertex positions 21 | imagePositionLocation 22 | ; 23 | 24 | // make the canvas fill the window 25 | canvas.width = W; 26 | canvas.height = H; 27 | 28 | 29 | function initGLData() { 30 | // now we can get some config info 31 | gl.viewport(0, 0, W, H); 32 | mouseUniformLocation = gl.getUniformLocation(program, "u_mouse"); 33 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 34 | timeUniformLocation = gl.getUniformLocation(program, "u_time"); 35 | matrixUniformLocation = gl.getUniformLocation(program, "u_matrix"); 36 | 37 | gl.uniform2f(resolutionUniformLocation, W, H); 38 | 39 | // Even though we aren't drawing anything really fancy, 40 | // we have to tell the GL Context how much of the screen we are drawing 41 | positionLocation = gl.getAttribLocation(program, "a_position"); 42 | imagePositionLocation = gl.getAttribLocation(program, "a_imagePosition"); 43 | gl.enableVertexAttribArray(positionLocation); 44 | var buffer = gl.createBuffer(); 45 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 46 | gl.bufferData( 47 | gl.ARRAY_BUFFER, 48 | /** 49 | note that unlike processing or canvas.getContext('2d'), 50 | the screen coordinates are 51 | -1, 1 left to right 52 | 1, -1 top to bottom 53 | and 0, 0 is the center 54 | and because GL is finicky, you have to specify them as floats, 55 | not ints, so add that '.0' to the end 56 | */ 57 | new Float32Array([ 58 | -1.0, 1.0, 59 | 1.0, 1.0, 60 | -1.0, -1.0, 61 | 1.0, -1.0]), 62 | gl.STATIC_DRAW ); 63 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 64 | 65 | 66 | 67 | // scale the image up to cover 68 | var aspect = W/H, 69 | imgAspect = img.width / img.height, 70 | imgW, imgH, 71 | imgL, imgR, 72 | imgT, imgB; 73 | if (imgAspect == aspect) { 74 | imgH = 1.0; 75 | imgW = 1.0; 76 | imgL = 0.0; 77 | imgT = 0.0; 78 | } else if (imgAspect > aspect) { 79 | imgT = 0.0; 80 | imgH = 1.0; 81 | imgW = aspect / imgAspect; 82 | imgL = (imgW - 1.0) * -.5; 83 | } else { 84 | imgW = 1.0; 85 | imgL = 0.0; 86 | imgH = imgAspect / aspect; 87 | imgT = (imgH - 1.0) * -.5; 88 | imgT = 0.0; 89 | } 90 | imgR = imgL + imgW; 91 | imgB = imgT + imgH; 92 | 93 | 94 | var texCoordBuffer = gl.createBuffer(); 95 | gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); 96 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 97 | imgL, imgT, 98 | imgR, imgT, 99 | imgL, imgB, 100 | imgR, imgB]), gl.STATIC_DRAW); 101 | gl.enableVertexAttribArray(imagePositionLocation); 102 | gl.vertexAttribPointer(imagePositionLocation, 2, gl.FLOAT, false, 0, 0); 103 | 104 | var texture = gl.createTexture(); 105 | gl.bindTexture(gl.TEXTURE_2D, texture); 106 | 107 | // Set the parameters so we can render any size image. 108 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 109 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 110 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 111 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 112 | 113 | // Upload the image into the texture. 114 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img); 115 | /***** 116 | 117 | Try these different versions of the 'matrix' variable 118 | to get different effects in the image. 119 | 120 | 121 | **/ 122 | // set the matrix 123 | // var matrix = [0, 0, 0, 124 | // 0, 1.0, 0, 125 | // 0, 0, 0]; // untransformed 126 | // var matrix = [-1, -1, -1, 127 | // -1, 8, -1, 128 | // -1, -1, -1]; // edge 129 | // var matrix = [-1, -1, -1, 130 | // -1, 9, -1, 131 | // -1, -1, -1]; // sharpen 132 | // var matrix = [-1, 1, 1, 133 | // -1, .5, 1, 134 | // -1, -1, 1]; // emboss 135 | // var matrix = [1/9.0, 1/9.0, 1/9.0, 136 | // 1/9.0, 1/9.0, 1/9.0, 137 | // 1/9.0, 1/9.0, 1/9.0]; // blur 138 | var matrix = [0, 2, 0, 139 | -2, 0, 2, 140 | 0, -2, 0]; // gettin' wiggy! 141 | gl.uniform1fv(matrixUniformLocation, matrix); 142 | } 143 | 144 | 145 | function draw() { 146 | // Set clear color to black, fully opaque 147 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 148 | // Clear the color buffer with specified clear color 149 | gl.clear(gl.COLOR_BUFFER_BIT); 150 | var elapsed = Date.now() - startTime; 151 | gl.uniform1f(timeUniformLocation, elapsed / 1000.0); 152 | gl.uniform2f(mouseUniformLocation, mouseX, mouseY); 153 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 154 | } 155 | 156 | 157 | 158 | 159 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 160 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 161 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 162 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 163 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 164 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 165 | 166 | 167 | 168 | 169 | img = new Image(); 170 | img.addEventListener('load', ()=> { 171 | // new: fetch the shaders after the image is loaded 172 | fetch('frag.glsl') 173 | .then(function(response) { 174 | return response.text(); 175 | }).then(fragShaderText=>{ 176 | // console.log(fragShaderText) 177 | fetch('vert.glsl') 178 | .then(function(response) { 179 | return response.text(); 180 | }).then(vertShaderText=>{ 181 | // console.log(vertShaderText); 182 | compileGL(fragShaderText, vertShaderText); 183 | initGLData(); 184 | requestDraw(); 185 | }); 186 | }); 187 | }); 188 | img.src = "../images/home.jpg"; 189 | // img.src = "../images/dd.jpeg"; 190 | 191 | 192 | 193 | 194 | // build our program 195 | function compileGL(fragShaderText, vertShaderText) { 196 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 197 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 198 | program = gl.createProgram(); 199 | gl.attachShader(program, vert); 200 | gl.attachShader(program, frag); 201 | gl.linkProgram(program); 202 | gl.useProgram(program); 203 | } 204 | 205 | function requestDraw() { 206 | requestAnimationFrame(draw); 207 | } 208 | 209 | // straight outta mozilla 210 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 211 | function loadShader(gl, type, source) { 212 | const shader = gl.createShader(type); 213 | // Send the source to the shader object 214 | gl.shaderSource(shader, source); 215 | // Compile the shader program 216 | gl.compileShader(shader); 217 | // See if it compiled successfully 218 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 219 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 220 | gl.deleteShader(shader); 221 | return null; 222 | } 223 | return shader; 224 | } 225 | 226 | 227 | })(); 228 | 229 | -------------------------------------------------------------------------------- /shader_03.4/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | 3 | 4 | // New: the image coordinates 5 | // the attribute gets it from the js program 6 | attribute vec2 a_imagePosition; 7 | // and stashes it in the varying version, which allows 8 | // it to pass to the fragment shader 9 | varying vec2 v_imagePosition; 10 | 11 | void main() { 12 | v_imagePosition = a_imagePosition; 13 | gl_Position = vec4(a_position, 0, 1); 14 | } -------------------------------------------------------------------------------- /shader_04.0/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | // New: a place where we can get a color passed from the wertex shader 6 | varying vec4 v_color; 7 | 8 | void main(){ 9 | gl_FragColor = v_color; 10 | } -------------------------------------------------------------------------------- /shader_04.0/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_04.0/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | positionLocation, 9 | 10 | // New: we are going to pass some colors from js to the shader 11 | colorLocation 12 | ; 13 | 14 | // make the canvas fill the window 15 | canvas.width = W; 16 | canvas.height = H; 17 | 18 | function initGLData() { 19 | // now we can get some config info 20 | gl.viewport(0, 0, W, H); 21 | 22 | positionLocation = gl.getAttribLocation(program, "a_position"); 23 | gl.enableVertexAttribArray(positionLocation); 24 | var buffer = gl.createBuffer(); 25 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 26 | gl.bufferData( 27 | gl.ARRAY_BUFFER, 28 | /** 29 | note that unlike processing or canvas.getContext('2d'), 30 | the screen coordinates are 31 | -1, 1 left to right 32 | 1, -1 top to bottom 33 | and 0, 0 is the center 34 | and because GL is finicky, you have to specify them as floats, 35 | not ints, so add that '.0' to the end 36 | */ 37 | new Float32Array([ 38 | -1.0, 1.0, 39 | 1.0, 1.0, 40 | -1.0, -1.0, 41 | 1.0, -1.0 42 | ]), 43 | gl.STATIC_DRAW 44 | ); 45 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 46 | 47 | 48 | // New: get the place where the shader wants us to put colors 49 | colorLocation = gl.getAttribLocation(program, "a_color"); 50 | gl.enableVertexAttribArray(colorLocation); 51 | buffer = gl.createBuffer(); 52 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 53 | gl.bufferData(gl.ARRAY_BUFFER, 54 | // we send over a color for each vertex 55 | new Float32Array([ 56 | 1.0, 1.0, 1.0, 1.0, // white 57 | 1.0, 0.0, 0.0, 1.0, // red 58 | 0.0, 1.0, 0.0, 1.0, // green 59 | 0.0, 0.0, 1.0, 1.0, // blue 60 | ]), 61 | gl.STATIC_DRAW); 62 | gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0); 63 | 64 | } 65 | 66 | 67 | 68 | 69 | function draw() { 70 | // Set clear color to black, fully opaque 71 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 72 | // Clear the color buffer with specified clear color 73 | gl.clear(gl.COLOR_BUFFER_BIT); 74 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 75 | } 76 | 77 | 78 | 79 | 80 | 81 | 82 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 83 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 84 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 85 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 86 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 87 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 88 | 89 | 90 | // load files 91 | fetch('frag.glsl') 92 | .then(function(response) { 93 | return response.text(); 94 | }).then(fragShaderText=>{ 95 | // console.log(fragShaderText) 96 | fetch('vert.glsl') 97 | .then(function(response) { 98 | return response.text(); 99 | }).then(vertShaderText=>{ 100 | // console.log(vertShaderText); 101 | compileGL(fragShaderText, vertShaderText); 102 | initGLData(); 103 | requestDraw(); 104 | }); 105 | }); 106 | 107 | 108 | 109 | // build our program 110 | function compileGL(fragShaderText, vertShaderText) { 111 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 112 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 113 | program = gl.createProgram(); 114 | gl.attachShader(program, vert); 115 | gl.attachShader(program, frag); 116 | gl.linkProgram(program); 117 | gl.useProgram(program); 118 | } 119 | 120 | function requestDraw() { 121 | requestAnimationFrame(draw); 122 | } 123 | 124 | // straight outta mozilla 125 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 126 | function loadShader(gl, type, source) { 127 | const shader = gl.createShader(type); 128 | // Send the source to the shader object 129 | gl.shaderSource(shader, source); 130 | // Compile the shader program 131 | gl.compileShader(shader); 132 | // See if it compiled successfully 133 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 134 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 135 | gl.deleteShader(shader); 136 | return null; 137 | } 138 | return shader; 139 | } 140 | 141 | 142 | })(); 143 | 144 | -------------------------------------------------------------------------------- /shader_04.0/vert.glsl: -------------------------------------------------------------------------------- 1 | attribute vec2 a_position; 2 | // New: a place to get the color passed from js 3 | attribute vec4 a_color; 4 | 5 | // New: a place where we can tell the fragment shader what the color is 6 | varying vec4 v_color; 7 | 8 | void main() { 9 | gl_Position = vec4(a_position, 0, 1); 10 | v_color = a_color; 11 | } -------------------------------------------------------------------------------- /shader_04.1/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /shader_04.1/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | 9 | 10 | positionLocation, 11 | colorLocation, 12 | 13 | resolutionUniformLocation, 14 | 15 | 16 | // New: we are going to start moving the vertices around in space. 17 | // Or more accuratly, we are going to move the space in which 18 | // the vertices are placed. According to convention, the layout 19 | // of the vertices is called the "model". 20 | modelUniform, 21 | 22 | // New: to move the vertices, we will use math! Each type of motion 23 | // will be in its own matrix. 24 | translationMatrix, 25 | rotationMatrix, 26 | scaleMatrix, 27 | //And then we will merge all different types of motion into one matrix 28 | // to hand over to the shader 29 | modelMatrix 30 | 31 | ; 32 | 33 | // make the canvas fill the window 34 | canvas.width = W; 35 | canvas.height = H; 36 | 37 | 38 | 39 | function initGLData() { 40 | // now we can get some config info 41 | gl.viewport(0, 0, W, H); 42 | 43 | resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); 44 | gl.uniform2f(resolutionUniformLocation, W, H); 45 | 46 | // New: where does the shader store the model 47 | modelUniform = gl.getUniformLocation(program, "u_model"); 48 | // There are several ways we will move the model, and we will 49 | // track each in its own matrix. 50 | // Translation is the technical term for changing the location. 51 | translationMatrix = mat4.create(); 52 | // Rotation rotates 53 | rotationMatrix = mat4.create(); 54 | // and scale isgrowing or shrinking 55 | scaleMatrix = mat4.create(); 56 | // we will combine translation, rotation, and scale into one matrix 57 | modelMatrix = mat4.create(); 58 | 59 | // move the drawing position a bit to where we want to 60 | // start drawing the square. 61 | // note: with glmatrix.js, the first parameter 62 | // is always the matrix that you are writing to. Any values 63 | // in that matrix will be overwritten. 64 | mat4.translate( 65 | translationMatrix, // the matrix that tracks the translated location 66 | translationMatrix, // matrix to start from (which is not moved at this point) 67 | [-0.25, 0.25, 0.0]); // amount to translate 68 | 69 | mat4.rotate( 70 | rotationMatrix, // the matrix that tracks the rotation 71 | rotationMatrix, // matrix to to start from (unrotated here) 72 | Math.PI * .25, // amount to rotate it 73 | [0, 0, 1] // the axis it rotates around: the center of the square 74 | ); 75 | 76 | mat4.scale( 77 | scaleMatrix, // the matrix that will track the scaling 78 | scaleMatrix, // source matrix 79 | [2, .5, 1.0]); // the scaling amount in the x, y, and z directions 80 | 81 | 82 | // the positions of our vertices 83 | var corners = [ 84 | 0.0, 0.5, 85 | 0.75, 0.0, 86 | -0.5, -0.0, 87 | 0.0, -0.5 88 | ]; 89 | // the colors for each vertex 90 | var colors = [ 91 | 1.0, 1.0, 1.0, 1.0, // white 92 | 1.0, 0.0, 0.0, 1.0, // red 93 | 0.0, 1.0, 0.0, 1.0, // green 94 | 0.0, 0.0, 1.0, 1.0, // blue, 95 | ]; 96 | 97 | // pass our vertex locations to the vertex shader 98 | positionLocation = gl.getAttribLocation(program, "a_position"); 99 | var positionBuffer = gl.createBuffer(); 100 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 101 | gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(corners), gl.STATIC_DRAW); 102 | gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 103 | gl.enableVertexAttribArray(positionLocation); 104 | 105 | colorLocation = gl.getAttribLocation(program, "a_color"); 106 | gl.enableVertexAttribArray(colorLocation); 107 | var colorBuffer = gl.createBuffer(); 108 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 109 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); 110 | gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0); 111 | gl.enableVertexAttribArray(colorLocation); 112 | } 113 | 114 | 115 | 116 | 117 | function draw() { 118 | // Set clear color to black, fully opaque 119 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 120 | gl.clearDepth(1.0); 121 | // Clear the color buffer with specified clear color 122 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 123 | 124 | 125 | // New: combine the translation matrix and rotation matrix, 126 | // and store it in the modelMatrix 127 | mat4.multiply(modelMatrix, translationMatrix, rotationMatrix); 128 | 129 | // if you want to scale the positions as well, 130 | // mulitply the model matrix by the scale matrix 131 | // mat4.multiply(modelMatrix, modelMatrix, scaleMatrix); 132 | 133 | // order matters! Instead of translation and rotation first, try scaling and rotation first 134 | // mat4.multiply(modelMatrix, scaleMatrix, rotationMatrix); 135 | // mat4.multiply(modelMatrix, modelMatrix, translationMatrix); 136 | 137 | // make the rotation change a little each frame 138 | // mat4.rotate( 139 | // rotationMatrix, // destination matrix 140 | // rotationMatrix, // matrix to rotate 141 | // Math.PI * .01 , // amount it rotates each frame 142 | // [0, 0, 1] // the axis it rotates around: the center of the square 143 | // ); 144 | 145 | gl.uniformMatrix4fv(modelUniform, false, modelMatrix); 146 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 147 | } 148 | 149 | 150 | 151 | 152 | 153 | 154 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 155 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 156 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 157 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 158 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 159 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 160 | 161 | 162 | // load files 163 | fetch('frag.glsl') 164 | .then(function(response) { 165 | return response.text(); 166 | }).then(fragShaderText=>{ 167 | // console.log(fragShaderText) 168 | fetch('vert.glsl') 169 | .then(function(response) { 170 | return response.text(); 171 | }).then(vertShaderText=>{ 172 | // console.log(vertShaderText); 173 | compileGL(fragShaderText, vertShaderText); 174 | initGLData(); 175 | setInterval(requestDraw, 33); 176 | }); 177 | }); 178 | 179 | 180 | 181 | // build our program 182 | function compileGL(fragShaderText, vertShaderText) { 183 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 184 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 185 | program = gl.createProgram(); 186 | gl.attachShader(program, vert); 187 | gl.attachShader(program, frag); 188 | gl.linkProgram(program); 189 | gl.useProgram(program); 190 | } 191 | 192 | function requestDraw() { 193 | requestAnimationFrame(draw); 194 | } 195 | 196 | // straight outta mozilla 197 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 198 | function loadShader(gl, type, source) { 199 | const shader = gl.createShader(type); 200 | // Send the source to the shader object 201 | gl.shaderSource(shader, source); 202 | // Compile the shader program 203 | gl.compileShader(shader); 204 | // See if it compiled successfully 205 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 206 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 207 | gl.deleteShader(shader); 208 | return null; 209 | } 210 | return shader; 211 | } 212 | 213 | 214 | })(); 215 | 216 | -------------------------------------------------------------------------------- /shader_04.1/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | uniform mat4 u_model; 11 | 12 | uniform vec2 u_resolution; 13 | 14 | void main() { 15 | float s = min(u_resolution.x, u_resolution.y); 16 | vec4 scale = vec4(vec2(s, s) / u_resolution, 1.0, 1.0); 17 | gl_Position = u_model * a_position * scale; 18 | v_color = a_color; 19 | } -------------------------------------------------------------------------------- /shader_04.2/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_04.2/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | uniform mat4 u_model; 11 | uniform mat4 u_projection; 12 | 13 | void main() { 14 | gl_Position = u_projection * u_model * a_position; 15 | v_color = a_color; 16 | } -------------------------------------------------------------------------------- /shader_04.3/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_04.3/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | 9 | positionLocation, 10 | colorLocation, 11 | 12 | modelUniform, 13 | 14 | 15 | // New: we are going to define where we are watching from, 16 | // which will enable a sense of foreshortening 17 | projectionUniform, 18 | // the matrix for the projection that will be passed to the shader 19 | projectionMatrix, 20 | 21 | translationMatrix, 22 | rotationMatrix, 23 | scaleMatrix, 24 | 25 | modelMatrix, 26 | 27 | pointCount 28 | 29 | ; 30 | 31 | 32 | const ARC_PRECISION = 50; 33 | 34 | // make the canvas fill the window 35 | canvas.width = W; 36 | canvas.height = H; 37 | 38 | 39 | 40 | function initGLData() { 41 | // now we can get some config info 42 | gl.viewport(0, 0, W, H); 43 | 44 | // New: get the locations where the shader wants the model and projection 45 | modelUniform = gl.getUniformLocation(program, "u_model"); 46 | // We will be positioning things in 3d space, so tell the program 47 | // how we want it to handle things behind or in front of each other 48 | gl.enable(gl.DEPTH_TEST); 49 | gl.depthFunc(gl.LEQUAL); 50 | 51 | // straight from mozilla! 52 | // Create a perspective matrix, a special matrix that is 53 | // used to simulate the distortion of perspective in a camera. 54 | // Our field of view is 45 degrees, with a width/height 55 | // ratio that matches the display size of the canvas 56 | // and we only want to see objects between 0.1 units 57 | // and 100 units away from the camera. 58 | const fieldOfView = 45 * Math.PI / 180; // in radians 59 | const aspect = W / H; 60 | const zNear = 0.1; 61 | const zFar = 100.0; 62 | projectionMatrix = mat4.create(); 63 | projectionUniform = gl.getUniformLocation(program, "u_projection"); 64 | 65 | // note: with glmatrix.js, the first parameter 66 | // is always the matrix that you are writing to. Any values 67 | // in that matrix will be overwritten. 68 | mat4.perspective(projectionMatrix, 69 | fieldOfView, 70 | aspect, 71 | zNear, 72 | zFar); 73 | 74 | translationMatrix = mat4.create(); 75 | rotationMatrix = mat4.create(); 76 | scaleMatrix = mat4.create(); 77 | modelMatrix = mat4.create(); 78 | // Now move the drawing position a bit to where we want to 79 | // start drawing the square. 80 | mat4.translate( 81 | translationMatrix, // the matrix that tracks the translated location 82 | translationMatrix, // matrix to start from (which is not moved at this point) 83 | [-0.0, 0.0, -6.0]); // amount to translate 84 | 85 | mat4.rotate( 86 | rotationMatrix, // the matrix that tracks the rotation 87 | rotationMatrix, // matrix to to start from (unrotated here) 88 | Math.PI * .25, // amount to rotate it 89 | [0, 0, 1] // the axis it rotates around: the center of the square 90 | ); 91 | 92 | positionLocation = gl.getAttribLocation(program, "a_position"); 93 | var positionBuffer = gl.createBuffer(); 94 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 95 | 96 | 97 | // New: we will creatig a lot or vertices, too many to hand curate the 98 | // color for each vertex. So here we create a list of colors, which we 99 | // will draw from programmatically as we set up the sphere coordinates. 100 | const colorSources = [ 101 | [1.0, 1.0, 1.0, 1.0], // white 102 | [1.0, 0.0, 0.0, 1.0], // red 103 | [0.0, 1.0, 0.0, 1.0], // green 104 | 105 | [0.0, 0.0, 1.0, 1.0], // blue, 106 | [1.0, 0.5, 0.0, 1.0], // orange 107 | [0.0, 1.0, 0.5, 1.0], // violet 108 | 109 | [0.5, 0.0, 1.0, 1.0], // yellow 110 | [1.0, 1.0, 0.0, 1.0], // yellow 111 | [0.0, 1.0, 1.0, 1.0], // cyan 112 | [1.0, 0.0, 1.0, 1.0], // magenta 113 | [0.0, 0.5, 1.2, 1.0] 114 | ]; 115 | 116 | 117 | // New: rather than curate the vertices, we will generate them using 118 | // good ole trigonometry. 119 | var coords = [], 120 | colors = []; 121 | const cos = Math.cos, 122 | sin = Math.sin, 123 | PI = Math.PI, 124 | TAU = PI * 2, 125 | HALF_PI = PI * .5, 126 | INCREMENT = PI / ARC_PRECISION, 127 | // because floats can get imprecise, allow ourselves to 128 | // overshoot the last row a little bit 129 | LIMIT = HALF_PI + INCREMENT/2; 130 | // we need to track many vertices we will draw 131 | pointCount = 0; 132 | // we will build out the sphere row by row 133 | for (var lat = -HALF_PI; lat <= LIMIT; lat += INCREMENT) { 134 | var previousRow = lat - INCREMENT; 135 | var prevY = sin(previousRow), 136 | currentY = sin(lat), 137 | // var prevY = sin(previousRow * 2), 138 | // currentY = sin(lat * 2), 139 | cosPrevious = cos(previousRow), 140 | cosCurrent = cos(lat), 141 | // cosPrevious = cos(previousRow * 3), 142 | // cosCurrent = cos(lat * 3), 143 | colorIndex = 0; 144 | // build out the triangles for this row 145 | for (var lon = 0; lon <= TAU; lon += INCREMENT) { 146 | var cosLon = cos(lon), 147 | sinLon = sin(lon), 148 | // sinLon = sin(Math.pow(lon/TAU, 2) * TAU), 149 | previousX = cosPrevious * cosLon, 150 | currentX = cosCurrent * cosLon, 151 | previousZ = cosPrevious * sinLon, 152 | currentZ = cosCurrent * sinLon, 153 | color = colorSources[colorIndex]; 154 | coords.push(previousX); 155 | coords.push(prevY); 156 | coords.push(previousZ); 157 | // add each elemnt of the color to the color array 158 | for (var i=0; i{ 262 | // console.log(fragShaderText) 263 | fetch('vert.glsl') 264 | .then(function(response) { 265 | return response.text(); 266 | }).then(vertShaderText=>{ 267 | // console.log(vertShaderText); 268 | compileGL(fragShaderText, vertShaderText); 269 | initGLData(); 270 | startTime = Date.now(); 271 | setInterval(requestDraw, 33); 272 | }); 273 | }); 274 | 275 | 276 | 277 | // build our program 278 | function compileGL(fragShaderText, vertShaderText) { 279 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 280 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 281 | program = gl.createProgram(); 282 | gl.attachShader(program, vert); 283 | gl.attachShader(program, frag); 284 | gl.linkProgram(program); 285 | gl.useProgram(program); 286 | } 287 | 288 | function requestDraw() { 289 | requestAnimationFrame(draw); 290 | } 291 | 292 | // straight outta mozilla 293 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 294 | function loadShader(gl, type, source) { 295 | const shader = gl.createShader(type); 296 | // Send the source to the shader object 297 | gl.shaderSource(shader, source); 298 | // Compile the shader program 299 | gl.compileShader(shader); 300 | // See if it compiled successfully 301 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 302 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 303 | gl.deleteShader(shader); 304 | return null; 305 | } 306 | return shader; 307 | } 308 | 309 | 310 | })(); 311 | 312 | -------------------------------------------------------------------------------- /shader_04.3/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | uniform mat4 u_model; 11 | uniform mat4 u_projection; 12 | 13 | void main() { 14 | gl_Position = u_projection * u_model * a_position; 15 | v_color = a_color; 16 | } -------------------------------------------------------------------------------- /shader_04.4/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_04.4/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | 9 | positionLocation, 10 | colorLocation, 11 | positionBuffer, 12 | colorBUffer, 13 | 14 | // New: we are going to start positioning vertices in space! 15 | modelUniform, 16 | projectionUniform, 17 | 18 | translationMatrix, 19 | rotationMatrix, 20 | scaleMatrix, 21 | 22 | modelMatrix, 23 | projectionMatrix 24 | 25 | ; 26 | 27 | // make the canvas fill the window 28 | canvas.width = W; 29 | canvas.height = H; 30 | 31 | 32 | 33 | function initGLData() { 34 | // now we can get some config info 35 | gl.viewport(0, 0, W, H); 36 | 37 | // New: get the locations where the shader wants the model and projection 38 | modelUniform = gl.getUniformLocation(program, "u_model"); 39 | projectionUniform = gl.getUniformLocation(program, "u_projection"); 40 | // We will be positioning things in 3d space, so tell the program 41 | // how we want it to handle things behind or in front of each other 42 | gl.enable(gl.DEPTH_TEST); 43 | gl.depthFunc(gl.LEQUAL); 44 | 45 | // straight from mozilla! 46 | // Create a perspective matrix, a special matrix that is 47 | // used to simulate the distortion of perspective in a camera. 48 | // Our field of view is 45 degrees, with a width/height 49 | // ratio that matches the display size of the canvas 50 | // and we only want to see objects between 0.1 units 51 | // and 100 units away from the camera. 52 | const fieldOfView = 45 * Math.PI / 180; // in radians 53 | const aspect = W / H; 54 | const zNear = 0.1; 55 | const zFar = 100.0; 56 | projectionMatrix = mat4.create(); 57 | 58 | // note: glmatrix.js always has the first argument 59 | // as the destination to receive the result. 60 | mat4.perspective(projectionMatrix, 61 | fieldOfView, 62 | aspect, 63 | zNear, 64 | zFar); 65 | 66 | 67 | translationMatrix = mat4.create(); 68 | rotationMatrix = mat4.create(); 69 | scaleMatrix = mat4.create(); 70 | modelMatrix = mat4.create(); 71 | // Now move the drawing position a bit to where we want to 72 | // start drawing the square. 73 | mat4.translate( 74 | translationMatrix, // destination matrix 75 | translationMatrix, // matrix to translate 76 | [-0.0, 0.0, -6.0]); // amount to translate 77 | 78 | 79 | mat4.rotate( 80 | rotationMatrix, // destination matrix 81 | rotationMatrix, // matrix to rotate 82 | Math.PI * .2 , // amount it rotates each frame 83 | [0, 0, 1] // the axis it rotates around: the center of the square 84 | ); 85 | 86 | mat4.scale( 87 | scaleMatrix, // destination matrix 88 | scaleMatrix, // matrix to rotate 89 | [2, .5, 1.5]); // axis to rotate around 90 | 91 | 92 | // Even though we aren't drawing anything really fancy, 93 | // we have to tell the GL Context how much of the screen we are drawing 94 | positionLocation = gl.getAttribLocation(program, "a_position"); 95 | positionBuffer = gl.createBuffer(); 96 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 97 | 98 | 99 | /* 100 | New: we aren;'t building a cube this time, 101 | but a more abstract shape. The coordinates are tweaked so that 102 | they work with TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN. 103 | */ 104 | 105 | gl.bufferData( 106 | gl.ARRAY_BUFFER, 107 | new Float32Array([ 108 | 0.0, -1.0, 0.0, 109 | 0.5, 0.0, 0.5, 110 | -0.5, 0.0, 0.5, 111 | 112 | 0.0, 0.0, 0.25, 113 | -1.0, 0.0, -0.5, 114 | 0.0, 1.0, -0.5, 115 | 116 | 0.0, 0.0, -1.0, 117 | 0.25, 1.0, -1.5, 118 | 1.0, 0.0, -1.5 119 | 120 | ]), 121 | gl.STATIC_DRAW 122 | ); 123 | gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); 124 | gl.enableVertexAttribArray(positionLocation); 125 | 126 | colorLocation = gl.getAttribLocation(program, "a_color"); 127 | gl.enableVertexAttribArray(colorLocation); 128 | colorBuffer = gl.createBuffer(); 129 | gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 130 | gl.bufferData(gl.ARRAY_BUFFER, 131 | // we send over a color for each vertex 132 | new Float32Array([ 133 | 1.0, 1.0, 1.0, 1.0, // white 134 | 1.0, 0.0, 0.0, 1.0, // red 135 | 0.0, 1.0, 0.0, 1.0, // green 136 | 137 | 0.0, 0.0, 1.0, 1.0, // blue, 138 | 1.0, 0.5, 0.0, 1.0, // orange 139 | 0.5, 0.0, 1.0, 1.0, // violet 140 | 141 | 1.0, 1.0, 0.0, 1.0, // yellow 142 | 0.0, 1.0, 1.0, 1.0, // cyan 143 | 1.0, 0.0, 1.0, 1.0, // magenta 144 | ]), 145 | gl.STATIC_DRAW); 146 | gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0); 147 | gl.enableVertexAttribArray(colorLocation); 148 | 149 | 150 | gl.uniformMatrix4fv(projectionUniform, false, projectionMatrix); 151 | 152 | 153 | } 154 | 155 | 156 | 157 | 158 | function draw() { 159 | // Set clear color to black, fully opaque 160 | gl.clearColor(0.0, 0.0, 0.0, 1.0); 161 | gl.clearDepth(1.0); 162 | // Clear the color buffer with specified clear color 163 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 164 | 165 | var elapsed = Date.now() - startTime; 166 | 167 | // // rotate the square a little each time 168 | mat4.rotate( 169 | rotationMatrix, // destination matrix 170 | rotationMatrix, // matrix to rotate 171 | Math.PI * .01 , // amount it rotates each frame 172 | // [0, 0, 1] // the axis it rotates around: the center of the square 173 | // [0, 1, 0] // rotate around a vertical axis 174 | // [0, 1, 1] // rotate around a tilting axis 175 | [(Math.cos(elapsed * .001)+1)*.5, .5, 1] // rotate around a moving axis 176 | ); 177 | 178 | 179 | 180 | mat4.multiply( 181 | modelMatrix, // the results go here 182 | translationMatrix, // when you multiply this matrix 183 | rotationMatrix // by this matrix 184 | ); 185 | 186 | // mat4.multiply( 187 | // modelMatrix, // the results go here 188 | // modelMatrix, // even when we are multiplying the same matrix 189 | // scaleMatrix // by a different matrix 190 | // ); 191 | 192 | 193 | gl.uniformMatrix4fv(modelUniform, false, modelMatrix); 194 | 195 | // New: try different ways of grouping the vertices we pass to the shader 196 | gl.drawArrays(gl.TRIANGLES, 0, 9); 197 | // gl.drawArrays(gl.TRIANGLE_STRIP, 0, 9); 198 | // gl.drawArrays(gl.TRIANGLE_FAN, 0, 9); 199 | // gl.drawArrays(gl.LINES, 0, 9); 200 | // gl.drawArrays(gl.LINE_STRIP, 0, 9); 201 | // gl.drawArrays(gl.LINE_LOOP, 0, 9); 202 | // gl.drawArrays(gl.POINTS, 0, 9); 203 | } 204 | 205 | 206 | 207 | 208 | 209 | 210 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 211 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 212 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 213 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 214 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 215 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 216 | 217 | 218 | // load files 219 | fetch('frag.glsl') 220 | .then(function(response) { 221 | return response.text(); 222 | }).then(fragShaderText=>{ 223 | // console.log(fragShaderText) 224 | fetch('vert.glsl') 225 | .then(function(response) { 226 | return response.text(); 227 | }).then(vertShaderText=>{ 228 | // console.log(vertShaderText); 229 | compileGL(fragShaderText, vertShaderText); 230 | initGLData(); 231 | startTime = Date.now(); 232 | setInterval(requestDraw, 33); 233 | }); 234 | }); 235 | 236 | 237 | 238 | // build our program 239 | function compileGL(fragShaderText, vertShaderText) { 240 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 241 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 242 | program = gl.createProgram(); 243 | gl.attachShader(program, vert); 244 | gl.attachShader(program, frag); 245 | gl.linkProgram(program); 246 | gl.useProgram(program); 247 | } 248 | 249 | function requestDraw() { 250 | requestAnimationFrame(draw); 251 | } 252 | 253 | // straight outta mozilla 254 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 255 | function loadShader(gl, type, source) { 256 | const shader = gl.createShader(type); 257 | // Send the source to the shader object 258 | gl.shaderSource(shader, source); 259 | // Compile the shader program 260 | gl.compileShader(shader); 261 | // See if it compiled successfully 262 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 263 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 264 | gl.deleteShader(shader); 265 | return null; 266 | } 267 | return shader; 268 | } 269 | 270 | 271 | })(); 272 | 273 | -------------------------------------------------------------------------------- /shader_04.4/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | uniform mat4 u_model; 11 | uniform mat4 u_projection; 12 | 13 | void main() { 14 | gl_Position = u_projection * u_model * a_position; 15 | // New: should we decide to render points, how big should they be? 16 | gl_PointSize = 10.0; 17 | v_color = a_color; 18 | } -------------------------------------------------------------------------------- /shader_04.5/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_04.5/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | positionLocation, 9 | colorLocation, 10 | positionBuffer, 11 | colorBuffer, 12 | 13 | points, 14 | 15 | 16 | activePositions 17 | ; 18 | 19 | const cos = Math.cos, 20 | sin = Math.sin; 21 | 22 | // make the canvas fill the window 23 | canvas.width = W; 24 | canvas.height = H; 25 | 26 | 27 | 28 | function initGLData() { 29 | // now we can get some config info 30 | gl.viewport(0, 0, W, H); 31 | 32 | // We will be positioning things in 3d space, so tell the program 33 | // how we want it to handle things behind or in front of each other 34 | gl.enable(gl.DEPTH_TEST); 35 | gl.depthFunc(gl.LEQUAL); 36 | 37 | 38 | positionLocation = gl.getAttribLocation(program, "a_position"); 39 | positionBuffer = gl.createBuffer(); 40 | 41 | // New: create some points that will rotate around 42 | points = []; 43 | for (var i=0; i< 9; i++) { 44 | let xrot = .1 * (1 - Math.random()), 45 | yrot = .1 * (1 - Math.random()), 46 | radius = 1 - Math.random(); 47 | radius += radius < 0 ? -.25 : .25; 48 | radius *= .5; 49 | var point = { 50 | "x_rotation_amount" : xrot, 51 | "y_rotation_amount" : yrot, 52 | "x_rotation" : xrot, 53 | "y_rotation" : yrot, 54 | "radius" : radius, 55 | "x" : cos(xrot) * cos(yrot) * radius, 56 | "y" : sin(yrot) * radius, 57 | "z" : sin(xrot) * cos(yrot) * radius 58 | } 59 | points.push(point); 60 | } 61 | 62 | 63 | activePositions = []; 64 | for (var i=0; i{ 156 | // console.log(fragShaderText) 157 | fetch('vert.glsl') 158 | .then(function(response) { 159 | return response.text(); 160 | }).then(vertShaderText=>{ 161 | // console.log(vertShaderText); 162 | compileGL(fragShaderText, vertShaderText); 163 | initGLData(); 164 | setInterval(requestDraw, 33); 165 | }); 166 | }); 167 | 168 | 169 | 170 | // build our program 171 | function compileGL(fragShaderText, vertShaderText) { 172 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 173 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 174 | program = gl.createProgram(); 175 | gl.attachShader(program, vert); 176 | gl.attachShader(program, frag); 177 | gl.linkProgram(program); 178 | gl.useProgram(program); 179 | } 180 | 181 | function requestDraw() { 182 | requestAnimationFrame(draw); 183 | } 184 | 185 | // straight outta mozilla 186 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 187 | function loadShader(gl, type, source) { 188 | const shader = gl.createShader(type); 189 | // Send the source to the shader object 190 | gl.shaderSource(shader, source); 191 | // Compile the shader program 192 | gl.compileShader(shader); 193 | // See if it compiled successfully 194 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 195 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 196 | gl.deleteShader(shader); 197 | return null; 198 | } 199 | return shader; 200 | } 201 | 202 | 203 | })(); 204 | 205 | -------------------------------------------------------------------------------- /shader_04.5/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | void main() { 11 | gl_Position = a_position; 12 | gl_PointSize = 10.0; 13 | v_color = a_color; 14 | } -------------------------------------------------------------------------------- /shader_04.6/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | void main(){ 8 | gl_FragColor = v_color; 9 | } -------------------------------------------------------------------------------- /shader_04.6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_04.6/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | 8 | positionLocation, 9 | colorLocation, 10 | positionBuffer, 11 | colorBuffer, 12 | 13 | // New: track how many frames have gone on 14 | frameCount, 15 | frameCountUniformLocation 16 | 17 | 18 | ; 19 | 20 | const cos = Math.cos, 21 | sin = Math.sin, 22 | POINT_COUNT = 9; 23 | 24 | // make the canvas fill the window 25 | canvas.width = W; 26 | canvas.height = H; 27 | 28 | 29 | 30 | function initGLData() { 31 | // now we can get some config info 32 | gl.viewport(0, 0, W, H); 33 | 34 | // We will be positioning things in 3d space, so tell the program 35 | // how we want it to handle things behind or in front of each other 36 | gl.enable(gl.DEPTH_TEST); 37 | gl.depthFunc(gl.LEQUAL); 38 | 39 | // New: we need to pass the number of frames to the shader, 40 | // so that it can calculate the updated position of each particle 41 | frameCountUniformLocation = gl.getUniformLocation(program, "u_frameCount"); 42 | frameCount = 0; 43 | 44 | positionLocation = gl.getAttribLocation(program, "a_position"); 45 | positionBuffer = gl.createBuffer(); 46 | 47 | // New: we don't need to save the points so that they can 48 | // be adjusted in the draw loop. And the variables that 49 | // track their current position aren't needed either. 50 | var points = []; 51 | for (var i=0; i < POINT_COUNT; i++) { 52 | let xrot = .1 * (1 - Math.random()), 53 | yrot = .1 * (1 - Math.random()), 54 | radius = 1 - Math.random(); 55 | radius += radius < 0 ? -.25 : .25; 56 | radius *= .5; 57 | var point = { 58 | "x_rotation_amount" : xrot, 59 | "y_rotation_amount" : yrot, 60 | "radius" : radius 61 | } 62 | points.push(point); 63 | } 64 | 65 | // New: Before, we declared activePositions globally so we could 66 | // update it every time we called draw. Now we can declare it locally, 67 | // and just pass it once to the shader. 68 | // Instead of tracking actual positions, it now tracks the parameters 69 | // required to calculate each point's position. 70 | var activePositions = []; 71 | for (var i=0; i{ 142 | // console.log(fragShaderText) 143 | fetch('vert.glsl') 144 | .then(function(response) { 145 | return response.text(); 146 | }).then(vertShaderText=>{ 147 | // console.log(vertShaderText); 148 | compileGL(fragShaderText, vertShaderText); 149 | initGLData(); 150 | setInterval(requestDraw, 33); 151 | }); 152 | }); 153 | 154 | 155 | 156 | // build our program 157 | function compileGL(fragShaderText, vertShaderText) { 158 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 159 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 160 | program = gl.createProgram(); 161 | gl.attachShader(program, vert); 162 | gl.attachShader(program, frag); 163 | gl.linkProgram(program); 164 | gl.useProgram(program); 165 | } 166 | 167 | function requestDraw() { 168 | requestAnimationFrame(draw); 169 | } 170 | 171 | // straight outta mozilla 172 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 173 | function loadShader(gl, type, source) { 174 | const shader = gl.createShader(type); 175 | // Send the source to the shader object 176 | gl.shaderSource(shader, source); 177 | // Compile the shader program 178 | gl.compileShader(shader); 179 | // See if it compiled successfully 180 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 181 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 182 | gl.deleteShader(shader); 183 | return null; 184 | } 185 | return shader; 186 | } 187 | 188 | 189 | })(); 190 | 191 | -------------------------------------------------------------------------------- /shader_04.6/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | // New: how many frames have been drawn 11 | uniform float u_frameCount; 12 | 13 | void main() { 14 | // New: in this version, a_position tracks the parameters 15 | // used to calculate the point's position" 16 | // how much to rotate around the x axis every frame 17 | // how much to rotate around the y axis every frame 18 | // the distance from the center. 19 | // where this point lies in the list of vertices 20 | // GLSL lets you access these paramters under different names, 21 | // but they all reference the same data points. The different 22 | // names can be intuitive for whatever you are working with. 23 | // You can use rgba when working with color, xyzw when working 24 | // with locations, and stpq when working with othter stuff. 25 | // Why not stuv instead of stpq? It's not entirely clear. 26 | // Here, we use s, t, and p (and maybe q), since the stufff 27 | // in a_position is not the actual x, y, and z coordinates 28 | // of the point. 29 | float x_rotation = a_position.s * u_frameCount; 30 | float y_rotation = a_position.t * u_frameCount; 31 | float radius = a_position.p; 32 | float x = cos(x_rotation) * cos(y_rotation) * radius; 33 | float y = sin(y_rotation) * radius; 34 | float z = sin(x_rotation) * cos(y_rotation) * radius; 35 | 36 | gl_Position = vec4(x, y, z, 1.0); 37 | gl_PointSize = 10.0; 38 | // gl_PointSize = a_position.q * 2.0; 39 | v_color = a_color; 40 | } -------------------------------------------------------------------------------- /shader_05.0/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | // New: the image 8 | uniform sampler2D u_image; 9 | 10 | void main(){ 11 | vec4 imageColor = texture2D(u_image, gl_PointCoord.st); 12 | gl_FragColor = imageColor; 13 | } -------------------------------------------------------------------------------- /shader_05.0/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_05.0/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | // New: when we create the WebGL context, we can pass it some options. 4 | // What we will be doing later is using an image to draw each point. 5 | // The images have a transparent background, so we want the shader to 6 | // mix colors when those images overlap. We tell the shader to do that 7 | // by passing in the "premultipliedAlpha : false" option 8 | gl = canvas.getContext('webgl', {premultipliedAlpha: false}), 9 | program, 10 | W = window.innerWidth, 11 | H = window.innerHeight, 12 | 13 | 14 | frameCount, 15 | frameCountUniformLocation, 16 | 17 | // New: the image we will use to draw each point / particle. 18 | dotTexture 19 | ; 20 | 21 | const cos = Math.cos, 22 | sin = Math.sin, 23 | POINT_COUNT = 9; 24 | 25 | // make the canvas fill the window 26 | canvas.width = W; 27 | canvas.height = H; 28 | 29 | 30 | 31 | function initGLData() { 32 | // now we can get some config info 33 | gl.viewport(0, 0, W, H); 34 | 35 | // New: the images we use to blend particles have transparent 36 | // backgrounds. FOr this to work as expected, we need to turn off 37 | // depth testing. If we don't the backgrounds don't show up as 38 | // transparent: they show up as black and block other particles. 39 | gl.disable(gl.DEPTH_TEST); 40 | // tell the shader that we want blending 41 | gl.enable(gl.BLEND); 42 | // and specify just how we want the blending to work 43 | gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA); 44 | gl.blendEquation(gl.FUNC_ADD); 45 | // there are many options for how you want blending to work 46 | // gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); 47 | // gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE) 48 | 49 | 50 | // New: pass an image to the shader so it can be used to draw the points. 51 | // where is it gonna go? 52 | var imageUniform = gl.getUniformLocation(program, "u_image"); 53 | // Images are referred to as textures, and setting one up 54 | // is a bureaucratic operation. 55 | // Create a texture, and tell the shader that it is the one you want 56 | // to work with. Note that it is not yet attached to our image. 57 | var texture = gl.createTexture(); 58 | gl.bindTexture(gl.TEXTURE_2D, texture); 59 | // Set up texture so we can render any size image and so we are 60 | // working with pixels. 61 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 62 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 63 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 64 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 65 | // now tell the texture to use our image 66 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, dotTexture); 67 | // and tell the shader that we want to use this image for the uniform 68 | gl.uniform1i(imageUniform, 1); 69 | // and that this is the image to use for now 70 | gl.activeTexture(gl.TEXTURE1); 71 | gl.bindTexture(gl.TEXTURE_2D, texture); 72 | 73 | 74 | 75 | frameCountUniformLocation = gl.getUniformLocation(program, "u_frameCount"); 76 | frameCount = 0; 77 | 78 | var positionLocation = gl.getAttribLocation(program, "a_position"); 79 | var positionBuffer = gl.createBuffer(); 80 | 81 | var points = []; 82 | for (var i=0; i < POINT_COUNT; i++) { 83 | let xrot = .1 * (1 - Math.random()), 84 | yrot = .1 * (1 - Math.random()), 85 | radius = 1 - Math.random(); 86 | radius += radius < 0 ? -.25 : .25; 87 | radius *= .5; 88 | var point = { 89 | "x_rotation_amount" : xrot, 90 | "y_rotation_amount" : yrot, 91 | "radius" : radius 92 | } 93 | points.push(point); 94 | } 95 | 96 | var activePositions = []; 97 | for (var i=0; i { 166 | // new: fetch the shaders after the image is loaded 167 | // load files 168 | fetch('frag.glsl') 169 | .then(function(response) { 170 | return response.text(); 171 | }).then(fragShaderText=>{ 172 | // console.log(fragShaderText) 173 | fetch('vert.glsl') 174 | .then(function(response) { 175 | return response.text(); 176 | }).then(vertShaderText=>{ 177 | // console.log(vertShaderText); 178 | compileGL(fragShaderText, vertShaderText); 179 | initGLData(); 180 | setInterval(requestDraw, 33); 181 | }); 182 | }); 183 | }); 184 | dotTexture.src = "../images/dot.png"; 185 | 186 | 187 | 188 | // build our program 189 | function compileGL(fragShaderText, vertShaderText) { 190 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 191 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 192 | program = gl.createProgram(); 193 | gl.attachShader(program, vert); 194 | gl.attachShader(program, frag); 195 | gl.linkProgram(program); 196 | gl.useProgram(program); 197 | } 198 | 199 | function requestDraw() { 200 | requestAnimationFrame(draw); 201 | } 202 | 203 | // straight outta mozilla 204 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 205 | function loadShader(gl, type, source) { 206 | const shader = gl.createShader(type); 207 | // Send the source to the shader object 208 | gl.shaderSource(shader, source); 209 | // Compile the shader program 210 | gl.compileShader(shader); 211 | // See if it compiled successfully 212 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 213 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 214 | gl.deleteShader(shader); 215 | return null; 216 | } 217 | return shader; 218 | } 219 | 220 | 221 | })(); 222 | 223 | -------------------------------------------------------------------------------- /shader_05.0/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | attribute vec4 a_color; 7 | 8 | varying vec4 v_color; 9 | 10 | uniform float u_frameCount; 11 | 12 | void main() { 13 | float x_rotation = a_position.x * u_frameCount; 14 | float y_rotation = a_position.y * u_frameCount; 15 | float radius = a_position.z; 16 | float x = cos(x_rotation) * cos(y_rotation) * radius; 17 | float y = sin(y_rotation) * radius; 18 | float z = sin(x_rotation) * cos(y_rotation) * radius; 19 | 20 | gl_Position = vec4(x, y, z, 1.0); 21 | gl_PointSize = 32.0; 22 | // gl_PointSize = a_position.w * 10.0; 23 | v_color = a_color; 24 | } -------------------------------------------------------------------------------- /shader_05.1/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | uniform sampler2D u_image; 8 | 9 | varying vec2 v_imagePosition; 10 | 11 | 12 | void main(){ 13 | vec4 color = texture2D(u_image, v_imagePosition); 14 | // copy the color from the image, and use it for the current pixel 15 | gl_FragColor = color; 16 | // or use the red channel to drive how dark a pixel is 17 | // and use the position in the screen to drive the rbg value 18 | // float bw = color.r; 19 | // vec2 st = gl_FragCoord.xy/1024.0; 20 | // gl_FragColor = vec4(0.0, st.x * bw, st.y * bw, 1.0); 21 | // Or use the position on the face of the cube to drive the rbg value 22 | // vec2 st2 = v_imagePosition.xy; 23 | // gl_FragColor = vec4(0.0, st2.x * bw, st2.y * bw, 1.0); 24 | // or combine them 25 | // gl_FragColor = vec4(st2.x * bw, st.x * st2.y * bw, st.y * bw, 1.0); 26 | } -------------------------------------------------------------------------------- /shader_05.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_05.1/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } -------------------------------------------------------------------------------- /shader_05.2/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | uniform sampler2D u_image; 8 | 9 | varying vec2 v_imagePosition; 10 | 11 | 12 | void main(){ 13 | vec4 color = texture2D(u_image, v_imagePosition); 14 | // copy the color from the image, and use it for the current pixel 15 | gl_FragColor = color; 16 | } -------------------------------------------------------------------------------- /shader_05.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_05.2/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } -------------------------------------------------------------------------------- /shader_05.3/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | uniform sampler2D u_image; 8 | 9 | varying vec2 v_imagePosition; 10 | 11 | 12 | void main(){ 13 | vec4 color = texture2D(u_image, v_imagePosition); 14 | // copy the color from the image, and use it for the current pixel 15 | gl_FragColor = color; 16 | // or replace it with nicer colors 17 | // if (color.a >= .5) { 18 | // gl_FragColor = vec4(0.4, 0.4, 0.4, 1.0); 19 | // } else { 20 | // gl_FragColor = vec4(1.0); 21 | // } 22 | } -------------------------------------------------------------------------------- /shader_05.3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_05.3/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {premultipliedAlpha: false}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | 9 | positionLocation, 10 | 11 | modelUniform, 12 | 13 | 14 | projectionUniform, 15 | projectionMatrix, 16 | 17 | translationMatrix, 18 | rotationMatrix, 19 | scaleMatrix, 20 | 21 | modelMatrix, 22 | 23 | faceTexture 24 | 25 | 26 | ; 27 | 28 | 29 | const ARC_PRECISION = 50; 30 | 31 | 32 | // make the canvas fill the window 33 | canvas.width = W; 34 | canvas.height = H; 35 | 36 | 37 | 38 | function initGLData() { 39 | // now we can get some config info 40 | gl.viewport(0, 0, W, H); 41 | 42 | modelUniform = gl.getUniformLocation(program, "u_model"); 43 | gl.enable(gl.DEPTH_TEST); 44 | gl.depthFunc(gl.LEQUAL); 45 | 46 | // tell the shader that we want blending 47 | // gl.enable(gl.BLEND); 48 | // // and specify just how we want the blending to work 49 | // // gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA); 50 | // gl.blendFunc(gl.SRC_ALPHA, gl.DST_ALPHA); 51 | // gl.blendEquation(gl.FUNC_ADD); 52 | 53 | // straight from mozilla! 54 | // Create a perspective matrix, a special matrix that is 55 | // used to simulate the distortion of perspective in a camera. 56 | // Our field of view is 45 degrees, with a width/height 57 | // ratio that matches the display size of the canvas 58 | // and we only want to see objects between 0.1 units 59 | // and 100 units away from the camera. 60 | const fieldOfView = 45 * Math.PI / 180; // in radians 61 | const aspect = W / H; 62 | const zNear = 0.1; 63 | const zFar = 100.0; 64 | projectionMatrix = mat4.create(); 65 | projectionUniform = gl.getUniformLocation(program, "u_projection"); 66 | 67 | // note: with glmatrix.js, the first parameter 68 | // is always the matrix that you are writing to. Any values 69 | // in that matrix will be overwritten. 70 | mat4.perspective(projectionMatrix, 71 | fieldOfView, 72 | aspect, 73 | zNear, 74 | zFar); 75 | 76 | gl.uniformMatrix4fv(projectionUniform, false, projectionMatrix); 77 | 78 | translationMatrix = mat4.create(); 79 | rotationMatrix = mat4.create(); 80 | scaleMatrix = mat4.create(); 81 | modelMatrix = mat4.create(); 82 | // Now move the drawing position a bit to where we want to 83 | // start drawing the square. 84 | mat4.translate( 85 | translationMatrix, // the matrix that tracks the translated location 86 | translationMatrix, // matrix to start from (which is not moved at this point) 87 | [-0.0, 0.0, -6.0]); // amount to translate 88 | 89 | mat4.rotate( 90 | rotationMatrix, // the matrix that tracks the rotation 91 | rotationMatrix, // matrix to to start from (unrotated here) 92 | Math.PI, // amount to rotate it 93 | [1, 0, 0] // the axis it rotates around: the center of the square 94 | ); 95 | 96 | mat4.scale( 97 | scaleMatrix, // the matrix that tracks the rotation 98 | scaleMatrix, // matrix to to start from (unrotated here) 99 | [1.5, 1.5, 1.5] 100 | ); 101 | 102 | 103 | 104 | positionLocation = gl.getAttribLocation(program, "a_position"); 105 | var positionBuffer = gl.createBuffer(); 106 | gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 107 | 108 | var coords = [], 109 | textureCoords = []; 110 | const cos = Math.cos, 111 | sin = Math.sin, 112 | PI = Math.PI, 113 | TAU = PI * 2, 114 | HALF_PI = PI * .5, 115 | INCREMENT = PI / ARC_PRECISION, 116 | // because floats can get imprecise, allow ourselves to 117 | // overshoot the last row a little bit 118 | LIMIT = HALF_PI + INCREMENT/2; 119 | pointCount = 0; 120 | 121 | 122 | for (var lat = -HALF_PI + INCREMENT; lat <= LIMIT; lat += INCREMENT) { 123 | var previousRow = lat - INCREMENT, 124 | prevY = sin(previousRow), 125 | currentY = sin(lat), 126 | cosPrevious = cos(previousRow), 127 | cosCurrent = cos(lat), 128 | previousTextureY = (previousRow+HALF_PI)/PI, 129 | currentTextureY = (lat+HALF_PI)/PI; 130 | 131 | for (var lon = 0; lon <= TAU + .001; lon += INCREMENT) { 132 | var cosLon = cos(lon), 133 | sinLon = sin(lon), 134 | previousX = cosPrevious * cosLon, 135 | currentX = cosCurrent * cosLon, 136 | previousZ = cosPrevious * sinLon, 137 | currentZ = cosCurrent * sinLon, 138 | textureX = lon/TAU; 139 | coords.push(previousX); 140 | coords.push(prevY); 141 | coords.push(previousZ); 142 | textureCoords.push(textureX); 143 | textureCoords.push(previousTextureY); 144 | pointCount++; 145 | coords.push(currentX); 146 | coords.push(currentY); 147 | coords.push(currentZ); 148 | textureCoords.push(textureX); 149 | textureCoords.push(currentTextureY); 150 | pointCount++; 151 | } 152 | } 153 | 154 | 155 | gl.bufferData( 156 | gl.ARRAY_BUFFER, 157 | new Float32Array(coords), 158 | gl.STATIC_DRAW 159 | ); 160 | gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0); 161 | gl.enableVertexAttribArray(positionLocation); 162 | 163 | // New: Our goal here is to place the same image 164 | // on each face of the cube. So for each corner 165 | // of each triangle above, we have to tell it which 166 | // corner of the image to use. 167 | var imagePositionBuffer = gl.createBuffer(); 168 | gl.bindBuffer(gl.ARRAY_BUFFER, imagePositionBuffer); 169 | gl.bufferData( 170 | gl.ARRAY_BUFFER, 171 | new Float32Array(textureCoords), 172 | gl.STATIC_DRAW 173 | ); 174 | var imagePositionLocation = gl.getAttribLocation(program, "a_imagePosition"); 175 | gl.enableVertexAttribArray(imagePositionLocation); 176 | gl.vertexAttribPointer(imagePositionLocation, 2, gl.FLOAT, false, 0, 0); 177 | 178 | // pass an image to the shader so it can be used to draw the points. 179 | // where is it gonna go? 180 | var imageUniform = gl.getUniformLocation(program, "u_image"); 181 | // Images are referred to as textures, and setting one up 182 | // is a bureaucratic operation. 183 | // Create a texture, and tell the shader that it is the one you want 184 | // to work with. Note that it is not yet attached to our image. 185 | var texture = gl.createTexture(); 186 | gl.bindTexture(gl.TEXTURE_2D, texture); 187 | // Set up texture so we can render any size image and so we are 188 | // working with pixels. 189 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 190 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 191 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 192 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 193 | // Upload the image into the texture. 194 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, faceTexture); 195 | // and tell the shader that we want to use this image for the uniform 196 | gl.uniform1i(imageUniform, 1); 197 | // and that this is the image to use for now 198 | gl.activeTexture(gl.TEXTURE1); 199 | gl.bindTexture(gl.TEXTURE_2D, texture); 200 | 201 | } 202 | 203 | 204 | 205 | 206 | function draw() { 207 | // Set clear color to black, fully opaque 208 | gl.clearColor(1.0, 1.0, 1.0, 0.1); 209 | gl.clearDepth(1.0); 210 | // Clear the color buffer with specified clear color 211 | gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 212 | 213 | 214 | elapsed = Date.now() - startTime; 215 | 216 | 217 | 218 | // and store it in the modelMatrix 219 | mat4.multiply(modelMatrix, translationMatrix, rotationMatrix); 220 | 221 | // if you want to scale the positions as well, 222 | // mulitply the model matrix by the scale matrix 223 | mat4.multiply(modelMatrix, modelMatrix, scaleMatrix); 224 | 225 | // order matters! Instead of translation and rotation first, try scaling and rotation first 226 | // mat4.multiply(modelMatrix, rotationMatrix, scaleMatrix); 227 | // mat4.multiply(modelMatrix, modelMatrix, translationMatrix); 228 | 229 | // rotate the square a little each time 230 | mat4.rotate( 231 | rotationMatrix, // destination matrix 232 | rotationMatrix, // matrix to rotate 233 | Math.PI * -.005, // amount it rotates each frame 234 | // [0, 0, 1] // the axis it rotates around: the center of the front face 235 | [0, 1, 0] // the axis it rotates around: a vertical axis 236 | // [0, 1, 1] // the axis it rotates around: tilted 237 | // [(Math.cos(elapsed * .001)+1)*.5, .5, 1] // the axis it rotates around: a moving axis 238 | ); 239 | 240 | 241 | gl.uniformMatrix4fv(modelUniform, false, modelMatrix); 242 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, pointCount); 243 | } 244 | 245 | 246 | 247 | 248 | 249 | 250 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 251 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 252 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 253 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 254 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 255 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 256 | 257 | 258 | // load files 259 | 260 | faceTexture = new Image(); 261 | faceTexture.addEventListener('load', ()=> { 262 | // new: fetch the shaders after the image is loaded 263 | // load files 264 | fetch('frag.glsl') 265 | .then(function(response) { 266 | return response.text(); 267 | }).then(fragShaderText=>{ 268 | // console.log(fragShaderText) 269 | fetch('vert.glsl') 270 | .then(function(response) { 271 | return response.text(); 272 | }).then(vertShaderText=>{ 273 | // console.log(vertShaderText); 274 | compileGL(fragShaderText, vertShaderText); 275 | initGLData(); 276 | startTime = Date.now(); 277 | setInterval(requestDraw, 33); 278 | }); 279 | }); 280 | }); 281 | // faceTexture.src = "../images/bumpy.jpeg"; 282 | // faceTexture.src = "../images/rust.jpg"; 283 | // faceTexture.src = "../images/f.png"; 284 | // faceTexture.src = "../images/world.png"; 285 | // faceTexture.src = "../images/dnb_land_ocean_ice.2012.3600x1800.jpg"; 286 | faceTexture.src = "../images/nasa_blue_marble.4096.jpg"; 287 | // dnb_land_ocean_ice.2012.3600x1800.jpg courtesy of NASA 288 | // https://visibleearth.nasa.gov/view.php?id=79765 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | // build our program 297 | function compileGL(fragShaderText, vertShaderText) { 298 | var frag = loadShader(gl, gl.FRAGMENT_SHADER, fragShaderText); 299 | var vert = loadShader(gl, gl.VERTEX_SHADER, vertShaderText); 300 | program = gl.createProgram(); 301 | gl.attachShader(program, vert); 302 | gl.attachShader(program, frag); 303 | gl.linkProgram(program); 304 | gl.useProgram(program); 305 | } 306 | 307 | function requestDraw() { 308 | requestAnimationFrame(draw); 309 | } 310 | 311 | // straight outta mozilla 312 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 313 | function loadShader(gl, type, source) { 314 | const shader = gl.createShader(type); 315 | // Send the source to the shader object 316 | gl.shaderSource(shader, source); 317 | // Compile the shader program 318 | gl.compileShader(shader); 319 | // See if it compiled successfully 320 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 321 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 322 | gl.deleteShader(shader); 323 | return null; 324 | } 325 | return shader; 326 | } 327 | 328 | 329 | })(); 330 | 331 | -------------------------------------------------------------------------------- /shader_05.3/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } -------------------------------------------------------------------------------- /shader_05.4/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | 7 | uniform sampler2D u_dayImage; 8 | uniform sampler2D u_nightImage; 9 | uniform vec2 u_resolution; 10 | 11 | varying vec2 v_imagePosition; 12 | 13 | 14 | void main(){ 15 | vec4 dayColor = texture2D(u_dayImage, v_imagePosition); 16 | vec4 nightColor = texture2D(u_nightImage, v_imagePosition); 17 | // copy the color from the image, and use it for the current pixel 18 | // gl_FragColor = dayColor; 19 | // gl_FragColor = dayColor; 20 | vec2 st = gl_FragCoord.xy / u_resolution; 21 | if (st.x >= 0.6) { 22 | gl_FragColor = dayColor; 23 | } else if (st.x < 0.5) { 24 | gl_FragColor = nightColor; 25 | } else { 26 | float f = smoothstep(0.5, 0.6, st.x); 27 | gl_FragColor = ((1.0 - f) * nightColor + f * dayColor); 28 | } 29 | } -------------------------------------------------------------------------------- /shader_05.4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_05.4/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } -------------------------------------------------------------------------------- /shader_06.0/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | varying vec2 v_imagePosition; 7 | 8 | uniform sampler2D u_image; 9 | uniform sampler2D u_dataColors; 10 | 11 | 12 | void main(){ 13 | vec4 color = texture2D(u_image, v_imagePosition); 14 | gl_FragColor = color; 15 | 16 | 17 | /* 18 | To see the country lookup values, we can isolate the red channel. 19 | Oceans and things that are not countries are transparent. 20 | */ 21 | // if (color.a <= 0.5) { 22 | // gl_FragColor = vec4(1.0); 23 | // } else { 24 | // gl_FragColor = vec4(color.r, 0.0, 0.0, 1.0); 25 | // } 26 | 27 | 28 | /* 29 | We can also test whether the country lookup is working 30 | */ 31 | // if (color.a <= 0.5) { 32 | // gl_FragColor = vec4(1.0); 33 | // } else { 34 | // // get the color, and scale up from the shader range of 0-1 to 35 | // // integers in the 0-255 range 36 | // float countryColor = floor(color.r * 255.0); 37 | // // Looking at the data file population_2018.json, the country at 38 | // // index position 3.0 is China, 39 | // // 1.0 is the USA 40 | // // 24.0 is Chile 41 | // // 33.0 is Ireland 42 | // // 53.0 is Egypt 43 | // // 212 is New Guinea 44 | // if (countryColor == 212.0) { 45 | // gl_FragColor = vec4(0.0, 0.5, 1.0, 1.0); 46 | // } else { 47 | // gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); 48 | // } 49 | // } 50 | } -------------------------------------------------------------------------------- /shader_06.0/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_06.0/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } -------------------------------------------------------------------------------- /shader_06.1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /shader_06.1/main.js: -------------------------------------------------------------------------------- 1 | (()=>{ 2 | var canvas = document.getElementById('shade'), 3 | gl = canvas.getContext('webgl', {premultipliedAlpha: false}), 4 | program, 5 | W = window.innerWidth, 6 | H = window.innerHeight, 7 | startTime, 8 | 9 | dataColorUniform, 10 | 11 | countryRGB, 12 | 13 | dataColorCanvas, 14 | dataColorCtx, 15 | dataColorImg = new Image(), 16 | dataTexture, 17 | 18 | popData 19 | 20 | ; 21 | 22 | 23 | 24 | 25 | 26 | 27 | function draw() { 28 | 29 | // Set clear color to black, fully opaque 30 | 31 | } 32 | 33 | 34 | function colorByPopulation() { 35 | // what is the max population? 36 | var maxTotal = 0, 37 | maxUrbanPct = 0, 38 | maxRuralPct = 0; 39 | popData.forEach(item=>{ 40 | if (item.total > 0) { 41 | maxTotal = Math.max(maxTotal, item.total); 42 | maxUrbanPct = Math.max(maxUrbanPct, item.urban / item.total); 43 | maxRuralPct = Math.max(maxRuralPct, item.rural / item.total); 44 | } 45 | }); 46 | dataColorCtx.clearRect(0,0,16,16); 47 | var countryIndex = 0; 48 | for ( var y=0;y<16;y++) { 49 | for ( var x=0;x<16;x++) { 50 | // we will use red, green, and blue channels to encode 51 | // total, urban and rural populations for each country. 52 | let countryData = popData[countryIndex], 53 | r = 0, 54 | g = 0, 55 | b = 0; 56 | if (countryData) { 57 | if (countryData.total > 0) { 58 | let urbanPct = countryData.urban / countryData.total, 59 | ruralPct = countryData.rural / countryData.total; 60 | // we will let 0 mean there is no data 61 | // so the lowest value will be 1, and the highest 62 | // will be 255 (or 1 + 254) 63 | r = 1 + countryData.total / maxTotal * 254; 64 | g = 1 + urbanPct / maxUrbanPct * 254; 65 | b = 1 + ruralPct / maxRuralPct * 254; 66 | } else { 67 | } 68 | } 69 | /* to see just the population in the red channel */ 70 | // let fs = 'rgb(' + Math.round(r) + ',0,0)'; 71 | /* to see just the urban population percent in the green channel */ 72 | // let fs = 'rgb(0,' + Math.round(g) + ',0)'; 73 | /* to see just the rural population percent in the blue channel */ 74 | // let fs = 'rgb(0,0,' + Math.round(b) + ')'; 75 | /* to see them all combined */ 76 | let fs = 'rgb(' + Math.round(r) + ',' + Math.round(g) + ',' + Math.round(b) + ')'; 77 | // console.log(fs, countryData ? countryData.name : '', x, y); 78 | dataColorCtx.fillStyle = fs; 79 | dataColorCtx.fillRect(x,y,1,1); 80 | countryIndex++; 81 | } 82 | } 83 | dataColorImg.src = dataColorCanvas.toDataURL(); 84 | // Append the data image to the document to inspect it 85 | var body = document.getElementById('b'); 86 | dataColorImg.style.width = '512px'; 87 | dataColorImg.style.height = '512px'; 88 | dataColorImg.style.position = 'absolute'; 89 | dataColorImg.style.top = '0'; 90 | dataColorImg.style.left = '0'; 91 | dataColorImg.style.zIndex = '1000'; 92 | body.appendChild(dataColorImg); 93 | } 94 | 95 | 96 | 97 | 98 | 99 | function initDataImage(){ 100 | countryRGB = new Float32Array(256*3); 101 | for ( var i=0;i<256;i++) { 102 | let i3 = i*3; 103 | countryRGB[i3] = 0; //Math.abs(Math.sin(Math.random() * Math.PI * 2)) * 255; 104 | countryRGB[i3+1] = 0; 105 | countryRGB[i3+2] = 0; 106 | } 107 | // create an image we can use for setting colors in the globe fragment shader 108 | dataColorCanvas = document.createElement('canvas'); 109 | var scale = 8; 110 | dataColorCanvas.width = 16 * scale; 111 | dataColorCanvas.height = 16 * scale; 112 | dataColorImg.width = 16 * scale; 113 | dataColorImg.height = 16 * scale; 114 | dataColorCtx = dataColorCanvas.getContext('2d'); 115 | dataColorCtx.scale(scale, scale); 116 | dataColorCtx.fillStyle = 'white'; 117 | dataColorCtx.fillRect(0,0,16,16); 118 | 119 | var launchShader = ()=>{ 120 | dataColorImg.removeEventListener('load', launchShader); 121 | colorByPopulation(); 122 | // setInterval(requestDraw, 33); 123 | } 124 | dataColorImg.addEventListener('load', launchShader); 125 | dataColorImg.src = dataColorCanvas.toDataURL(); 126 | } 127 | 128 | 129 | 130 | 131 | 132 | // ██████╗ ██████╗ ██████╗ ██╗███╗ ██╗ ██████╗ ███████╗████████╗██╗ ██╗███████╗███████╗ 133 | // ██╔══██╗██╔═══██╗██╔══██╗██║████╗ ██║██╔════╝ ██╔════╝╚══██╔══╝██║ ██║██╔════╝██╔════╝ 134 | // ██████╔╝██║ ██║██████╔╝██║██╔██╗ ██║██║ ███╗ ███████╗ ██║ ██║ ██║█████╗ █████╗ 135 | // ██╔══██╗██║ ██║██╔══██╗██║██║╚██╗██║██║ ██║ ╚════██║ ██║ ██║ ██║██╔══╝ ██╔══╝ 136 | // ██████╔╝╚██████╔╝██║ ██║██║██║ ╚████║╚██████╔╝ ███████║ ██║ ╚██████╔╝██║ ██║ 137 | // ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ 138 | 139 | 140 | // load files 141 | fetch('population_2018.json') 142 | .then(function(response) { 143 | return response.json(); 144 | }).then(popDataResponse=>{ 145 | popData = popDataResponse; 146 | // New: we have one more step before launching the shader. 147 | // We are going to encode our data into an image, and then 148 | // kick off the shader program. 149 | initDataImage(); 150 | }); 151 | 152 | 153 | function requestDraw() { 154 | requestAnimationFrame(draw); 155 | } 156 | 157 | // straight outta mozilla 158 | //https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Adding_2D_content_to_a_WebGL_context 159 | function loadShader(gl, type, source) { 160 | const shader = gl.createShader(type); 161 | // Send the source to the shader object 162 | gl.shaderSource(shader, source); 163 | // Compile the shader program 164 | gl.compileShader(shader); 165 | // See if it compiled successfully 166 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 167 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); 168 | gl.deleteShader(shader); 169 | return null; 170 | } 171 | return shader; 172 | } 173 | 174 | 175 | })(); 176 | 177 | -------------------------------------------------------------------------------- /shader_06.2/frag.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | varying vec4 v_color; 6 | varying vec2 v_imagePosition; 7 | 8 | uniform sampler2D u_image; 9 | uniform sampler2D u_dataColors; 10 | 11 | 12 | void main(){ 13 | vec4 color = texture2D(u_image, v_imagePosition); 14 | gl_FragColor = color; 15 | if (color.a <= 0.5) { 16 | gl_FragColor = vec4(1.0); 17 | } else { 18 | /* 19 | what country is this on the map? 20 | scale up the red channel to the 0-255 range 21 | */ 22 | float countryColor = floor(color.r * 255.0); 23 | /* What are the x and y coordinates for this country on the data image? */ 24 | float x = mod(countryColor,16.0)/16.0 + 0.5/16.0; 25 | float y = floor(countryColor/16.0)/16.0 + 0.5/16.0; 26 | /* grab the data for this country from the data image */ 27 | vec4 dataColor = texture2D(u_dataColors,vec2(x,y)); 28 | // gl_FragColor = vec4(dataColor.rgb, 1.0); 29 | /* red encodes population as a % of the largest population */ 30 | float popPct = dataColor.r; 31 | /* green encodes urban population as a % of the country's total */ 32 | float urbanPct = dataColor.g; 33 | /* blue encodes rural population as a % of the country's total */ 34 | float ruralPct = dataColor.b; 35 | // float c = popPct; 36 | float c = urbanPct; 37 | // float c = ruralPct; 38 | 39 | /* 0 indicates no data */ 40 | if (c < 1.0/ 255.0) { 41 | /* if there's no data, color it dark gray */ 42 | gl_FragColor = vec4(0.4, 0.4, 0.4, 1.0); 43 | } else { 44 | /* color it according to the data */ 45 | gl_FragColor = vec4(0.0, c, c, 1.0); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /shader_06.2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SHADER SHADER FRIDAY 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /shader_06.2/vert.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | precision mediump float; 3 | #endif 4 | 5 | attribute vec4 a_position; 6 | 7 | // New: the image coordinates 8 | // the attribute gets it from the js program 9 | attribute vec2 a_imagePosition; 10 | // and stashes it in the varying version, which allows 11 | // it to pass to the fragment shader 12 | varying vec2 v_imagePosition; 13 | 14 | uniform mat4 u_model; 15 | uniform mat4 u_projection; 16 | 17 | 18 | void main() { 19 | gl_Position = u_projection * u_model * a_position; 20 | v_imagePosition = a_imagePosition; 21 | } --------------------------------------------------------------------------------