├── .gitignore
├── Selective Color
├── .DS_Store
├── Selective Color - Red & Blue.arp
├── Selective Color - other colors.arp
└── README.md
├── SimplePickerUI
├── picker.arprojpkg
├── picker.js
└── README.md
├── delay-a-texture
├── [UNGROUP_ME].arp
├── Screen Shot 2020-07-14 at 00.08.59.png
└── README.md
├── fire-shader
├── Fire Shader - Learning.zip
└── README.md
├── raymarching-v1.0.102-g
├── raymarching-v1.0.102-g.arproj
├── README.md
├── objects
│ └── Cube
│ │ └── Cube.gltf
└── shaders
│ └── Raymarching 1.0.102.sca
├── Native UI Multiple Sliders
├── multipleSliders
│ ├── textures
│ │ ├── icon0.jpg
│ │ ├── icon1.jpg
│ │ ├── icon2.jpg
│ │ ├── icon3.jpg
│ │ ├── icon4.jpg
│ │ ├── icon5.jpg
│ │ ├── icon6.jpg
│ │ ├── icon7.jpg
│ │ ├── icon8.jpg
│ │ └── icon9.jpg
│ ├── multipleSliders.arproj
│ └── scripts
│ │ ├── tsconfig.json
│ │ └── script.js
├── README.md
└── script.js
├── num2txt.js
├── Native UI Slider
├── Simple Slider - Material.js
├── Slider never-reset-value.js
├── Slider wPersistence.js
└── README.md
├── README.md
├── LICENSE
└── Native UI Picker
├── README.md
├── Picker random-start.js
├── Picker.js
└── Picker with comments.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.arprojbk
3 |
--------------------------------------------------------------------------------
/Selective Color/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Selective Color/.DS_Store
--------------------------------------------------------------------------------
/SimplePickerUI/picker.arprojpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/SimplePickerUI/picker.arprojpkg
--------------------------------------------------------------------------------
/delay-a-texture/[UNGROUP_ME].arp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/delay-a-texture/[UNGROUP_ME].arp
--------------------------------------------------------------------------------
/fire-shader/Fire Shader - Learning.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/fire-shader/Fire Shader - Learning.zip
--------------------------------------------------------------------------------
/Selective Color/Selective Color - Red & Blue.arp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Selective Color/Selective Color - Red & Blue.arp
--------------------------------------------------------------------------------
/Selective Color/Selective Color - other colors.arp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Selective Color/Selective Color - other colors.arp
--------------------------------------------------------------------------------
/raymarching-v1.0.102-g/raymarching-v1.0.102-g.arproj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/raymarching-v1.0.102-g/raymarching-v1.0.102-g.arproj
--------------------------------------------------------------------------------
/delay-a-texture/Screen Shot 2020-07-14 at 00.08.59.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/delay-a-texture/Screen Shot 2020-07-14 at 00.08.59.png
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon0.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon1.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon2.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon3.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon4.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon5.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon6.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon7.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon8.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/textures/icon9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/textures/icon9.jpg
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/multipleSliders.arproj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tomaspietravallo/Spark-AR/HEAD/Native UI Multiple Sliders/multipleSliders/multipleSliders.arproj
--------------------------------------------------------------------------------
/num2txt.js:
--------------------------------------------------------------------------------
1 | const Patches = require('Patches');
2 |
3 | (async function () {
4 | // Gets a scalar variable called 'num'
5 | const p = await Patches.outputs.getScalar('num');
6 | // Output a string to a variable called 'txt'
7 | Patches.inputs.setString('txt', p.toString());
8 | })();
9 |
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/scripts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {"compilerOptions":{"allowJs":true,"baseUrl":"/var/folders/gl/tyj643vj7_l3pwcztxm681ch0000gn/T/65445eb963acb99e4c7cb85eb8228f00d59a/skylight-typedefs","checkJs":true,"lib":["ES2015"],"outDir":"/var/folders/gl/tyj643vj7_l3pwcztxm681ch0000gn/T/65445eb963acb99e4c7cb85eb8228f00d59a/skylight-typedefs/out-dir"},"include":["*.js"]}
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/README.md:
--------------------------------------------------------------------------------
1 | # Native UI Multiple Sliders
2 |
3 | [Picker textures](https://github.com/positlabs/spark-picker-number-icons) by @positlabs
4 |
5 | The code will use any texture that has a name that starts with `icon`. And will create a patch from script variable called `setting[1-9]` (There's no limit to a picker's length in theory).
6 |
7 | This code will be updated in the near future to add some more features.
8 |
9 | The lines to change the default `slider.value` and start picker `selectedIndex` can be found at the top.
--------------------------------------------------------------------------------
/Native UI Slider/Simple Slider - Material.js:
--------------------------------------------------------------------------------
1 | const Materials = require("Materials");
2 | const NativeUI = require("NativeUI");
3 | const slider = NativeUI.slider;
4 |
5 | let material = Materials.findFirst("yourMaterial"); // change yourMaterial for your material's name | put it between quotes ""
6 | slider.value = 1; // this is the default slider value
7 | slider.visible = true;
8 |
9 | slider.value.monitor({fireOnInitialValue: true}).subscribe((val)=>{
10 | material.then((result)=>{
11 | result.opacity = val.newValue // changes the selected material's opacity based on the slider value
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/Native UI Slider/Slider never-reset-value.js:
--------------------------------------------------------------------------------
1 | const NativeUI = require('NativeUI')
2 | const Persistence = require('Persistence')
3 | const Patches = require('Patches')
4 |
5 | const slider = NativeUI.slider
6 | const userScope = Persistence.userScope
7 |
8 | userScope.get('slider').then((val)=>{
9 | slider.value = val.value
10 | slider.visible = true
11 | }).catch(()=>{
12 | slider.value = 1
13 | slider.visible = true
14 | })
15 |
16 | slider.value.monitor({fireOnInitialValue: true}).subscribe((val)=>{
17 | userScope.set('slider', {value: val.newValue})
18 | Patches.inputs.setScalar('slider', val.newValue)
19 | })
20 |
21 |
--------------------------------------------------------------------------------
/raymarching-v1.0.102-g/README.md:
--------------------------------------------------------------------------------
1 | # Raymarching 1.0.102
2 |
3 | This project contains the code to Raymarch a scene in Spark SL. It contains:
4 | - Normals
5 | - Basic SDF Shapes and functions
6 | - Soft shadows
7 | - 2 point lights
8 | - Example scene
9 | - And more
10 |
11 | The scene to be rendered is under `SDF::scene()`. Lights are in the `render()` function, this may be changed to work with the standard Spark AR Studio lights in the future.
12 |
13 | The amount of rays can be changed but remember quality and performance are a tradeoff.
14 |
15 | Feel free to add your own functions or SDF primitives.
16 |
17 | > Part of the code were inspired by or taken from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
18 |
--------------------------------------------------------------------------------
/Native UI Slider/Slider wPersistence.js:
--------------------------------------------------------------------------------
1 | const NativeUI = require('NativeUI')
2 | const Persistence = require('Persistence')
3 | const Time = require("Time")
4 | const Patches = require('Patches')
5 |
6 | const slider = NativeUI.slider
7 | const userScope = Persistence.userScope
8 |
9 | let timer = Time.setTimeout(()=>{userScope.remove('slider')}, 12000);
10 |
11 | userScope.get('slider').then((val)=>{
12 | slider.value = val.value
13 | slider.visible = true
14 | }).catch(()=>{
15 | slider.value = 1
16 | slider.visible = true
17 | })
18 |
19 | slider.value.monitor({fireOnInitialValue: true}).subscribe((val)=>{
20 | userScope.set('slider', {value: val.newValue})
21 | Patches.inputs.setScalar('slider', val.newValue)
22 | timer.unsubscribe();
23 | timer = Time.setTimeout(()=>{userScope.remove('slider')}, 12000);
24 | })
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spark-AR
2 | Repository of useful code I've used on instagram filters, you can see the filters at my instagram [tomaspietravallo](www.instagram.com/tomaspietravallo). If you are curious about any of the features used on any of the filters, I'm more than happy to help / add part of the project here
3 |
4 | All of the files in the repository are subject to the licence, if whole projects or patch assets are uploaded there may be third party files like [Josh Beckwith's LUT Patch](https://github.com/positlabs/spark-lut-patch) which are subject to their own separate licences.
5 |
6 | I can't believe I have to say this but this repository is for learning, don't take whole projects and put them up for sale, it's only discouraging to me because I take the time to put things up together nicely for free, so the community can grow. Please use this as learning material and make your own project from that
7 |
8 | All of the code works with v85 (or the version of spark at the time of upload) & promises
9 |
10 | Feel free to contribute with your own code or to contact me for any reason (I'll probably answer faster through Instagram)
11 |
--------------------------------------------------------------------------------
/fire-shader/README.md:
--------------------------------------------------------------------------------
1 | # Fire Shader
2 |
3 | There's a more complete version with more advanced functions and an easy to integrate patch over [on gumroad](https://gum.co/kecLw)
4 |
5 |
Fire Shader - Learning by Tomas Pietravallo is licensed under CC BY-NC-SA 4.0
6 |
7 | 



8 |
--------------------------------------------------------------------------------
/Native UI Slider/README.md:
--------------------------------------------------------------------------------
1 | # Native UI Slider
2 | To use the files, create a script in Spark AR (Add Assets button) and copy paste the contents of the file you choose to it, or download the file and drag it into spark.
3 |
4 | ## Simple Sliders
5 | These are sliders that aren't integrated with the persistence capability, so the value isn't stored and used to set the slider the next time.
6 |
7 | ## Sliders with Persistence
8 | As the name says these sliders are integrated with the Persistence capability.
9 |
10 | ## Why the two groups?
11 | The sliders are divided in these two groups because sometimes as of 11/04/2020 - v85 - different things may collide in ways that when the slider uses Persistence, those things break in ways whose cause I haven't figured out. If adding a slider with persistence breaks something you can't figure out how to solve, consider using the alternative version.
12 |
13 | ## Common problems:
14 | * Remember to add the slider capability, to do this go to capabilites, add NativeUI then tick the "Slider" checkbox.
15 | * For sliders with Persistence, remember to whitelist the key, to do this go to capabilites, add Persistence and add the key in the box, do so without any quotes or similar, if you've already added a key, you just leave a space in-between.
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/Native UI Picker/README.md:
--------------------------------------------------------------------------------
1 | # Native UI Picker (with Persistence)
2 | To use the files, create a script in Spark AR (Add Assets button) and copy paste the contents of the file you choose to it, or download the file and drag it into spark.
3 |
4 | If you don't really understand javascript or code as a whole (like when I started) I'd recommend using the version with comments, it has `// little things like this (comments)` that don't change the result but will tell you what you can change, what the result of doing so will be, and what you shouldn't.
5 |
6 | If you know what you're doing feel free to use the version without comments (Picker.js) and change it as you wish.
7 |
8 | ## Common problems:
9 | * Remember to add picker in the project capabilities - Add the NativeUI capability, then tick the "Picker" checkbox.
10 | * Add the "index" key to whitelisted keys - Add the Persistence capability, then write "index" in the box (without quotes) then save changes, if you've already added a key, you just leave a space in-between.
11 | * Disable compression in your logos/button textures, try to make them tiny in photoshop to save size, I tend to use 150x150px, otherwise your project size skyrockets, you can also use services like [TinyPng](https://tinypng.com), I've had images that weigh *bytes* instead of megabytes that way.
12 |
--------------------------------------------------------------------------------
/Native UI Picker/Picker random-start.js:
--------------------------------------------------------------------------------
1 | const Scene = require('Scene');
2 | const Materials = require('Materials');
3 | const NativeUI = require('NativeUI');
4 | const Textures = require('Textures');
5 | const Time = require("Time");
6 | const Patches = require("Patches");
7 | const Persistence = require("Persistence");
8 |
9 | const picker = NativeUI.picker;
10 |
11 | function visible(){
12 | try {
13 | picker.visible = true;
14 | } catch (error) {
15 | Time.setTimeout(visible(), 100);
16 | }
17 | }
18 |
19 | Promise.all([
20 |
21 | Textures.findFirst('LOGO0'),
22 | Textures.findFirst('LOGO1'),
23 | Textures.findFirst('LOGO2'),
24 | Textures.findFirst('LOGO3'),
25 | Textures.findFirst('LOGO4'),
26 |
27 | ]).then((result)=>{
28 | picker.configure({
29 | selectedIndex: 0,
30 | items: [
31 | {image_texture: result[0]},
32 | {image_texture: result[1]},
33 | {image_texture: result[2]},
34 | {image_texture: result[3]},
35 | {image_texture: result[4]},
36 | ]
37 | });
38 | picker.selectedIndex = Math.round(Math.random()*4);
39 | })
40 |
41 | picker.selectedIndex.monitor({fireOnInitialValue: true}).subscribe((val)=>{
42 | Patches.inputs.setScalar("scriptToEditorVar", val.newValue);
43 | })
44 |
45 | visible();
46 |
--------------------------------------------------------------------------------
/SimplePickerUI/picker.js:
--------------------------------------------------------------------------------
1 | // const Diagnostics = require('Diagnostics');
2 | const NUI = require('NativeUI');
3 | const Patches = require('Patches');
4 | const Textures = require('Textures');
5 |
6 | const Picker = {
7 | init(assets = []) {
8 | Promise.all(assets).then((assets) => this.onLoad(assets));
9 | },
10 | onLoad(assets) {
11 | this.icons = assets[0];
12 | if (this.icons.length <= 0) {
13 | throw `\nNo icon with the name provided was found. Remember it's case SENSITIVE.\n\nEg:\nicon1, icon2, icon3 are OK.\nIcon1, iCon2, icOn3 are NOT ok`;
14 | }
15 | this.setUpPicker().then(() => {
16 | // Please make sure to define a FromScript patch with that name in the patch editor. Select the script > +From Script Variable (scalar) called "index" (case SENSITIVE)
17 | Patches.inputs.setScalar('index', NUI.picker.selectedIndex);
18 | });
19 | },
20 | setUpPicker() {
21 | return new Promise((resolve) => {
22 | this.icons.sort((a, b) => {
23 | return a.name.localeCompare(b.name);
24 | });
25 | let iconsArray = [];
26 | this.icons.forEach((element) => {
27 | iconsArray.push({ image_texture: element });
28 | });
29 | try {
30 | NUI.picker.configure({ selectedIndex: 0, items: iconsArray });
31 | NUI.picker.visible = true;
32 | resolve();
33 | } catch (error) {
34 | throw '\nAn error occured:\n\nGo to Project > Edit Properties... > Capabilities > + NativeUI > + Picker\n\nRemember to disable compression on the textures you choose as icons ;)';
35 | }
36 | });
37 | },
38 | };
39 |
40 | Picker.init([Textures.findUsingPattern('icon*')]);
41 |
--------------------------------------------------------------------------------
/Native UI Picker/Picker.js:
--------------------------------------------------------------------------------
1 | const Scene = require('Scene');
2 | const Materials = require('Materials');
3 | const NativeUI = require('NativeUI');
4 | const Textures = require('Textures');
5 | const Time = require("Time");
6 | const Patches = require("Patches");
7 | const Persistence = require("Persistence");
8 |
9 | const picker = NativeUI.picker;
10 | const userScope = Persistence.userScope;
11 | let timer = Time.setTimeout(()=>{userScope.remove("index")}, 12000);
12 |
13 | function visible(){
14 | try {
15 | picker.visible = true;
16 | } catch (error) {
17 | Time.setTimeout(visible(), 100);
18 | }
19 | }
20 |
21 | Promise.all([
22 |
23 | Textures.findFirst('LOGO0'),
24 | Textures.findFirst('LOGO1'),
25 | Textures.findFirst('LOGO2'),
26 | Textures.findFirst('LOGO3'),
27 | Textures.findFirst('LOGO4'),
28 | Textures.findFirst('LOGO5'),
29 | Textures.findFirst('LOGO6'),
30 | Textures.findFirst('LOGO7'),
31 | Textures.findFirst('LOGO8'),
32 | Textures.findFirst('LOGO9'),
33 | Textures.findFirst('LOGO10'),
34 |
35 | ]).then((result)=>{
36 | picker.configure({
37 | selectedIndex: 0,
38 | items: [
39 | {image_texture: result[0]},
40 | {image_texture: result[1]},
41 | {image_texture: result[2]},
42 | {image_texture: result[3]},
43 | {image_texture: result[4]},
44 | {image_texture: result[5]},
45 | {image_texture: result[6]},
46 | {image_texture: result[7]},
47 | {image_texture: result[8]},
48 | {image_texture: result[9]},
49 | {image_texture: result[10]},
50 | ]
51 | });
52 | userScope.get("index").then((val)=>{
53 | picker.selectedIndex = val.value;
54 | }).catch(()=>{
55 | picker.selectedIndex = 0;
56 | })
57 | })
58 |
59 | picker.selectedIndex.monitor({fireOnInitialValue: true}).subscribe((val)=>{
60 | Patches.inputs.setScalar("scriptToEditorVar", val.newValue);
61 | userScope.set("index", { value: (val.newValue) })
62 | timer.unsubscribe()
63 | timer = Time.setTimeout(()=>{userScope.remove("index")}, 12000);
64 | })
65 |
66 | visible();
67 |
--------------------------------------------------------------------------------
/Selective Color/README.md:
--------------------------------------------------------------------------------
1 | # Selective Color
2 | To use the files, just download them and drag them into Spark AR or use the 'Import from Computer' button
3 |
4 | The patch asset uses Josh Beckwith's \([@positlabs](https://github.com/positlabs)\) [incredible LUT patch](https://github.com/positlabs/spark-lut-patch), please go and check his work, he makes incredible stuff
5 |
6 | ## How it works
7 | ### Inputs:
8 | - 'PLUS RGBA': A modified LUT that modifies the saturation\* of a color positively, [e.g. with reds here](https://drive.google.com/drive/folders/1PtXGoqf4EKgfmRd6UnDEhmfiyMD6i-cJ?usp=sharing)
9 | - 'MINUS RGBA': A modified LUT that modifies the saturation\* of a color negatively, [e.g. with reds here](https://drive.google.com/drive/folders/1PtXGoqf4EKgfmRd6UnDEhmfiyMD6i-cJ?usp=sharing)
10 | - 'CAMERA TEXTURE': The camera texture RGBA or RGB (alpha is discarted so it doesn't matter)
11 | - 'Slider Value': This value should range from -1 to +1 (you can use a 'From range' to transform the slider value)
12 |
13 | \* I have only done this with saturation, but I assume lightness and hue should work, also, the luts are modifed to +70/65 and -100, because +100 can cause unwanted noise if you can see a sharp edge form in the LUT png.
14 |
15 | ### Outputs:
16 | - 'Result': A RGBA signal that should be assigned to a flat material (Blend Mode: alpha), and that material assigned to its own rectangle
17 |
18 | ## The idea behind it
19 | **I dont know anything about color theory or anything, I just thought way too much** With that said:
20 |
21 | The PLUS RGBA and MINUS RGBA are chosen depending on whether the value is greater or less than zero, after that the LUT is applied to the camera texture and IF the LUT causes a change in Hue, Saturation or Value (these are weighted)
22 | that point of the image is added to the Alpha channel, and the modified camera texture is sent to the RGB part of the signal. The Alpha is multiplied by the absolute value of 'Slider Value' so that a small change in 'Slider Value' results in only a small change being shown
23 |
24 | TL;DR: If the LUT (which should only modify one color) causes a change in x part of the image, that change will be shown in proportion to the 'Slider Value'
25 |
26 | #### Why are there two versions?
27 | Red & Blue have different effects compared to the other colors, the difference is only inside the LUT patch, the clamp values are changed slightly in a way that removes the effect. Why does that happen? I'm not sure, I have no idea to be honest, I'd guess there's some process or property of the LUT base .png, or the color space (no idea), that represents those colors differently
28 |
--------------------------------------------------------------------------------
/SimplePickerUI/README.md:
--------------------------------------------------------------------------------
1 | # Simple Picker UI
2 |
3 | This script is designed for people with little or no experience in programming who still want to use the NativeUI Picker.
4 |
5 | ## How to use:
6 |
7 | 1. To use it just download the script called [picker.js](https://github.com/tomaspietravallo/Spark-AR/blob/master/SimplePickerUI/picker.js) and import it to your project.
8 |
9 | 2. Rename the textures you want to use for your picker's icons with the following pattern: `icon[0-9]`
10 |
11 | 3. Add the Picker capability. Go to Project > Edit Properties... > Capabilities > + NativeUI > + Picker.
12 |
13 | 4. Create a From Script variable called `index` (case sensitive) of the type `scalar` / `number`, select the script you imported and on the right side add the variable. Then drag the script to the patch editor (otherwise you'll see an error saying it doesn't exist)
14 |
15 | 
16 |
17 | Example icon names: `icon0`, `icon1`, `icon2` ... `icon999`.
18 |
19 | There's no limit to how many icons you can have, just keep adding numbers to the name.
20 |
21 | ⚠️ Remember to disable compression on the textures just like with the regular Native UI Picker Patch ⚠️
22 |
23 | ## More than 10 icons:
24 |
25 | If you wish to have more than 10 icons - more than `icon9`.
26 |
27 | Use the pattern: `icon01`, `icon02`, `icon03`, ... `icon09`, `icon10`, `icon11` ...
28 |
29 | For numbers up to 999, use the pattern `icon001`, `icon002`, `icon003`, ... `icon099`, ... `icon999`.
30 |
31 | Always make sure the amount of digits on the name is the same, pad with `0`s at the front as necessary.
32 |
33 | ## Example Project:
34 | You can see an example project here: [picker.arprojpkg](https://github.com/tomaspietravallo/Spark-AR/blob/master/SimplePickerUI/picker.arprojpkg)
35 |
36 | ## Order of the icons:
37 |
38 | The icons will get ordered in ascending order.
39 |
40 | Eg: `icon0`, `icon1`, `icon2`, `icon3`, ... `icon99`
41 |
42 | ## Using other patterns instead of `icon[0-9]`
43 | If you want to change the pattern used to load the icons you will have to change line 48 of the [picker.js](https://github.com/tomaspietravallo/Spark-AR/blob/master/SimplePickerUI/picker.js) script.
44 |
45 | The patterns have to be in the format: `name*`, `*` means it will match any string that follows the name you choose.
46 |
47 | Patterns are case sensitive.
48 |
49 | Eg:
50 |
51 | `myIcon*`:
52 | - ✅ `myIcon0`, `myIcon1`, `myIcon2`, ... `myIcon999`
53 | - ❌ `MYICON0`, `mYIcon0`, `myicon0`, ...
54 |
55 | ## Credits:
56 | Picker icons by [Josh Beckwith](https://www.instagram.com/positlabs/)
57 |
58 | ## Donations ❤️:
59 | If you found this useful or used it on a client's project, please consider donating a small amount as that helps me out and allows me to keep making small scripts like this one. This would be a one time donation with no hidden charges nor recurrent charges.
60 |
61 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LEXFVQET96N2Y)
62 |
--------------------------------------------------------------------------------
/delay-a-texture/README.md:
--------------------------------------------------------------------------------
1 | # Delay-a-texture
2 | Languages / Idiomas
3 | - [English](#English)
4 | - [Spanish \/ Español](#Spanish--espa%C3%B1ol)
5 |
6 | ---
7 |
8 | ## English
9 |
10 | > Note: This is still more manual than I'd like it to be, it's not just changing one value. If a new update or scriting with render passes is released this will probably become obsolete. As of now this is sort of a tutorial.
11 |
12 | > IMPORTANT: **Keeping down the size, amount of channels and amount of Delay frames is a must**. Each Delay Frame consumes a lot of processing/memoory resources and **it will hamper performance if not kept under control**, even to the point of crashing Instagram.
13 |
14 | Everything is contained within a patch group (\[UNGROUP_ME\].arp) that you will have to ungroup. That's because Spark AR would complain whenever I tried adding render passes containerized in their own separate groups or importing multiple ones at once
15 |
16 | To delay a texture for an extended amount of time (more than 1 frame), you will have to chain multiple patches together as seen in the image below. You can `Ctrl+C` + `Ctrl+V` things.
17 |
18 | From what I've seen every loop through the 'Delay Frame' delays the texture for about 1 to 2 frames. So every 15-30 patches you connect you will delay the texture for a second
19 |
20 | 
21 |
22 | The 'input' & 'output' seen on the image is due to everything beeing contained inside a group. The delay frames themselves are not grouped separately, but rather all together inside a group. The input is an RGBA signal (most likely the camera's)
23 |
24 | ----
25 |
26 | ## Spanish / Español
27 |
28 | > Observación: Esto sigue siendo más manual de lo que me gustaria, no es simplemente cambiar un valor. Si se lanza una nueva actualización o pases de renderizado desde codigo esto probablemente se vuelva obsoleto. Por ahora esto es una especie de tutorial.
29 |
30 | > IMPORTANTE: **Mantener al minimo el tamaño (Size), cantidad de canales (Color channels) y cantidad de delay frames es importantisimo**. Cada Delay Frame consume muchos recursos del telefono y **va terminar afectando el rendimiento si no se controla**, incluso al punto de que se quede trabado Instagram.
31 |
32 | Todo esta dentro de un grupo de patches (\[UNGROUP_ME\].arp) que vas tener que desagrupar. Esto es porque Spark AR daba error cada vez que intentaba agregar pases de renderizado en sus grupos individuales o importar multiples pases de renderizado de una.
33 |
34 | Para atrasar una textura por un periodo prolongado (mas de 1 fotograma), es necesario encadenar multiples patches unos con otros como se puede ver en la imagen de abajo. Podes `Ctrl+C` + `Ctrl+V` los patches (copiar y pegar).
35 |
36 | 
37 |
38 | Por lo que he visto cada vez que se pasa por un 'Delay Frame' se atrasa la textura por 1 o 2 fotogramas. Por lo que cada 15-30 patches que conectes en cadena vas a atrasar la textura por un segundo
39 |
40 | El 'input' & 'output' que se ven en la imagen son porque todo esta dentro de un grupo. Los `delay frames` no estan agrupados de manera separada, sino que todos en el mismo grupo. El input (la entrada) es una señal RGBA (lo mas probable es que uses la de la camara)
41 |
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/multipleSliders/scripts/script.js:
--------------------------------------------------------------------------------
1 | const NUI = require('NativeUI');
2 | const Textures = require('Textures');
3 | const Patches = require('Patches');
4 | const Persistence = require('Persistence');
5 | const Diagnostics = require('Diagnostics');
6 |
7 | const Picker = {
8 | icons: null,
9 | sliderValue: 0.5,
10 | defaultSliderValue: 0.5,
11 | pickerIndex: 0,
12 | settings: {},
13 | persistenceKey: 'multipleSliders',
14 |
15 | init(assets = []) {
16 | Promise.all(assets).then((assets) => this.onLoad(assets));
17 | },
18 | onLoad(assets) {
19 | this.icons = assets[0];
20 | this.setUpPicker()
21 | .then(() => {
22 | return this.persistence();
23 | })
24 | .then(() => {
25 | return this.setUpSlider();
26 | })
27 | .then(() => {
28 | this.monitorIndex();
29 | });
30 | },
31 | setUpPicker() {
32 | return new Promise((resolve) => {
33 | this.icons.sort((a, b) => {
34 | return a.name.localeCompare(b.name);
35 | });
36 | let iconsArray = [];
37 | this.icons.forEach((element) => {
38 | iconsArray.push({ image_texture: element });
39 | });
40 | NUI.picker.configure({ selectedIndex: 0, items: iconsArray });
41 | NUI.picker.visible = true;
42 | resolve();
43 | });
44 | },
45 | setUpSlider() {
46 | return new Promise((resolve) => {
47 | if (this.settings[this.pickerIndex]) {
48 | NUI.slider.value = this.settings[this.pickerIndex];
49 | } else {
50 | NUI.slider.value = this.sliderValue;
51 | }
52 |
53 | NUI.slider.visible = true;
54 | NUI.slider.value
55 | .monitor({ fireOnInitialValue: false })
56 | .select('newValue')
57 | .subscribe((val) => {
58 | this.sliderValue = val;
59 | if (this.settings[this.pickerIndex]) {
60 | this.settings[this.pickerIndex] +=
61 | val - this.settings[this.pickerIndex];
62 | } else {
63 | this.settings[this.pickerIndex] = val;
64 | }
65 |
66 | this.pushToPatches();
67 | });
68 | resolve();
69 | });
70 | },
71 | monitorIndex() {
72 | NUI.picker.selectedIndex
73 | .monitor({ fireOnInitialValue: true })
74 | .select('newValue')
75 | .subscribe((index) => {
76 | if (this.settings.hasOwnProperty(index)) {
77 | NUI.slider.value = this.settings[index];
78 | } else {
79 | NUI.slider.value = this.defaultSliderValue;
80 | }
81 | this.pickerIndex = index;
82 | });
83 | },
84 | pushToPatches() {
85 | for (const key in this.settings) {
86 | Patches.inputs.setScalar(`setting${key}`, this.settings[key]);
87 | }
88 | try {
89 | Persistence.userScope.set(this.persistenceKey, { v: this.settings });
90 | } catch (error) {
91 | Diagnostics.log(
92 | `The key: "${this.persistenceKey}" is not whitelisted (case sensitive)`
93 | );
94 | }
95 | },
96 | persistence() {
97 | return new Promise((resolve) => {
98 | try {
99 | Persistence.userScope.get(this.persistenceKey).then((v) => {
100 | try {
101 | this.settings = v.v;
102 | Diagnostics.log(this.settings);
103 | } catch {
104 | Diagnostics.log('There were no settings saved');
105 | }
106 | this.pushToPatches();
107 | });
108 | } catch {
109 | Diagnostics.log(
110 | `The key: "${this.persistenceKey}" is not whitelisted (case sensitive)`
111 | );
112 | }
113 | resolve();
114 | });
115 | },
116 | };
117 | Picker.init([Textures.findUsingPattern('icon*')]);
118 |
--------------------------------------------------------------------------------
/Native UI Picker/Picker with comments.js:
--------------------------------------------------------------------------------
1 | const Scene = require('Scene');
2 | const Materials = require('Materials');
3 | const NativeUI = require('NativeUI');
4 | const Textures = require('Textures');
5 | const Time = require("Time");
6 | const Patches = require("Patches");
7 | const Persistence = require("Persistence");
8 |
9 | const picker = NativeUI.picker;
10 | const userScope = Persistence.userScope;
11 | let timer = Time.setTimeout(()=>{userScope.remove("index")}, 25000); // this is a default value for timer, it is not the time it takes for the memory value to be deleted see line 65 for that
12 |
13 | function visible(){ // This bit makes surre the picker is visible | Not sure what the chances of it not showing are but hey instagram wants error handling so...
14 | try {
15 | picker.visible = true;
16 | } catch (error) {
17 | Time.setTimeout(visible(), 100); // This is the "error handling" | I've checked (Diagnostics.log) this to make sure that under normal conditions this doesn't suddenly start a recursive loop
18 | }
19 | }
20 |
21 | Promise.all([
22 |
23 | // Finds textures (picker logos)
24 | Textures.findFirst('LOGO0'), // Change the names here for the ones of your logos/ button images as they appear in SparkAR. Add or remove as you need (always end the line with a comma) | Remember computers count from 0
25 | Textures.findFirst('LOGO1'), // This would be result[1] | Remember computers count from 0 so the line above is result[0]
26 | Textures.findFirst('LOGO2'), // This would be result[2]
27 | Textures.findFirst('LOGO3'), // This would be result[3]
28 | Textures.findFirst('LOGO4'), // etc
29 | Textures.findFirst('LOGO5'),
30 | Textures.findFirst('LOGO6'),
31 | Textures.findFirst('LOGO7'),
32 | Textures.findFirst('LOGO8'),
33 | Textures.findFirst('LOGO9'),
34 | Textures.findFirst('LOGO10'),
35 |
36 | ]).then((result)=>{ // Once it finds the textures it configures the picker
37 | picker.configure({
38 | selectedIndex: 0,
39 | items: [
40 | {image_texture: result[0]}, // These are the picker bottons. Add or remove as you need (always end the line with a comma) | Remember computers count from 0
41 | {image_texture: result[1]}, // result[1] is the texture you found above (line 25)
42 | {image_texture: result[2]}, // result[2] is the texture you found above (line 26)
43 | {image_texture: result[3]}, // you get the idea
44 | {image_texture: result[4]},
45 | {image_texture: result[5]},
46 | {image_texture: result[6]},
47 | {image_texture: result[7]},
48 | {image_texture: result[8]},
49 | {image_texture: result[9]},
50 | {image_texture: result[10]},
51 | ]
52 | });
53 | userScope.get("index").then((val)=>{ // "index" is the Persistence key, you add them in Capabilities -> +Persistence
54 | picker.selectedIndex = val.value;
55 | }).catch(()=>{
56 | picker.selectedIndex = 0; // this is the default value if none is found in memory
57 | })
58 | })
59 | // Monitors & sends the value to the patch editor
60 | picker.selectedIndex.monitor({fireOnInitialValue: true}).subscribe((val)=>{
61 | Patches.inputs.setScalar("scriptToEditorVar", val.newValue); // "scriptToEditorVar" is the name of your "From Script" variable (it has to be a Number Variable, unless you change the setScalar part)
62 | userScope.set("index", { value: (val.newValue) }) // sets the value of the key
63 | timer.unsubscribe() // clears the last timeout
64 | timer = Time.setTimeout(()=>{userScope.remove("index")}, 12000); // 12000 is the amount of time the index is storred in memory in ms| 12000ms = 12s
65 | })
66 | // Makes it visible (calls a try/catch block that makes sure it's set to visible = true)
67 | visible();
68 |
--------------------------------------------------------------------------------
/Native UI Multiple Sliders/script.js:
--------------------------------------------------------------------------------
1 | const NUI = require('NativeUI');
2 | const Textures = require('Textures');
3 | const Patches = require('Patches');
4 | const Persistence = require('Persistence');
5 | const Diagnostics = require('Diagnostics');
6 |
7 | const Picker = {
8 | icons: null,
9 | sliderValue: 0.5,
10 | defaultSliderValue: 0.5,
11 | pickerIndex: 0,
12 | settings: {},
13 | persistenceKey: 'multipleSliders',
14 |
15 | init(assets = []) {
16 | Promise.all(assets).then((assets) => this.onLoad(assets));
17 | },
18 | onLoad(assets) {
19 | this.icons = assets[0];
20 | this.setUpPicker()
21 | .then(() => {
22 | return this.persistence();
23 | })
24 | .then(() => {
25 | return this.setUpSlider();
26 | })
27 | .then(() => {
28 | this.monitorIndex();
29 | });
30 | },
31 | setUpPicker() {
32 | return new Promise((resolve) => {
33 | this.icons.sort((a, b) => {
34 | return a.name.localeCompare(b.name);
35 | });
36 | let iconsArray = [];
37 | this.icons.forEach((element) => {
38 | iconsArray.push({ image_texture: element });
39 | });
40 | NUI.picker.configure({ selectedIndex: 0, items: iconsArray });
41 | NUI.picker.visible = true;
42 | resolve();
43 | });
44 | },
45 | setUpSlider() {
46 | return new Promise((resolve) => {
47 | if (this.settings[this.pickerIndex]) {
48 | NUI.slider.value = this.settings[this.pickerIndex];
49 | } else {
50 | NUI.slider.value = this.sliderValue;
51 | }
52 |
53 | NUI.slider.visible = true;
54 | NUI.slider.value
55 | .monitor({ fireOnInitialValue: false })
56 | .select('newValue')
57 | .subscribe((val) => {
58 | this.sliderValue = val;
59 | if (this.settings[this.pickerIndex]) {
60 | this.settings[this.pickerIndex] +=
61 | val - this.settings[this.pickerIndex];
62 | } else {
63 | this.settings[this.pickerIndex] = val;
64 | }
65 |
66 | this.pushToPatches();
67 | require('Diagnostics').log(this.settings);
68 | });
69 | resolve();
70 | });
71 | },
72 | monitorIndex() {
73 | NUI.picker.selectedIndex
74 | .monitor({ fireOnInitialValue: true })
75 | .select('newValue')
76 | .subscribe((index) => {
77 | if (this.settings.hasOwnProperty(index)) {
78 | NUI.slider.value = this.settings[index];
79 | } else {
80 | NUI.slider.value = this.defaultSliderValue;
81 | }
82 | this.pickerIndex = index;
83 | });
84 | },
85 | pushToPatches() {
86 | for (const key in this.settings) {
87 | Patches.inputs.setScalar(`setting${key}`, this.settings[key]);
88 | }
89 | try {
90 | Persistence.userScope.set(this.persistenceKey, { v: this.settings });
91 | } catch (error) {
92 | Diagnostics.log(
93 | `The key: "${this.persistenceKey}" is not whitelisted (case sensitive)`
94 | );
95 | }
96 | },
97 | persistence() {
98 | return new Promise((resolve) => {
99 | try {
100 | Persistence.userScope.get(this.persistenceKey).then((v) => {
101 | try {
102 | this.settings = v.v;
103 | Diagnostics.log(this.settings);
104 | } catch {
105 | Diagnostics.log('There were no settings saved');
106 | }
107 | this.pushToPatches();
108 | resolve();
109 | });
110 | } catch {
111 | Diagnostics.log(
112 | `The key: "${this.persistenceKey}" is not whitelisted (case sensitive)`
113 | );
114 | }
115 | });
116 | },
117 | };
118 | Picker.init([Textures.findUsingPattern('icon*')]);
119 |
--------------------------------------------------------------------------------
/raymarching-v1.0.102-g/objects/Cube/Cube.gltf:
--------------------------------------------------------------------------------
1 | {
2 | "asset" : {
3 | "copyright" : "Facebook",
4 | "generator" : "Khronos glTF Blender I/O v0.9.36",
5 | "version" : "2.0"
6 | },
7 | "scene" : 0,
8 | "scenes" : [
9 | {
10 | "name" : "Scene",
11 | "nodes" : [
12 | 0
13 | ]
14 | }
15 | ],
16 | "nodes" : [
17 | {
18 | "mesh" : 0,
19 | "name" : "Cube",
20 | "scale" : [
21 | 0.009999999776482582,
22 | 0.009999999776482582,
23 | 0.009999999776482582
24 | ]
25 | }
26 | ],
27 | "materials" : [
28 | {
29 | "alphaMode" : "BLEND",
30 | "name" : "Cube_mat",
31 | "pbrMetallicRoughness" : {
32 | "baseColorFactor" : [
33 | 1,
34 | 1,
35 | 1,
36 | 1
37 | ],
38 | "metallicFactor" : 0.10000000149011612,
39 | "roughnessFactor" : 0.5
40 | }
41 | }
42 | ],
43 | "meshes" : [
44 | {
45 | "name" : "Mesh.005",
46 | "primitives" : [
47 | {
48 | "attributes" : {
49 | "POSITION" : 0,
50 | "NORMAL" : 1,
51 | "TEXCOORD_0" : 2
52 | },
53 | "indices" : 3,
54 | "material" : 0
55 | }
56 | ]
57 | }
58 | ],
59 | "accessors" : [
60 | {
61 | "bufferView" : 0,
62 | "componentType" : 5126,
63 | "count" : 24,
64 | "max" : [
65 | 2.500004291534424,
66 | 2.5,
67 | 2.5
68 | ],
69 | "min" : [
70 | -2.5,
71 | -2.5,
72 | -2.5
73 | ],
74 | "type" : "VEC3"
75 | },
76 | {
77 | "bufferView" : 1,
78 | "componentType" : 5126,
79 | "count" : 24,
80 | "type" : "VEC3"
81 | },
82 | {
83 | "bufferView" : 2,
84 | "componentType" : 5126,
85 | "count" : 24,
86 | "type" : "VEC2"
87 | },
88 | {
89 | "bufferView" : 3,
90 | "componentType" : 5123,
91 | "count" : 36,
92 | "type" : "SCALAR"
93 | }
94 | ],
95 | "bufferViews" : [
96 | {
97 | "buffer" : 0,
98 | "byteLength" : 288,
99 | "byteOffset" : 0
100 | },
101 | {
102 | "buffer" : 0,
103 | "byteLength" : 288,
104 | "byteOffset" : 288
105 | },
106 | {
107 | "buffer" : 0,
108 | "byteLength" : 192,
109 | "byteOffset" : 576
110 | },
111 | {
112 | "buffer" : 0,
113 | "byteLength" : 72,
114 | "byteOffset" : 768
115 | }
116 | ],
117 | "buffers" : [
118 | {
119 | "byteLength" : 840,
120 | "uri" : "data:application/octet-stream;base64,8v8fwAAAIMDk/x9AEgAgQAAAIEDm/x9A8v8fwAAAIEDk/x9AAAAgQAAAIMAAACBA//8fQAAAIMD//x/AAAAgwAAAIEAAACDA//8fQAAAIED//x/AAAAgwAAAIMAAACDA8v8fwAAAIEDk/x9A//8fQAAAIED//x/AAAAgwAAAIEAAACDAEgAgQAAAIEDm/x9A//8fQAAAIMD//x/A8v8fwAAAIMDk/x9AAAAgwAAAIMAAACDAAAAgQAAAIMAAACBA8v8fwAAAIMDk/x9AAAAgwAAAIEAAACDAAAAgwAAAIMAAACDA8v8fwAAAIEDk/x9AEgAgQAAAIEDm/x9A//8fQAAAIMD//x/A//8fQAAAIED//x/AAAAgQAAAIMAAACBAYY9CtW1mJjUAAIA/YY9CtW1mJjUAAIA/YY9CtW1mJjUAAIA/YY9CtW1mJjUAAIA/CtcjMwAAAAAAAIC/CtcjMwAAAAAAAIC/CtcjMwAAAAAAAIC/CtcjMwAAAAAAAIC/AAAAAAAAgD/ezEwzAAAAAAAAgD/ezEwzAAAAAAAAgD/ezEwzAAAAAAAAgD/ezEwzAAAAAAAAgL8V1yMzAAAAAAAAgL8V1yMzAAAAAAAAgL8V1yMzAAAAAAAAgL8V1yMzAACAvwAAAABDMzM1AACAvwAAAABDMzM1AACAvwAAAABDMzM1AACAvwAAAABDMzM1AACAPxHXo7QFAAC1AACAPxHXo7QFAAC1AACAPxHXo7QFAAC1AACAPxHXo7QFAAC1AACAPgAAwD4AAAA/AAAgPwAAgD4AACA/AAAAPwAAwD4AAEA/AADAPgAAgD8AACA/AABAPwAAID8AAIA/AADAPgAAgD4AACA/AAAAPwAAYD8AAIA+AABgPwAAAD8AACA/AAAAPwAAAD4AAIA+AADAPgAAgD4AAAA+AAAAPwAAwD4AAIA+AADAPgAAAAAAACA/AAAAAAAAwD4AAIA+AAAgPwAAAD8AACA/AABAPwAAwD4AAEA/AAAgPwAAAD8AAMA+AAABAAIAAAADAAEABAAFAAYABAAHAAUACAAJAAoACAALAAkADAANAA4ADwANAAwAEAARABIAEAATABEAFAAVABYAFAAXABUA"
121 | }
122 | ]
123 | }
124 |
--------------------------------------------------------------------------------
/raymarching-v1.0.102-g/shaders/Raymarching 1.0.102.sca:
--------------------------------------------------------------------------------
1 | precision highp float;
2 |
3 | #define time std::getTime()
4 |
5 | // Namespace for all the SDF functions :)
6 | // SDF::scene is the SDF to be rendered
7 | namespace SDF {
8 | float sphere( vec3 p, float s ){
9 | return length(p)-s;
10 | };
11 | float box( vec3 p, vec3 b ){
12 | vec3 q = abs(p) - b;
13 | return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0);
14 | };
15 | float roundBox( vec3 p, vec3 b, float r ){
16 | vec3 q = abs(p) - b;
17 | return length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0) - r;
18 | };
19 | float torus( vec3 p, vec2 t ){
20 | vec2 q = vec2(length(p.xz)-t.x,p.y);
21 | return length(q)-t.y;
22 | };
23 | float cone( in vec3 p, in vec2 c, float h ){
24 | // c is the sin/cos of the angle, h is height
25 | // Alternatively pass q instead of (c,h),
26 | // which is the point at the base in 2D
27 | vec2 q = h*vec2(c.x/c.y,-1.0);
28 |
29 | vec2 w = vec2( length(p.xz), p.y );
30 | vec2 a = w - q*clamp( dot(w,q)/dot(q,q), 0.0, 1.0 );
31 | vec2 b = w - q*vec2( clamp( w.x/q.x, 0.0, 1.0 ), 1.0 );
32 | float k = sign( q.y );
33 | float d = min(dot( a, a ),dot(b, b));
34 | float s = max( k*(w.x*q.y-w.y*q.x),k*(w.y-q.y) );
35 | return sqrt(d)*sign(s);
36 | };
37 | float octahedron( vec3 p, float s){
38 | p = abs(p);
39 | float m = p.x+p.y+p.z-s;
40 | vec3 q;
41 | if( 3.0*p.x < m ) q = p.xyz;
42 | else if( 3.0*p.y < m ) q = p.yzx;
43 | else if( 3.0*p.z < m ) q = p.zxy;
44 | else return m*0.57735027;
45 |
46 | float k = clamp(0.5*(q.z-q.y+s),0.0,s);
47 | return length(vec3(q.x,q.y-s+k,q.z-k));
48 | };
49 | float opSmoothUnion( float d1, float d2, float k ) {
50 | float h = clamp( 0.5 + 0.5*(d2-d1)/k, 0.0, 1.0 );
51 | return mix( d2, d1, h ) - k*h*(1.0-h);
52 | };
53 | float opSmoothSubtraction( float d1, float d2, float k ) {
54 | float h = clamp( 0.5 - 0.5*(d2+d1)/k, 0.0, 1.0 );
55 | return mix( d2, -d1, h ) + k*h*(1.0-h);
56 | };
57 |
58 | float opSmoothIntersection( float d1, float d2, float k ) {
59 | float h = clamp( 0.5 - 0.5*(d2-d1)/k, 0.0, 1.0 );
60 | return mix( d2, d1, h ) + k*h*(1.0-h);
61 | };
62 | float scene(vec3 p){
63 | // Rotation matrix (X axis)
64 | mat3 rotation = mat3(vec3(1,0,0),
65 | vec3(0,cos(time),-sin(time)),
66 | vec3(0,sin(time),cos(time)));
67 |
68 | float t = octahedron(((p - vec3(0,0.02,0) * rotation) * rotation), 0.01);
69 |
70 | float s = sphere(p, 0.005);
71 |
72 | float b = box(
73 | p-vec3(sin(time * 0.7) * 0.03, 0, 0),
74 | vec3(0.005)
75 | );
76 |
77 | float finalSDF;
78 | finalSDF = opSmoothUnion(s, b, 0.008);
79 | finalSDF = opSmoothUnion(finalSDF, t, 0.005);
80 |
81 | return finalSDF;
82 | };
83 | };
84 |
85 | vec3 getCameraRayDir(vec2 uv, vec3 camPos, vec3 camTarget){
86 | vec3 camForward = normalize(camTarget - camPos);
87 | vec3 camRight = normalize(cross(vec3(0.0, 1.0, 0.0), camForward));
88 | vec3 camUp = normalize(cross(camForward, camRight));
89 |
90 | float fPersp = 2.;
91 | vec3 vDir = normalize(uv.x * camRight + uv.y * camUp + camForward * fPersp);
92 |
93 | return vDir;
94 | };
95 |
96 | float castRay(vec3 rayOrigin, vec3 rayDir){
97 | float t = 0.; // Distance along ray
98 |
99 | // More iterations leads to better quality/less artifacts but it will reduce performace
100 | for (int i = 0; i < 64; i++){
101 | float res = SDF::scene(rayOrigin + rayDir * t);
102 | if (res < (0.0001*t)){
103 | return t;
104 | };
105 | t += res;
106 | };
107 |
108 | return -1.0;
109 | };
110 |
111 | // Calculate the normals for a shape
112 | vec3 calcNormal(vec3 p){
113 | // Center sample
114 | float c = SDF::scene(p);
115 | vec2 eps_zero = vec2(0.001, 0.0);
116 | return normalize(vec3( SDF::scene(p + eps_zero.xyy), SDF::scene(p + eps_zero.yxy), SDF::scene(p + eps_zero.yyx) ) - c);
117 | };
118 |
119 | // Hard Shadows
120 | //float shadow( vec3 ro, vec3 rd, float mint, float maxt ){
121 | // float t = mint;
122 | // for ( int i = 0; i < 32; ++i ){
123 | // float h = SDF::scene( ro + rd * t );
124 | // if ( h < 0.001 )
125 | // return 0.0;
126 | // t += h;
127 | //
128 | // if ( t > maxt )
129 | // break;
130 | // };
131 | // return 1.0;
132 | //};
133 |
134 | float shadowSoft( vec3 ro, vec3 rd, float mint, float maxt, float k ){
135 | float t = mint;
136 | float res = 1.0;
137 | for ( int i = 0; i < 32; ++i ){
138 | float h = SDF::scene( ro + rd * t );
139 | if ( h < 0.001 )
140 | return 0.0;
141 |
142 | res = min( res, k * h / t );
143 | t += h;
144 |
145 | if ( t > maxt )
146 | break;
147 | };
148 | return res;
149 | };
150 |
151 | vec3 shade( vec3 p, vec3 nrm, vec4 light ){
152 | vec3 toLight = light.xyz - p;
153 |
154 | float toLightLen = length( toLight );
155 | toLight = normalize( toLight );
156 |
157 | float comb = 0.1;
158 |
159 | float vis = shadowSoft( p, toLight, 0.0625, toLightLen, 8.0 );
160 |
161 | if ( vis > 0.0 ){
162 | float diff = 2.0 * max( 0.0, dot( nrm, toLight ) );
163 | float attn = 1.0 - pow( min( 1.0, toLightLen / light.w ), 2.0 );
164 | comb += diff * attn * vis;
165 | };
166 | return vec3( comb, comb, comb );
167 | };
168 |
169 | vec4 render(vec3 rayOrigin, vec3 rayDir){
170 | vec4 col;
171 | float t = castRay(rayOrigin, rayDir);
172 |
173 | if (t != -1.0){
174 | // our ray hit the scene, so shade it with 2 lights
175 | vec3 p = rayOrigin + rayDir * t;
176 | // Normals of the shape
177 | vec3 N = normalize(calcNormal(p));
178 |
179 | // Light 1
180 | vec4 L1 = vec4(
181 | sin(time * 2.2),
182 | 2.,
183 | cos(time * 2.2),
184 | 3.
185 | );
186 | L1 = normalize(L1);
187 |
188 | // Light 1
189 | vec4 L2 = vec4(
190 | cos(time * 2.2),
191 | 2.,
192 | sin(time * 2.2),
193 | 3.
194 | );
195 | L2 = normalize(L2);
196 |
197 | vec3 shade1 = shade( p, N, L1 );
198 | vec3 shade2 = shade( p, N, L2 );
199 |
200 | // Shade
201 | vec3 shadeAll =
202 | shade1 * (vec3( 1.0, 0.3, 0.2 ))
203 | + shade2 * (vec3( 0.1, 0.2, 1.0 ));
204 |
205 | col = vec4(shadeAll,1);
206 | } else {
207 | // The ray hit nothing, render as 0,0,0,0 (transparent)
208 | col = vec4(0);
209 | };
210 | col = pow(col, vec4(0.4545, 0.4545, 0.4545, 1));
211 | return col;
212 | };
213 |
214 | vec2 normalizeScreenCoords(vec2 screenCoord){
215 | vec2 result = 2.0 * (screenCoord - 0.5);
216 | return result;
217 | };
218 |
219 | // @main
220 | void main(in function image, out vec4 fragColor) {
221 | // The "image" isn't used *yet*, it's for future functions
222 | vec2 uv = fragment(normalizeScreenCoords(std::getVertexTexCoord()));
223 |
224 | vec4 p = fragment(std::getVertexPosition());
225 | // Thanks @alwayscodingsomething for the matrix help
226 | mat4 im = std::getInverseModelMatrix();
227 | vec4 cam = std::getCameraPosition();
228 | vec4 oro = im*cam;
229 | vec3 ro = oro.xyz;
230 | vec3 rd = normalize(p.xyz-ro);
231 |
232 | vec4 col = render(ro, rd);//
233 |
234 | fragColor = vec4(col);
235 | };
236 |
--------------------------------------------------------------------------------