summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-09-06 22:40:08 -0400
committerpommicket <pommicket@gmail.com>2023-09-06 22:40:08 -0400
commitc7b9db0d1bf3ae55c7e70207c636ced8606902ec (patch)
tree539995efe448a1eaa71ae3f11479c2b05c02cfb5
parent6cb40e9bc8c5f15a0c5158fe2c65b507221e4b4d (diff)
add some more widgets, cleanup
-rw-r--r--guide-src/index.html122
-rw-r--r--guide-src/introduction.html118
-rw-r--r--guide-src/outline.txt1
-rw-r--r--guide-src/widget-inputs.html3
-rw-r--r--index.html32
-rw-r--r--pugl.js294
-rw-r--r--style.css3
-rw-r--r--things.txt3
8 files changed, 389 insertions, 187 deletions
diff --git a/guide-src/index.html b/guide-src/index.html
index 0e765b4..e590fc7 100644
--- a/guide-src/index.html
+++ b/guide-src/index.html
@@ -1,118 +1,20 @@
---- introduction
+--- about
-<h3>your first pugl</h3>
+<h2>pugl</h2>
+<i><b>p</b>ommicket's <b>u</b>tility for <b>gl</b> shaders</i>
+<hr>
<p>
-when you load up pugl for the first time, you should be greeted with a “Buffer” widget.
-try changing its “input” value to <code>.pos.x</code>.
-<div>
- <img src="ex-posx.png" alt="">
-</div>
-you should see a nice gradient like this: <span style="display:inline-block;margin-right:1em;width:2em;height:1em;background-image:linear-gradient(90deg, #000,#000,#000,#fff);"></span>
-here the color of each pixel is directly determined by its x coordinate.
-specifically: <code>.pos.x</code> is −1 at the left side of the screen and +1 at the right side of the screen.
-since the “Buffer” widget’s title is in <span style="color:yellow;font-weight:bold;">yellow</span>,
-the pixel values will be drawn from it. 0 (or anything below 0) is black and 1 (or anything above 1) is white,
-so we see a gradient from black to white starting from the center of the screen.
+ pugl is a tool that lets you create &amp; share shaders without writing any code.
</p>
<p>
-now let’s try something a little more interesting. try adding a “Multiply” widget (by searching for it or
-selecting it from the “math” section). set the “a” input to <code>.pos.x</code> and the “b” input to
-<code>.pos.y</code>. then click on the “Multiply” text to set it as the active widget.
-<div>
- <img src="ex-multiply.png" alt="">
-</div>
-you should now see a more interesting pattern where two of the corners of the screen are
-white, and the other two corners are black: <img src="output-multiply.png" style="height:1em;" alt="">
-</p>
-
-<h3>vectors</h3>
-
-<p>
-well, black &amp; white is pretty boring. let’s try making some colors!
-one of the nice things about shaders is that they’re very good at dealing with <a href="https://en.wikipedia.org/wiki/Vector_%28mathematics_and_physics%29" target="_blank">vectors</a>.
-there’s a lot of mathematical theory behind vectors, but for our purposes all that really matters is that a vector is a list of numbers (called <em>components</em>).
-in shaders you basically only deal with vectors with 2 to 4 components (referred to as x, y, z, w).
-in graphics programming, colors are represented as vectors with 3 components, <span style="color:#f00;">red</span>,
-<span style="color:#0f0;">green</span>, and <span style="color:#22f;">blue</span>, which go from 0 to 1.
-try putting <code>0,0.8,1</code> in a “Buffer” widget and making it active.
-now the widget is outputting a vector with x=0, y=0.8, and z=1, so
-you’ll get a nice <span style="color:#0cf">greenish blue</span> color!
-</p>
-
-<p>
-<code>.pos</code> is itself a vector, so you can just throw it into the Buffer input:
-<div><img src="ex-vector.png" alt=""> <img src="output-vector.png" alt="" height="32"></div>
-notice how the output is red on the right side of the screen (where the x component of <code>.pos</code> is high)
-and green at the top of the screen (where the y component of <code>.pos</code> is high).
-</p>
-
-<p>
-most widgets like Multiply work on both numbers and vectors. try multiplying together
-<code>.pos</code> and <code>.pos.x</code>:
-<div><img src="ex-multiply-vector.png" alt=""> <img src="output-multiply-vector.png" alt="" height="32"></div>
-this multiplies each of the components of <code>.pos</code> by <code>.pos.x</code>.
-so the top-left corner is red, because (−1, 1) × −1 = (1, −1), so the top-left pixel gets a red value of 1 and a green value of −1.
-</p>
-
-<h3>multiple widgets</h3>
-
-<p>
-you can use the output of one widget to specify the input of another widget using its name.
-try creating an “Add” widget with inputs <code>mul1,0</code> and <code>0,0,.pos.x</code> (assuming
-your Multiply widget from the last section was called mul1).
-<div><img src="ex-multiply-add.png" alt=""> <img src="output-multiply-add.png" alt="" height="32"></div>
-now the left side looks the same as before, but the right side (where <code>.pos.x</code> is 1) is bluer!
-</p>
-
-<h3>putting everything together</h3>
-
-<p>
-alright let's use all this to make something cool.
-we'll start by making a rainbow.
-the “Hue shift” widget shifts the hue of a color through the rainbow.
-so if we start with a color of red, and shift it by <code>.pos.x</code>,
-we'll get a rainbow across the screen:
-<div>
-<img src="ex-hue-shift.png" alt=""> <img src="output-hue-shift.png" alt="" height="32">
-</div>
-</p>
-
-<p>
-now let's animate this rainbow: create a new “Add” widget,
-and set a=<code>.pos.x</code>, b=<code>.time</code>,
-and use that as the shift instead of <code>.pos.x</code>:
-<div><img src="ex-hue-shift-time.png" alt=""></div>
-now the rainbow moves across the screen over time!
-</p>
-
-<p>
-next we’ll use the widget that makes pugl unique ☺
-“Last frame”. this lets you grab pixel values from the previous frame
-to use in the current frame. add a “Last frame” widget,
-and set it as the active widget. notice how the rainbow freezes in place —
-that’s because each pixel value is just being determined by what it was
-on the last frame.
-<div><img src="ex-last-frame.png" alt=""></div>
+ to learn how to use pugl, check out <a href="introduction.html">the next section</a>.
</p>
+<h3>credits</h3>
+<hr>
<p>
-now add a “Weighted sum” widget, set “a weight” to 0.95, “b weight” to 0.05,
-”a” to your last frame widget's output, and “b” to the hue shift's output.
-this will output a value which is 95% like the previous frame's value,
-and 5% like the shifting rainbow.
-<div><img src="ex-weighted-sum.png" alt=""></div>
-try switching between the “Hue shift” and “Weighted sum” widgets
-and note how the weighted sum is blurrier, because it's averaging
-with the previous pixel value.
+icon based on
+<a href="https://commons.wikimedia.org/wiki/File:Long-beakedEchidna.jpg" target="_blank">Long-beakedEchidna.jpg from WikiMedia</a>
+CC BY-SA 3.0.
</p>
<p>
-now, we don’t have to use <code>.pos</code> as the position for getting
-pixel values from the last frame. instead, let’s rotate <code>.pos</code>
-by a small amount and use that as the position for the “Last frame” widget:
-<div><img src="ex-rotate-2d.png" alt=""> <img src="output-rotate-2d.png" alt=""></div>
-now we’re getting something interesting!
-</p>
-
-<p>
-be sure to check out the rest of this guide to learn all the things
-you can do with pugl. have fun! 🐱
-</p>
+everything else is licensed under WTFPLv2.
diff --git a/guide-src/introduction.html b/guide-src/introduction.html
new file mode 100644
index 0000000..5dd2bdc
--- /dev/null
+++ b/guide-src/introduction.html
@@ -0,0 +1,118 @@
+--- introduction
+
+<h3>your first pugl</h3>
+<p>
+when you load up pugl for the first time, you should be greeted with a “Buffer” widget.
+try changing its “input” value to <code>.pos.x</code>.
+<div>
+ <img src="ex-posx.png" alt="">
+</div>
+you should see a nice gradient like this: <span style="display:inline-block;margin-right:1em;width:2em;height:1em;background-image:linear-gradient(90deg, #000,#000,#000,#fff);"></span>
+here the color of each pixel is directly determined by its x coordinate.
+specifically: <code>.pos.x</code> is −1 at the left side of the screen and +1 at the right side of the screen.
+since the “Buffer” widget’s title is in <span style="color:yellow;font-weight:bold;">yellow</span>,
+the pixel values will be drawn from it. 0 (or anything below 0) is black and 1 (or anything above 1) is white,
+so we see a gradient from black to white starting from the center of the screen.
+</p>
+<p>
+now let’s try something a little more interesting. try adding a “Multiply” widget (by searching for it or
+selecting it from the “math” section). set the “a” input to <code>.pos.x</code> and the “b” input to
+<code>.pos.y</code>. then click on the “Multiply” text to set it as the active widget.
+<div>
+ <img src="ex-multiply.png" alt="">
+</div>
+you should now see a more interesting pattern where two of the corners of the screen are
+white, and the other two corners are black: <img src="output-multiply.png" style="height:1em;" alt="">
+</p>
+
+<h3>vectors</h3>
+
+<p>
+well, black &amp; white is pretty boring. let’s try making some colors!
+one of the nice things about shaders is that they’re very good at dealing with <a href="https://en.wikipedia.org/wiki/Vector_%28mathematics_and_physics%29" target="_blank">vectors</a>.
+there’s a lot of mathematical theory behind vectors, but for our purposes all that really matters is that a vector is a list of numbers (called <em>components</em>).
+in shaders you basically only deal with vectors with 2 to 4 components (referred to as x, y, z, w).
+in graphics programming, colors are represented as vectors with 3 components, <span style="color:#f00;">red</span>,
+<span style="color:#0f0;">green</span>, and <span style="color:#22f;">blue</span>, which go from 0 to 1.
+try putting <code>0,0.8,1</code> in a “Buffer” widget and making it active.
+now the widget is outputting a 3D vector with x=0, y=0.8, and z=1, so
+you’ll get a nice <span style="color:#0cf">greenish blue</span> color!
+</p>
+
+<p>
+<code>.pos</code> is itself a vector, so you can just throw it into the Buffer input:
+<div><img src="ex-vector.png" alt=""> <img src="output-vector.png" alt="" height="32"></div>
+notice how the output is red on the right side of the screen (where the x component of <code>.pos</code> is high)
+and green at the top of the screen (where the y component of <code>.pos</code> is high).
+</p>
+
+<p>
+most widgets like Multiply work on both numbers and vectors. try multiplying together
+<code>.pos</code> and <code>.pos.x</code>:
+<div><img src="ex-multiply-vector.png" alt=""> <img src="output-multiply-vector.png" alt="" height="32"></div>
+this multiplies each of the components of <code>.pos</code> by <code>.pos.x</code>.
+so the top-left corner is red, because (−1, 1) × −1 = (1, −1), so the top-left pixel gets a red value of 1 and a green value of −1.
+</p>
+
+<h3>multiple widgets</h3>
+
+<p>
+you can use the output of one widget to specify the input of another widget using its name.
+try creating an “Add” widget with inputs <code>mul1,0</code> and <code>0,0,.pos.x</code> (assuming
+your Multiply widget from the last section was called mul1).
+<div><img src="ex-multiply-add.png" alt=""> <img src="output-multiply-add.png" alt="" height="32"></div>
+now the left side looks the same as before, but the right side (where <code>.pos.x</code> is 1) is bluer!
+</p>
+
+<h3>putting everything together</h3>
+
+<p>
+alright let's use all this to make something cool.
+we'll start by making a rainbow.
+the “Hue shift” widget shifts the hue of a color through the rainbow.
+so if we start with a color of red, and shift it by <code>.pos.x</code>,
+we'll get a rainbow across the screen:
+<div>
+<img src="ex-hue-shift.png" alt=""> <img src="output-hue-shift.png" alt="" height="32">
+</div>
+</p>
+
+<p>
+now let's animate this rainbow: create a new “Add” widget,
+and set a=<code>.pos.x</code>, b=<code>.time</code>,
+and use that as the shift instead of <code>.pos.x</code>:
+<div><img src="ex-hue-shift-time.png" alt=""></div>
+now the rainbow moves across the screen over time!
+</p>
+
+<p>
+next we’ll use the widget that makes pugl unique ☺
+“Last frame”. this lets you grab pixel values from the previous frame
+to use in the current frame. add a “Last frame” widget,
+and set it as the active widget. notice how the rainbow freezes in place —
+that’s because each pixel value is just being determined by what it was
+on the last frame.
+<div><img src="ex-last-frame.png" alt=""></div>
+</p>
+<p>
+now add a “Weighted sum” widget, set “a weight” to 0.95, “b weight” to 0.05,
+”a” to your last frame widget's output, and “b” to the hue shift's output.
+this will output a value which is 95% like the previous frame's value,
+and 5% like the shifting rainbow.
+<div><img src="ex-weighted-sum.png" alt=""></div>
+try switching between the “Hue shift” and “Weighted sum” widgets
+and note how the weighted sum is blurrier, because it's averaging
+with the previous pixel value.
+</p>
+<p>
+now, we don’t have to use <code>.pos</code> as the position for getting
+pixel values from the last frame. instead, let’s rotate <code>.pos</code>
+by a small amount and use that as the position for the “Last frame” widget:
+<div><img src="ex-rotate-2d.png" alt=""> <img src="output-rotate-2d.png" alt=""></div>
+now we’re getting something interesting!
+</p>
+
+<p>
+be sure to check out the rest of this guide to learn all the things
+you can do with pugl. have fun! 🐱
+</p>
diff --git a/guide-src/outline.txt b/guide-src/outline.txt
index df12f5d..a2d8357 100644
--- a/guide-src/outline.txt
+++ b/guide-src/outline.txt
@@ -1,4 +1,5 @@
index.html
+introduction.html
widget-inputs.html
development: development
/index.html
diff --git a/guide-src/widget-inputs.html b/guide-src/widget-inputs.html
index f0e8bdb..048c75f 100644
--- a/guide-src/widget-inputs.html
+++ b/guide-src/widget-inputs.html
@@ -25,7 +25,7 @@ all of pugl's built-in values begin with a <code>.</code> to distinguish
them from your widgets.
here they all are.
below, <code>float</code> refers to a plain old number,
-<code>vec2</code> is a 2-component vector, etc.
+<code>vec2</code> is a 2D vector, etc.
<table>
<tbody>
@@ -37,5 +37,6 @@ below, <code>float</code> refers to a plain old number,
<tr><td><code>.mouse01</code></td><td><code>vec2</code><td>the position of the mouse ranging from (0, 0) to (+1, +1).</td></tr>
<tr><td><code>.pi</code></td><td><code>float</code><td>π (3.1415…).</td></tr>
<tr><td><code>.2pi</code></td><td><code>float</code><td>2π (6.2831…).</td></tr>
+<tr><td><code>.e</code></td><td><code>float</code><td>𝑒 (2.7182…).</td></tr>
</tbody>
</table>
diff --git a/index.html b/index.html
index 16a7c50..8bbbeb8 100644
--- a/index.html
+++ b/index.html
@@ -37,9 +37,11 @@
<img alt="copy link" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PHJlY3QgeD0iNiIgeT0iNCIgd2lkdGg9IjE0IiBoZWlnaHQ9IjIwIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMyIgcng9IjIiIGZpbGw9Im5vbmUiLz48cmVjdCB4PSIxMSIgeT0iOCIgd2lkdGg9IjE0IiBoZWlnaHQ9IjIwIiBzdHJva2U9IiNmZmYiIGNsaXAtcGF0aD0icGF0aCgnTSAyMCAwIGwgMCAyNCBsIC0xNCAwIGwgMCAxMDAgbCAxMDAgMCBMIDEwMCAwIHonKSIgc3Ryb2tlLXdpZHRoPSIzIiByeD0iMiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==">
<span id="copied-notice">Copied link!</span>
</button>
- <button id="about-button" class="img-button" title="about pugl">
- <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PGVsbGlwc2UgY3g9IjE2IiBjeT0iMTYiIHJ4PSIxMiIgcnk9IjEyIiBzdHJva2U9IiNmOGYiIHN0cm9rZS13aWR0aD0iMyIgZmlsbD0ibm9uZSIgLz48dGV4dCBmaWxsPSIjZjhmIiB4PSIxNiIgeT0iMjQiIGZvbnQtd2VpZ2h0PSJib2xkIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIyMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4/PC90ZXh0Pjwvc3ZnPg==">
- </button>
+ <a href="guide/index.html" class="no-text-decoration" target="_blank">
+ <button id="about-button" class="img-button" title="about pugl">
+ <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PGVsbGlwc2UgY3g9IjE2IiBjeT0iMTYiIHJ4PSIxMiIgcnk9IjEyIiBzdHJva2U9IiNmOGYiIHN0cm9rZS13aWR0aD0iMyIgZmlsbD0ibm9uZSIgLz48dGV4dCBmaWxsPSIjZjhmIiB4PSIxNiIgeT0iMjQiIGZvbnQtd2VpZ2h0PSJib2xkIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIyMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4/PC90ZXh0Pjwvc3ZnPg==">
+ </button>
+ </a>
<button id="new-creation" class="img-button" title="new creation">
<img alt="new creation" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PHBhdGggZD0iTTE2IDYgTDE2IDI2IE02IDE2IEwyNiAxNiIgc3Ryb2tlPSIjOGY4IiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjwvc3ZnPg==">
</button>
@@ -98,30 +100,6 @@
</div>
</div>
<div id="error">error</div>
- <dialog id="about-dialog">
- <h2>pugl</h2>
- <i><b>p</b>ommicket's <b>u</b>tility for <b>gl</b> shaders</i>
- <hr>
- <p>
- pugl is a tool that lets you create &amp; share shaders without writing any code.
- </p>
- <p>
- to learn how to use pugl, check out <a href="guide/index.html" target="_blank">the guide</a>.
- </p>
- <h3>credits</h3>
- <hr>
- <p>
- icon based on
- <a href="https://commons.wikimedia.org/wiki/File:Long-beakedEchidna.jpg" target="_blank">Long-beakedEchidna.jpg from WikiMedia</a>
- CC BY-SA 3.0.
- </p>
- <p>
- everything else is licensed under WTFPLv2.
- </p>
- <form method="dialog">
- <button>close</button>
- </form>
- </dialog>
<dialog id="creations-dialog">
<h3>saved creations</h3>
<hr>
diff --git a/pugl.js b/pugl.js
index f5de8b2..3c40494 100644
--- a/pugl.js
+++ b/pugl.js
@@ -76,7 +76,7 @@ const builtin_widgets = [
${type} buffer(${type} x) {
return x;
}`
- ).join('\n'),
+ ).join(''),
`
//! .name: Slider
//! .category: basic
@@ -94,7 +94,8 @@ float slider(float x, float min_val, float max_val) {
}
`,
`
-//! .name: Mix (lerp)
+//! .name: Mix
+//! .alt: lerp
//! .category: basic
//! .id: mix
//! .description: weighted average of two inputs
@@ -115,7 +116,7 @@ ${type} mix_(${type} a, ${type} b, ${type} x, int c) {
return mix(a, b, x);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Last frame
//! .category: basic
@@ -145,7 +146,7 @@ vec3 last_frame(vec2 pos, int wrap, int samp) {
`
//! .name: Weighted sum
//! .alt: weighted add
-//! .category: math
+//! .category: arithmetic
//! .description: add two numbers or vectors with weights
//! aw.name: a weight
//! aw.default: 1
@@ -159,10 +160,10 @@ ${type} wtadd(${type} a, float aw, ${type} b, float bw) {
return a * aw + b * bw;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Add
-//! .category: math
+//! .category: arithmetic
//! .description: add two numbers or vectors
` +
@@ -172,10 +173,10 @@ ${type} add(${type} a, ${type} b) {
return a + b;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Subtract
-//! .category: math
+//! .category: arithmetic
//! .description: subtract one number or vector from another
` +
@@ -185,10 +186,10 @@ ${type} sub(${type} a, ${type} b) {
return a - b;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Multiply
-//! .category: math
+//! .category: arithmetic
//! .description: multiply two numbers, scale a vector by a number, or perform component-wise multiplication between vectors
` +
GLSL_FLOAT_TYPES.map(
@@ -197,10 +198,10 @@ ${type} mul(${type} a, ${type} b) {
return a * b;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Divide
-//! .category: math
+//! .category: arithmetic
//! .description: divide one number or vector by another
` +
GLSL_FLOAT_TYPES.map(
@@ -209,12 +210,14 @@ ${type} div(${type} a, ${type} b) {
return a / b;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Power
-//! .category: math
+//! .category: arithmetic
//! .id: pow
//! .description: take one number to the power of another
+//! a.id: a
+//! b.default: 0.5
` +
GLSL_FLOAT_TYPES.map(
(type) => `
@@ -222,10 +225,10 @@ ${type} pow_(${type} a, ${type} b) {
return pow(a, b);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Modulo
-//! .category: math
+//! .category: arithmetic
//! .id: mod
//! .description: wrap a value at a certain limit
//! a.name: a
@@ -237,7 +240,7 @@ ${type} mod_(${type} a, ${type} b) {
return mod(a, b);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Square
//! .category: geometry
@@ -271,9 +274,9 @@ ${type2} square(${type} pos, ${type2} inside, ${type2} outside, ${type} size) {
}
`
)
- .join('\n');
+ .join('');
})
- .join('\n'),
+ .join(''),
`
//! .name: Circle
//! .category: geometry
@@ -295,7 +298,7 @@ ${type2} circle(${type} pos, ${type2} inside, ${type2} outside, ${type} size) {
return dot(pos, pos) < 1.0 ? inside : outside;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Comparator
//! .category: basic
@@ -319,7 +322,7 @@ ${type} compare(float cmp1, float cmp2, ${type} less, ${type} greater) {
return cmp1 < cmp2 ? less : greater;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Sine wave
//! .category: curves
@@ -363,7 +366,7 @@ ${type} sine_wave(int type, ${type} t, ${type} period, ${type} amp, ${type} phas
return amp * v + center;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Rotate 2D
//! .category: geometry
@@ -463,7 +466,7 @@ ${type} brightcont(${type} color, ${type} brightness, ${type} contrast) {
return clamp((contrast + 1.0) / (1.0 - contrast) * (color - 0.5) + (brightness + 0.5), 0.0, 1.0);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Clamp
//! .category: basic
@@ -483,7 +486,7 @@ ${type} clamp_(${type} x, ${type} minimum, ${type} maximum) {
return clamp(x, minimum, maximum);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Rotate 3D
//! .id: rot3
@@ -530,7 +533,7 @@ ${type} remap(${type} x, ${type} a1, ${type} b1, ${type} a2, ${type} b2) {
return (x - a1) / (b1 - a1) * (b2 - a2) + a2;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Smoothstep
//! .id: smoothstep
@@ -557,11 +560,11 @@ ${type} smoothst(${type} t, ${type} t1, ${type} t2, ${type} out1, ${type} out2)
return mix(out1, out2, smoothstep(t1, t2, t));
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Arctangent
//! .id: arctan2
-//! .category: math
+//! .category: trigonometry
//! .description: The arctangent function (radians) with 2 parameters (set x = 1 for normal arctangent)
//! y.id: y
//! x.id: x
@@ -574,25 +577,53 @@ ${type} arctan2(${type} y, ${type} x) {
return atan(y, x);
}
`
- ).join('\n'),
+ ).join(''),
+ `
+//! .name: Cosine
+//! .id: cos
+//! .category: trigonometry
+//! .description: The cosine function (radians)
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} cos_(${type} x) {
+ return cos(x);
+}
+`
+ ).join(''),
+ `
+//! .name: Sine
+//! .id: sine
+//! .category: trigonometry
+//! .description: The sine function (radians)
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} sin_(${type} x) {
+ return sin(x);
+}
+`
+ ).join(''),
`
//! .name: Tangent
//! .id: tan
-//! .category: math
+//! .category: trigonometry
//! .description: The tangent function (radians)
` +
GLSL_FLOAT_TYPES.map(
(type) => `
-${type} tang(${type} x) {
+${type} tan_(${type} x) {
return tan(x);
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Arcsine
//! .id: arcsin
-//! .category: math
+//! .category: trigonometry
//! .description: The arcsine function (radians) — input will be clamped to [−1, 1]
` +
@@ -602,7 +633,114 @@ ${type} arcsin(${type} x) {
return asin(clamp(x, -1.0, 1.0));
}
`
- ).join('\n'),
+ ).join(''),
+ `
+//! .name: Arccosine
+//! .id: arccos
+//! .category: trigonometry
+//! .description: The arccosine function (radians) — input will be clamped to [−1, 1]
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} arccos(${type} x) {
+ return acos(clamp(x, -1.0, 1.0));
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic cosine
+//! .alt: cosh
+//! .id: cosh
+//! .category: trigonometry
+//! .description: The hyperbolic cosine function
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} cosh_(${type} x) {
+ return cosh(x);
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic sine
+//! .alt: sinh
+//! .id: sinh
+//! .category: trigonometry
+//! .description: The hyperbolic sine function
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} sinh_(${type} x) {
+ return sinh(x);
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic tangent
+//! .alt: tanh
+//! .id: tanh
+//! .category: trigonometry
+//! .description: The hyperbolic tangent function (radians)
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} tanh_(${type} x) {
+ return tanh(x);
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic arccosine
+//! .alt: acosh
+//! .alt: arccosh
+//! .id: arccosh
+//! .category: trigonometry
+//! .description: The hyperbolic arccosine function (radians) — input will be clamped to [1, ∞]
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} arccosh(${type} x) {
+ return acosh(max(x, 1.0));
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic arcsine
+//! .alt: asinh
+//! .alt: arcsinh
+//! .id: arcsinh
+//! .category: trigonometry
+//! .description: The hyperbolic arcsine function (radians)
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} arcsinh(${type} x) {
+ return asinh(x);
+}
+`
+ ).join(''),
+ `
+//! .name: Hyperbolic arctangent
+//! .alt: atanh
+//! .alt: arctanh
+//! .id: arctanh
+//! .category: trigonometry
+//! .description: The hyperbolic arctangent function (radians) — input will be clamped to [-1, 1]
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} arctanh(${type} x) {
+ return atanh(clamp(x, -1.0, 1.0));
+}
+`
+ ).join(''),
`
//! .name: Sigmoid
//! .id: sigmoid
@@ -620,9 +758,9 @@ ${type} sigmoid(${type} x, ${type} a, ${type} b, ${type} sharpness) {
return mix(a, b, 1.0 / (1.0 + exp(-sharpness * x)));
}
`
- ).join('\n'),
+ ).join(''),
`
-//! .name: Staircase (floor)
+//! .name: Staircase
//! .id: floor
//! .category: curves
//! .description: The floor function — largest integer less than x
@@ -640,7 +778,7 @@ ${type} floorf(${type} x, ${type} stepw, ${type} steph, ${type} phase) {
return floor(x / stepw + phase) * steph;
}
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Sine noise
//! .category: noise
@@ -733,7 +871,7 @@ float norm(vec4 x) { return length(x); }
(type) => `
float dist(${type} x, ${type} y) { return distance(x, y); }
`
- ).join('\n'),
+ ).join(''),
`
//! .name: Dot product
//! .description: the dot product between two vectors
@@ -745,7 +883,17 @@ float dist(${type} x, ${type} y) { return distance(x, y); }
(type) => `
float dot_prod(${type} x, ${type} y) { return dot(x, y); }
`
- ).join('\n'),
+ ).join(''),
+ `
+//! .name: Cross product
+//! .description: the cross product between two 3D vectors
+//! .category: geometry
+//! .id: cross
+
+vec3 cross_(vec3 x, vec3 y) {
+ return cross(x, y);
+}
+`,
`
//! .name: White noise
//! .description: Uniform distribution over [0, 1)
@@ -969,27 +1117,75 @@ float worley(vec3 p, vec3 freq) {
`
//! .name: Minimum
//! .description: minimum of two values
-//! .category: math
+//! .category: basic
//! .id: min
` +
GLSL_FLOAT_TYPES.map(
(type) => `
-${type} _min(${type} a, ${type} b) {
+${type} min_(${type} a, ${type} b) {
return min(a, b);
}`
- ).join('\n'),
+ ).join(''),
`
//! .name: Maximum
//! .description: maximum of two values
-//! .category: math
+//! .category: basic
//! .id: max
` +
GLSL_FLOAT_TYPES.map(
(type) => `
-${type} _max(${type} a, ${type} b) {
+${type} max_(${type} a, ${type} b) {
return max(a, b);
}`
- ).join('\n'),
+ ).join(''),
+ `
+//! .name: Absolute value
+//! .id: abs
+//! .description: absolute value of number
+//! .category: basic
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} abs_(${type} x) {
+ return abs(x);
+}`
+ ).join(''),
+ `
+//! .name: Floor
+//! .id: floor_
+//! .description: the floor function — greatest integer smaller than x
+//! .category: basic
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} floor_(${type} x) {
+ return floor(x);
+}`
+ ).join(''),
+ `
+//! .name: Ceiling
+//! .id: ceil
+//! .description: the ceiling function — smallest integer greater than x
+//! .category: basic
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} ceil_(${type} x) {
+ return ceil(x);
+}`
+ ).join(''),
+ `
+//! .name: Round
+//! .id: round
+//! .description: round to nearest integer
+//! .category: basic
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} round_(${type} x) {
+ return round(x);
+}`
+ ).join(''),
];
function get_creation_title() {
@@ -1334,6 +1530,8 @@ for (const code of builtin_widgets) {
const result = parse_widget_definition(code);
if (result && result.error) {
console.error(result.error);
+ } else if (widget_info.has(result.id)) {
+ console.error('duplicate widget id', result.id);
} else {
widget_info.set(result.id, result);
}
@@ -1952,6 +2150,8 @@ ${this.code.join('')}
case '.2π':
case '.2pi':
return { code: '(6.2831853)', type: 'float' };
+ case '.e':
+ return { code: '(2.7182818)', type: 'float' };
default:
return { error: `no such builtin: ${input}` };
}
@@ -2523,10 +2723,6 @@ function startup() {
}
});
- document.getElementById('about-button').addEventListener('click', () => {
- document.getElementById('about-dialog').showModal();
- });
-
document.getElementById('list-creations').addEventListener('click', () => {
const container = document.getElementById('creations');
container.innerHTML = '';
@@ -2603,7 +2799,7 @@ function startup() {
});
document.getElementById('code-form').addEventListener('submit', () => {
- import_widgets(code_input.value);
+ new_creation(code_input.value);
});
pause_element = document.getElementById('pause');
diff --git a/style.css b/style.css
index 78debd7..2f15ea4 100644
--- a/style.css
+++ b/style.css
@@ -338,6 +338,9 @@ input[type='number'] {
.inline-block {
display: inline-block;
}
+.no-text-decoration {
+ text-decoration: none;
+}
.no-wrap {
whitespace: no-wrap;
}
diff --git a/things.txt b/things.txt
index e27e313..bc1692d 100644
--- a/things.txt
+++ b/things.txt
@@ -10,3 +10,6 @@ floor;n:floor1;ix:.pos01.x;istepw:0.1;isteph:0.1,0.1,0.2;iphase:0;;_out=floor1
noisy:
buffer;n:output;iinput:sn1,sn2,sn3;;rot2;n:rot21;iv:.pos;itheta:mul1.w;cdir:0;;circle;n:circle1;ipos:.pos;iinside:rot21,0;ioutside:#000;isize:0.8;;noise_sin;n:sn1;ix:rot21.xy,mul1.x;;remap;n:remap1;ix:.pos;ia1:-1;ib1:1;ia2:0;ib2:6.28;;noise_sin;n:sn2;ix:rot21.xy,mul1.y;;noise_sin;n:sn3;ix:rot21.xy,mul1.z;;mul;n:mul1;ia:.time;ib:0.2,0.4,0.6,0.1;;prev;n:prev1;ipos:.pos;cwrap:0;csample:0;;_out=output
+
+simple cross product:
+_title=cross;;cross;n:cross1;ix:.pos.xy,1;iy:0.2,.pos.xy;;_out=cross1