Navan Chauhan
20 minute readCreated on August 1, 2020

Introduction to AR.js and Natural Feature Tracking

AR.js

AR.js is a lightweight library for Augmented Reality on the Web, coming with features like Image Tracking, Location based AR and Marker tracking. It is the easiest option for cross-browser augmented reality.

The same code works for iOS, Android, Desktops and even VR Browsers!

It weas initially created by Jerome Etienne and is now maintained by Nicolo Carpignoli and the AR-js Organisation

NFT

Usually for augmented reality you need specialised markers, like this Hiro marker (notice the thick non-aesthetic borders 🤢)

This is called marker based tracking where the code knows what to look for. NFT or Natural Feature Tracing converts normal images into markers by extracting 'features' from it, this way you can use any image of your liking!

I'll be using my GitHub profile picture

Creating the Marker!

First we need to create the marker files required by AR.js for NFT. For this we use Carnaux's repository 'NFT-Marker-Creator'.

$ git clone https://github.com/Carnaux/NFT-Marker-Creator Cloning into 'NFT-Marker-Creator'... remote: Enumerating objects: 79, done. remote: Counting objects: 100% (79/79), done. remote: Compressing objects: 100% (72/72), done. remote: Total 580 (delta 10), reused 59 (delta 7), pack-reused 501 Receiving objects: 100% (580/580), 9.88 MiB | 282.00 KiB/s, done. Resolving deltas: 100% (262/262), done. $ cd NFT-Makrer-Creator

Install the dependencies

$ npm install npm WARN nodegenerator@1.0.0 No repository field. added 67 packages from 56 contributors and audited 67 packages in 2.96s 1 package is looking for funding run `npm fund` for details found 0 vulnerabilities ╭────────────────────────────────────────────────────────────────╮ │ │ │ New patch version of npm available! 6.14.5 → 6.14.7 │ │ Changelog: https://github.com/npm/cli/releases/tag/v6.14.7 │ │ Run npm install -g npm to update! │ │ │ ╰────────────────────────────────────────────────────────────────╯

Copy the target marker to the folder

$ cp ~/CodingAndStuff/ARjs/me.png .

Generate Marker

$ node app.js -i me.png Confidence level: [ * * * * * ] 5/5 || Entropy: 5.24 || Current max: 5.17 min: 4.6 Do you want to continue? (Y/N) y writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead! [info] Commands: [info] -- Generator started at 2020-08-01 16:01:41 +0580 [info] Tracking Extraction Level = 2 [info] MAX_THRESH = 0.900000 [info] MIN_THRESH = 0.550000 [info] SD_THRESH = 8.000000 [info] Initialization Extraction Level = 1 [info] SURF_FEATURE = 100 [info] min allow 3.699000. [info] Image DPI (1): 3.699000 [info] Image DPI (2): 4.660448 [info] Image DPI (3): 5.871797 [info] Image DPI (4): 7.398000 [info] Image DPI (5): 9.320896 [info] Image DPI (6): 11.743593 [info] Image DPI (7): 14.796000 [info] Image DPI (8): 18.641792 [info] Image DPI (9): 23.487186 [info] Image DPI (10): 29.592001 [info] Image DPI (11): 37.283585 [info] Image DPI (12): 46.974373 [info] Image DPI (13): 59.184002 [info] Image DPI (14): 72.000000 [info] Generating ImageSet... [info] (Source image xsize=568, ysize=545, channels=3, dpi=72.0). [info] Done. [info] Saving to asa.iset... [info] Done. [info] Generating FeatureList... [info] Start for 72.000000 dpi image. [info] ImageSize = 309560[pixel] [info] Extracted features = 24930[pixel] [info] Filtered features = 6192[pixel] 544/ 545.[info] [info] Done. [info] Max feature = 305 [info] 1: ( 22,474) : 0.211834 min=0.212201 max=0.583779, sd=36.253441 [info] 2: (259,449) : 0.365469 min=0.373732 max=0.667143, sd=64.356659 [info] 3: (244,492) : 0.368801 min=0.373514 max=0.644463, sd=52.414131 [info] 4: (542,503) : 0.388110 min=0.393117 max=0.659145, sd=21.867199 [info] 5: (544,451) : 0.426580 min=0.431487 max=0.697276, sd=24.540915 [info] 6: (486,334) : 0.593511 min=0.565134 max=0.800069, sd=31.706526 [info] 7: (217,283) : 0.602713 min=0.553285 max=0.815628, sd=11.092167 [info] 8: ( 44,420) : 0.612274 min=0.550906 max=0.832009, sd=29.664345 [info] 9: (522,343) : 0.615029 min=0.569004 max=0.796405, sd=34.439430 [info] 10: ( 57,476) : 0.621610 min=0.568849 max=0.816438, sd=41.452328 [info] 11: (407,335) : 0.626746 min=0.601339 max=0.802741, sd=22.136026 [info] 12: (483,375) : 0.636573 min=0.552658 max=0.851101, sd=53.539089 [info] 13: ( 54,509) : 0.637408 min=0.563383 max=0.804955, sd=34.774330 [info] 14: ( 22,386) : 0.642944 min=0.630736 max=0.852005, sd=29.959364 [info] 15: (459,434) : 0.649170 min=0.567012 max=0.817146, sd=44.087994 [info] 16: (510,409) : 0.667462 min=0.572251 max=0.808130, sd=49.187576 [info] 17: (330,270) : 0.690323 min=0.625252 max=0.836476, sd=24.105335 [info] 18: (544,270) : 0.695668 min=0.550262 max=0.841321, sd=53.076946 [info] 19: (443,489) : 0.696738 min=0.557579 max=0.868091, sd=27.418671 [info] 20: (439,373) : 0.706379 min=0.658029 max=0.856492, sd=52.750744 [info] 21: (381,264) : 0.712895 min=0.567250 max=0.829908, sd=21.462694 [info] 22: (114,344) : 0.726579 min=0.574026 max=0.873275, sd=19.631178 [info] 23: (450,339) : 0.730613 min=0.622663 max=0.840786, sd=36.808407 [info] 24: (187,316) : 0.737529 min=0.568579 max=0.856549, sd=35.841721 [info] 25: (155,451) : 0.741329 min=0.617655 max=0.848432, sd=50.381092 [info] 26: (425,406) : 0.770987 min=0.674625 max=0.908930, sd=39.619099 [info] 27: (520,308) : 0.773589 min=0.646116 max=0.856012, sd=31.303595 [info] 28: (239,244) : 0.784615 min=0.655032 max=0.943640, sd=25.512465 [info] 29: (415,277) : 0.784977 min=0.745286 max=0.898037, sd=24.985357 [info] 30: (278,244) : 0.796536 min=0.713171 max=0.940000, sd=36.488716 [info] 31: (536,235) : 0.825348 min=0.654568 max=0.901623, sd=54.036903 [info] 32: (341,310) : 0.828034 min=0.796073 max=0.928327, sd=57.174885 [info] 33: (355,438) : 0.833364 min=0.616488 max=0.944241, sd=57.199963 [info] 34: (330,215) : 0.852530 min=0.778738 max=0.960263, sd=31.844889 [info] 35: (307,163) : 0.859535 min=0.750590 max=0.963522, sd=41.524643 [info] 36: ( 43,246) : 0.865821 min=0.715005 max=0.967188, sd=17.746605 [info] 37: (207,171) : 0.873648 min=0.753025 max=0.956383, sd=22.992336 [info] 38: ( 75,383) : 0.877258 min=0.809668 max=0.943998, sd=24.749569 [info] 39: ( 77,438) : 0.893997 min=0.853110 max=0.953184, sd=37.195824 [info] 40: (186,231) : 0.897896 min=0.893945 max=0.959936, sd=53.592140 [info] --------------------------------------------------------------- [info] Start for 59.184002 dpi image. [info] ImageSize = 209216[pixel] [info] Extracted features = 16664[pixel] [info] Filtered features = 4219[pixel] 447/ 448.[info] [info] Done. [info] Max feature = 205 [info] 1: ( 24,404) : 0.263453 min=0.272001 max=0.579902, sd=30.270309 [info] 2: (181,415) : 0.286756 min=0.296179 max=0.570393, sd=51.832920 [info] 3: (229,375) : 0.299946 min=0.301300 max=0.620830, sd=63.595726 [info] 4: (443,403) : 0.395126 min=0.407708 max=0.635656, sd=21.330490 [info] 5: (224,412) : 0.444073 min=0.451129 max=0.679228, sd=50.032726 [info] 6: (402,276) : 0.562894 min=0.550990 max=0.783724, sd=31.768101 [info] 7: ( 22,324) : 0.597796 min=0.553165 max=0.803201, sd=25.844311 [info] 8: (408,318) : 0.606647 min=0.558857 max=0.803414, sd=50.661160 [info] 9: (378,394) : 0.616479 min=0.558946 max=0.824612, sd=26.079950 [info] 10: (384,361) : 0.668396 min=0.603888 max=0.820440, sd=36.232616 [info] 11: (337,278) : 0.671341 min=0.586483 max=0.837408, sd=23.079739 [info] 12: ( 52,371) : 0.679165 min=0.648876 max=0.842554, sd=35.683979 [info] 13: (440,260) : 0.683035 min=0.577838 max=0.836932, sd=36.886761 [info] 14: (444,227) : 0.687587 min=0.567562 max=0.837861, sd=49.854889 [info] 15: (149,266) : 0.688923 min=0.572425 max=0.832697, sd=31.967720 [info] 16: (290,212) : 0.714381 min=0.573321 max=0.825159, sd=25.429075 [info] 17: (374,309) : 0.720491 min=0.711943 max=0.874688, sd=58.918808 [info] 18: (103,283) : 0.723728 min=0.559241 max=0.835176, sd=17.688787 [info] 19: (235,200) : 0.742138 min=0.745569 max=0.912951, sd=36.019238 [info] 20: (128,360) : 0.770635 min=0.551060 max=0.871743, sd=51.743370 [info] 21: (297,368) : 0.794845 min=0.553557 max=0.908358, sd=48.856777 [info] 22: (348,343) : 0.798785 min=0.662930 max=0.928792, sd=40.917496 [info] 23: (195,204) : 0.801663 min=0.621057 max=0.936245, sd=25.684557 [info] 24: (325,221) : 0.810848 min=0.756911 max=0.898076, sd=30.086334 [info] 25: (276,253) : 0.825425 min=0.812713 max=0.926472, sd=58.497112 [info] 26: ( 57,409) : 0.838737 min=0.829799 max=0.922687, sd=45.331120 [info] 27: (174,164) : 0.846327 min=0.738286 max=0.963738, sd=31.914589 [info] 28: (440,191) : 0.859450 min=0.752551 max=0.938949, sd=62.600094 [info] 29: (271,176) : 0.865594 min=0.832825 max=0.961079, sd=36.463100 [info] 30: (247,141) : 0.869905 min=0.719910 max=0.944092, sd=39.328327 [info] 31: ( 62,315) : 0.889240 min=0.820342 max=0.949085, sd=28.934418 [info] 32: ( 55,200) : 0.896143 min=0.724967 max=0.973851, sd=18.574352 [info] --------------------------------------------------------------- [info] Start for 46.974373 dpi image. [info] ImageSize = 132076[pixel] [info] Extracted features = 10582[pixel] [info] Filtered features = 2654[pixel] 355/ 356.[info] [info] Done. [info] Max feature = 125 [info] 1: (147,328) : 0.253711 min=0.261744 max=0.546386, sd=49.037407 [info] 2: ( 23,318) : 0.326023 min=0.332772 max=0.553814, sd=29.970749 [info] 3: (180,307) : 0.332172 min=0.353050 max=0.582633, sd=55.894489 [info] 4: (339,229) : 0.568601 min=0.561106 max=0.788570, sd=35.519234 [info] 5: ( 34,277) : 0.618809 min=0.583962 max=0.811560, sd=31.459497 [info] 6: (120,210) : 0.655516 min=0.553481 max=0.808650, sd=30.417620 [info] 7: (299,226) : 0.660352 min=0.551423 max=0.810235, sd=40.050533 [info] 8: (289,291) : 0.672981 min=0.584721 max=0.865715, sd=34.681435 [info] 9: ( 85,221) : 0.735781 min=0.557358 max=0.837869, sd=15.401685 [info] 10: (192,150) : 0.748029 min=0.762064 max=0.911963, sd=36.248280 [info] 11: (348,194) : 0.750950 min=0.647856 max=0.880163, sd=44.824394 [info] 12: ( 27,244) : 0.779110 min=0.741316 max=0.889470, sd=27.621294 [info] 13: (192,110) : 0.801694 min=0.737249 max=0.930409, sd=40.227238 [info] 14: (142,131) : 0.807086 min=0.639763 max=0.952103, sd=32.719967 [info] 15: (218,190) : 0.819924 min=0.789691 max=0.922567, sd=52.960388 [info] 16: (265,213) : 0.829599 min=0.755986 max=0.906421, sd=30.495857 [info] 17: (348,159) : 0.833503 min=0.770736 max=0.922161, sd=62.732380 [info] 18: (241,296) : 0.846388 min=0.551359 max=0.934936, sd=41.934254 [info] 19: (263,178) : 0.888409 min=0.791312 max=0.931626, sd=35.446648 [info] --------------------------------------------------------------- [info] Start for 37.283585 dpi image. [info] ImageSize = 82908[pixel] [info] Extracted features = 6477[pixel] [info] Filtered features = 1665[pixel] 281/ 282.[info] [info] Done. [info] Max feature = 76 [info] 1: (126,255) : 0.291458 min=0.293245 max=0.532445, sd=44.819416 [info] 2: (259,179) : 0.544833 min=0.552487 max=0.779788, sd=34.632847 [info] 3: ( 22,217) : 0.577221 min=0.572050 max=0.765973, sd=29.686686 [info] 4: (101,164) : 0.634161 min=0.551986 max=0.799318, sd=26.766178 [info] 5: (263,212) : 0.644384 min=0.564216 max=0.795845, sd=42.637730 [info] 6: ( 22,258) : 0.680414 min=0.692315 max=0.791998, sd=35.050774 [info] 7: (220,182) : 0.698840 min=0.592309 max=0.862061, sd=37.508007 [info] 8: (229,257) : 0.703305 min=0.553369 max=0.864329, sd=24.709126 [info] 9: (151,118) : 0.726578 min=0.738549 max=0.906151, sd=38.828815 [info] 10: (177,214) : 0.781371 min=0.563572 max=0.832300, sd=54.721115 [info] 11: (225,215) : 0.788058 min=0.755838 max=0.899616, sd=50.707241 [info] 12: (158,155) : 0.794013 min=0.781587 max=0.916502, sd=48.264225 [info] 13: ( 63,176) : 0.841771 min=0.763143 max=0.907695, sd=19.686169 [info] 14: (206,145) : 0.844404 min=0.752984 max=0.916683, sd=35.973286 [info] 15: (270,142) : 0.845205 min=0.795885 max=0.935199, sd=59.147652 [info] 16: (149, 75) : 0.874711 min=0.796581 max=0.958077, sd=47.111187 [info] 17: (113,104) : 0.877415 min=0.769141 max=0.966519, sd=51.069527 [info] --------------------------------------------------------------- [info] Start for 29.592001 dpi image. [info] ImageSize = 52192[pixel] [info] Extracted features = 4027[pixel] [info] Filtered features = 1050[pixel] 223/ 224.[info] [info] Done. [info] Max feature = 50 [info] 1: (102,201) : 0.289298 min=0.304870 max=0.535742, sd=46.188416 [info] 2: (210,148) : 0.562558 min=0.576227 max=0.774472, sd=41.276623 [info] 3: ( 78,129) : 0.612243 min=0.551623 max=0.784806, sd=23.271040 [info] 4: (177,133) : 0.688757 min=0.576350 max=0.879510, sd=33.073624 [info] 5: (201,187) : 0.689806 min=0.643513 max=0.833690, sd=35.062008 [info] 6: (114, 82) : 0.729714 min=0.720887 max=0.903299, sd=42.064465 [info] 7: (124,118) : 0.735968 min=0.746138 max=0.899143, sd=45.898678 [info] 8: ( 23,164) : 0.779643 min=0.747459 max=0.878366, sd=34.013752 [info] 9: (140,163) : 0.809162 min=0.637383 max=0.881929, sd=50.335152 [info] 10: ( 23,198) : 0.819792 min=0.807587 max=0.883169, sd=39.944038 [info] 11: (210,113) : 0.867805 min=0.835419 max=0.952952, sd=62.521526 [info] --------------------------------------------------------------- [info] Start for 23.487186 dpi image. [info] ImageSize = 32930[pixel] [info] Extracted features = 2542[pixel] [info] Filtered features = 663[pixel] 177/ 178.[info] [info] Done. [info] Max feature = 26 [info] 1: ( 90,150) : 0.521553 min=0.522064 max=0.695849, sd=47.276417 [info] 2: (150,127) : 0.588753 min=0.553176 max=0.839270, sd=40.334232 [info] 3: ( 63,104) : 0.657959 min=0.625311 max=0.845079, sd=26.239153 [info] 4: ( 86, 71) : 0.716036 min=0.701616 max=0.897777, sd=40.668495 [info] 5: (124, 92) : 0.795828 min=0.799467 max=0.919533, sd=46.250336 [info] 6: ( 22,140) : 0.823488 min=0.788265 max=0.904299, sd=37.023449 [info] 7: (158, 94) : 0.846220 min=0.807598 max=0.945632, sd=57.189617 [info] --------------------------------------------------------------- [info] Start for 18.641792 dpi image. [info] ImageSize = 20727[pixel] [info] Extracted features = 1597[pixel] [info] Filtered features = 415[pixel] 140/ 141.[info] [info] Done. [info] Max feature = 17 [info] 1: ( 66,105) : 0.595532 min=0.553885 max=0.773757, sd=42.355804 [info] 2: (114, 96) : 0.636754 min=0.558845 max=0.877043, sd=41.727524 [info] 3: ( 68, 63) : 0.740243 min=0.674251 max=0.907678, sd=48.359558 [info] 4: ( 25, 97) : 0.770776 min=0.551998 max=0.915293, sd=33.076458 [info] 5: (102, 62) : 0.878442 min=0.879749 max=0.958104, sd=59.505066 [info] --------------------------------------------------------------- [info] Start for 14.796000 dpi image. [info] ImageSize = 13104[pixel] [info] Extracted features = 1028[pixel] [info] Filtered features = 266[pixel] 111/ 112.[info] [info] Done. [info] Max feature = 9 [info] 1: ( 48, 83) : 0.625048 min=0.567549 max=0.834230, sd=42.692223 [info] 2: ( 89, 73) : 0.670262 min=0.553308 max=0.882925, sd=45.027554 [info] 3: ( 52, 50) : 0.786427 min=0.743476 max=0.927114, sd=55.718193 [info] --------------------------------------------------------------- [info] Start for 11.743593 dpi image. [info] ImageSize = 8277[pixel] [info] Extracted features = 679[pixel] [info] Filtered features = 166[pixel] 88/ 89.[info] [info] Done. [info] Max feature = 4 [info] 1: ( 60, 64) : 0.633060 min=0.550807 max=0.857935, sd=42.695072 [info] 2: ( 26, 63) : 0.702131 min=0.685312 max=0.867015, sd=38.862392 [info] 3: ( 40, 30) : 0.833010 min=0.834262 max=0.945118, sd=62.075710 [info] --------------------------------------------------------------- [info] Start for 9.320896 dpi image. [info] ImageSize = 5254[pixel] [info] Extracted features = 398[pixel] [info] Filtered features = 106[pixel] 70/ 71.[info] [info] Done. [info] Max feature = 4 [info] 1: ( 47, 48) : 0.706897 min=0.668202 max=0.875970, sd=47.628330 [info] --------------------------------------------------------------- [info] Start for 7.398000 dpi image. [info] ImageSize = 3248[pixel] [info] Extracted features = 248[pixel] [info] Filtered features = 65[pixel] 55/ 56.[info] [info] Done. [info] Max feature = 1 [info] 1: ( 34, 33) : 0.794624 min=0.780241 max=0.925466, sd=59.612782 [info] --------------------------------------------------------------- [info] Start for 5.871797 dpi image. [info] ImageSize = 2024[pixel] [info] Extracted features = 161[pixel] [info] Filtered features = 41[pixel] 43/ 44.[info] [info] Done. [info] Max feature = 1 [info] --------------------------------------------------------------- [info] Start for 4.660448 dpi image. [info] ImageSize = 1295[pixel] [info] Extracted features = 108[pixel] [info] Filtered features = 26[pixel] 34/ 35.[info] [info] Done. [info] Max feature = 1 [info] --------------------------------------------------------------- [info] Start for 3.699000 dpi image. [info] ImageSize = 812[pixel] [info] Extracted features = 65[pixel] [info] Filtered features = 17[pixel] 27/ 28.[info] [info] Done. [info] Max feature = 0 [info] --------------------------------------------------------------- [info] Done. [info] Saving FeatureSet... [info] Done. [info] Generating FeatureSet3... [info] (568, 545) 72.000000[dpi] [info] Freak features - 405[info] ========= 405 =========== [info] (467, 448) 59.184002[dpi] [info] Freak features - 401[info] ========= 401 =========== [info] (371, 356) 46.974373[dpi] [info] Freak features - 385[info] ========= 385 =========== [info] (294, 282) 37.283585[dpi] [info] Freak features - 486[info] ========= 486 =========== [info] (233, 224) 29.592001[dpi] [info] Freak features - 362[info] ========= 362 =========== [info] (185, 178) 23.487186[dpi] [info] Freak features - 232[info] ========= 232 =========== [info] (147, 141) 18.641792[dpi] [info] Freak features - 148[info] ========= 148 =========== [info] (117, 112) 14.796000[dpi] [info] Freak features - 113[info] ========= 113 =========== [info] (93, 89) 11.743593[dpi] [info] Freak features - 81[info] ========= 81 =========== [info] (74, 71) 9.320896[dpi] [info] Freak features - 51[info] ========= 51 =========== [info] (58, 56) 7.398000[dpi] [info] Freak features - 36[info] ========= 36 =========== [info] (46, 44) 5.871797[dpi] [info] Freak features - 23[info] ========= 23 =========== [info] (37, 35) 4.660448[dpi] [info] Freak features - 19[info] ========= 19 =========== [info] (29, 28) 3.699000[dpi] [info] Freak features - 9[info] ========= 9 =========== [info] Done. [info] Saving FeatureSet3... [info] Done. [info] Generator finished at 2020-08-01 16:02:02 +0580 -- Finished marker creation! Now configuring demo! Finished! To run demo use: 'npm run demo'

Now we have the required files in the output folder

$ ls output me.fset me.fset3 me.iset

Creating the HTML Page

Create a new file called index.html in your project folder. This is the basic template we are going to use. Replace me with the root filename of your image, for example NeverGonnaGiveYouUp.png will become NeverGonnaGiveYouUp. Make sure you have copied all three files from the output folder in the previous step to the root of your project folder.

<script src="https://cdn.jsdelivr.net/gh/aframevr/aframe@1c2407b26c61958baa93967b5412487cd94b290b/dist/aframe-master.min.js"></script> <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script> <style> .arjs-loader { height: 100%; width: 100%; position: absolute; top: 0; left: 0; background-color: rgba(0, 0, 0, 0.8); z-index: 9999; display: flex; justify-content: center; align-items: center; } .arjs-loader div { text-align: center; font-size: 1.25em; color: white; } </style> <body style="margin : 0px; overflow: hidden;"> <div class="arjs-loader"> <div>Calculating Image Descriptors....</div> </div> <a-scene vr-mode-ui="enabled: false;" renderer="logarithmicDepthBuffer: true;" embedded arjs="trackingMethod: best; sourceType: webcam;debugUIEnabled: false;" > <a-nft type="nft" url="./me" smooth="true" smoothCount="10" smoothTolerance=".01" smoothThreshold="5" > </a-nft> <a-entity camera></a-entity> </a-scene> </body>

In this we are creating a AFrame scene and we are telling it that we want to use NFT Tracking. The amazing part about using AFrame is that we are able to use all AFrame objects!

Adding a simple box

Let us add a simple box!

<a-nft .....> <a-box position='100 0.5 -180' material='opacity: 0.5; side: double' scale="100 100 100"></a-box> </a-nft>

Now to test it out we will need to create a simple server, I use Python's inbuilt SimpleHTTPServer alongside ngrok

In one terminal window, cd to the project directory. Currently your project folder should have 4 files, index.html, me.fset3, me.fset and me.iset

Open up two terminal windows and cd into your project folder then run the following commands to start up your server.

In the first terminal window start the Python Server

$ cd ~/CodingAndStuff/ARjs $ python2 -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ...

In the other window run ngrok ( Make sure you have installed it prior to running this step )

$ ngrok http 8000

Now copy the url to your phone and try running the example

👏 Congratulations! You just built an Augmented Reality experience using AR.js and AFrame

Adding a Torus-Knot in the box

Edit your index.html

<a-nft ..> <a-box ..> <a-torus-knot radius='0.26' radius-tubular='0.05' ></a-torus-knot> </ a-box> </ a-nft>

Where are the GIFs?

Now that we know how to place a box in the scene and add a torus knot in it, what do we do next? We bring the classic internet back!

AFrame GIF Shader is a gif shader for A-Frame created by mayognaise.

First things first

Add <script src="https://rawgit.com/mayognaise/aframe-gif-shader/master/dist/aframe-gif-shader.min.js"></script> to <head>

Change the box's material to add the GIF shader

... <a-box position='100 0.5 -180' material="shader:gif;src:url(https://media.tenor.com/images/412b1aa9149d98d561df62db221e0789/tenor.gif);opacity:.5" .....>

Bonus Idea: Integrate it with GitHub's new profile Readme Feature!

1) Host the code using GitHub Pages

2) Create a new repository ( the name should be your GitHub username )

3) Add QR Code to the page and tell the users to scan your profile picture

??) Profit 💸

Here is a screenshot of me scanning a rounded version of my profile picture ( It still works! Even though the image is cropped and I haven't changed any line of code )

Tagged with: