summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-08-28 11:50:57 -0400
committerpommicket <pommicket@gmail.com>2023-08-28 11:50:57 -0400
commitf4cc8ce7a8712e2e840b0c120a3f86eadb665626 (patch)
tree36f5ee546dce6395006decc50418ccf7505f4237
parentf790b4e1baa5dfe1296cf0887011583bee7afca8 (diff)
add, sub, div, more work on the guide
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--README.md31
-rw-r--r--guide-src/development/index.html27
-rw-r--r--guide-src/development/js-features.html22
-rw-r--r--guide-src/ex-multiply-add.pngbin0 -> 6404 bytes
-rw-r--r--guide-src/ex-multiply-vector.pngbin0 -> 3176 bytes
-rw-r--r--guide-src/ex-multiply.pngbin0 -> 3410 bytes
-rw-r--r--guide-src/ex-posx.pngbin0 -> 2804 bytes
-rw-r--r--guide-src/ex-vector.pngbin0 -> 2609 bytes
-rw-r--r--guide-src/index.html69
-rw-r--r--guide-src/make.py108
-rw-r--r--guide-src/outline.txt7
-rw-r--r--guide-src/output-multiply-add.pngbin0 -> 1203 bytes
-rw-r--r--guide-src/output-multiply-vector.pngbin0 -> 1124 bytes
-rw-r--r--guide-src/output-multiply.pngbin0 -> 1059 bytes
-rw-r--r--guide-src/widget-inputs/builtins.html3
-rw-r--r--guide-src/widget-inputs/constants.html3
-rw-r--r--guide-src/widget-inputs/vectors.html3
-rw-r--r--guide/index.html21
-rw-r--r--pugl.js46
-rw-r--r--style.css40
22 files changed, 328 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index d33e901..cc42ca3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ scratch
*.swp
*~
node_modules
+guide
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4590fa2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,2 @@
+guide-target:
+ python3 guide-src/make.py
diff --git a/README.md b/README.md
index 16271ef..b06dcc5 100644
--- a/README.md
+++ b/README.md
@@ -4,33 +4,4 @@ online shader thingamabob
the main files of interest are `index.html` and `pugl.js`.
-### JS features
-
-i have been pretty liberal about using modern javascript;
-even though this could in theory run on IE it doesn't
-(in particular it is very nice to have template literals).
-that said, try to only use features that have at least as much
-support as webgl2 (i.e. >94%).
-
-no, i do not want to use a "poly-fill".
-
-we use webgl2 (and consequently GLSL ES 3.00) because:
-- having non-constant loops in shaders is nice
-- there aren't that many browsers that support webgl and ES6 but not webgl2 (looking at caniuse.com, they probably
- make up around 2% of browser usage)
-
-### widget description
-
-- `.alt` - alternate text for searching. e.g. a widget with name "Foo" and alt "bar" will
- show up in searches for both "foo" and "bar".
-
-### development
-
-before making any commits, run
-
-```sh
-npm install
-cp -i pre-commit .git/hooks/
-```
-
-this ensures that your changes are prettified &amp; linted.
+for more information, check out the guide.
diff --git a/guide-src/development/index.html b/guide-src/development/index.html
new file mode 100644
index 0000000..717ff6d
--- /dev/null
+++ b/guide-src/development/index.html
@@ -0,0 +1,27 @@
+--- getting started
+
+<p>
+note: this section is only for people who want to contribute to pugl itself.
+</p>
+
+<p>
+after cloning the <a href="https://github.com/pommicket/pugl" target="_blank">repository</a>,
+make sure you run
+<pre><code>npm install
+ln -s ../../pre-commit .git/hooks/</code></pre>
+
+this ensures that your changes are prettified &amp; linted.
+</p>
+
+<p>
+the main files of interest are <code>index.html</code> and <code>pugl.js</code>, which has all
+the JavaScript for pugl (hopefully it doesn't become too unmanageable to have just one file).
+</p>
+
+<h3>contributing to the guide</h3>
+<p>
+the guide is automatically generated from the files in <code>guide-src/</code> by <code>guide-src/make.py</code>
+(you can also just run <code>make</code> to generate it), which is a simple script whose main purpose is adding
+a sidebar to all of the guide pages. any PNG files are automatically copied from <code>guide-src/</code> to <code>guide/</code>.
+when you add or remove pages from the guide, you'll need to edit <code>guide-src/outline.txt</code>.
+</p>
diff --git a/guide-src/development/js-features.html b/guide-src/development/js-features.html
new file mode 100644
index 0000000..ea8ac97
--- /dev/null
+++ b/guide-src/development/js-features.html
@@ -0,0 +1,22 @@
+--- modern JavaScript features
+
+<p>
+pugl has no dependencies, and i'd like to keep it that way.
+</p>
+
+<p>
+i've been pretty liberal about using modern javascript;
+even though this could in theory run on IE it doesn't
+(in particular it's very nice to have template literals).
+that said, try to only use features that have at least as much
+support as webgl2 (i.e. &gt;94%).
+</p>
+
+<p>
+we use webgl2 because:
+<ul>
+ <li>having non-constant loops in shaders is nice</li>
+ <li>there aren't that many browsers that support webgl and ES6 but not webgl2 (looking at caniuse.com, they probably
+ make up around 2% of browser usage)</li>
+</ul>
+</p>
diff --git a/guide-src/ex-multiply-add.png b/guide-src/ex-multiply-add.png
new file mode 100644
index 0000000..1b826ad
--- /dev/null
+++ b/guide-src/ex-multiply-add.png
Binary files differ
diff --git a/guide-src/ex-multiply-vector.png b/guide-src/ex-multiply-vector.png
new file mode 100644
index 0000000..e25ea1d
--- /dev/null
+++ b/guide-src/ex-multiply-vector.png
Binary files differ
diff --git a/guide-src/ex-multiply.png b/guide-src/ex-multiply.png
new file mode 100644
index 0000000..1f3260d
--- /dev/null
+++ b/guide-src/ex-multiply.png
Binary files differ
diff --git a/guide-src/ex-posx.png b/guide-src/ex-posx.png
new file mode 100644
index 0000000..52c4375
--- /dev/null
+++ b/guide-src/ex-posx.png
Binary files differ
diff --git a/guide-src/ex-vector.png b/guide-src/ex-vector.png
new file mode 100644
index 0000000..681c6fe
--- /dev/null
+++ b/guide-src/ex-vector.png
Binary files differ
diff --git a/guide-src/index.html b/guide-src/index.html
new file mode 100644
index 0000000..7b5de8f
--- /dev/null
+++ b/guide-src/index.html
@@ -0,0 +1,69 @@
+--- guide
+
+<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 and 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 simple shader programming all that really matters is that a vector is a list of numbers (called <em>components</em>),
+&amp; in shaders you basically only deal with vectors with 2 to 4 components (labelled 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=""></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>
+
+<h1 style="color:red">TODO</h1>
diff --git a/guide-src/make.py b/guide-src/make.py
new file mode 100644
index 0000000..058a63b
--- /dev/null
+++ b/guide-src/make.py
@@ -0,0 +1,108 @@
+import os, html
+from urllib.parse import quote
+import shutil
+
+INPUT_DIR = 'guide-src'
+OUTPUT_DIR = 'guide'
+TITLE_PREFIX = '---'
+
+os.makedirs(OUTPUT_DIR, exist_ok=True)
+
+try:
+ for f in os.listdir(INPUT_DIR):
+ if f.endswith('.png'):
+ shutil.copyfile(INPUT_DIR + '/' + f, OUTPUT_DIR + '/' + f)
+ elif not '.' in f:
+ os.makedirs(OUTPUT_DIR + '/' + f, exist_ok=True)
+except FileNotFoundError:
+ print('this script must be run from the root directory.')
+ quit()
+
+def readlines(path):
+ f = open(path)
+ l = f.readlines()
+ f.close()
+ return l
+
+class Section:
+ def __init__(self, path, name):
+ self.path = path
+ self.name = name
+ self.items = []
+
+ def __repr__(self):
+ return ''.join(['Section(path=', repr(self.path), ', name=', repr(self.name), ', items=', repr(self.items), ')'])
+
+outline = [l.strip() for l in readlines('{}/outline.txt'.format(INPUT_DIR)) if l.strip()]
+sections = []
+for item in outline:
+ if item[0] == '/':
+ assert item.endswith('.html'), 'expected path ending in .html'
+ sections[-1].items.append(item[1:])
+ else:
+ [path, name] = item.split(': ')
+ sections.append(Section(path, name))
+
+sidebar_content = [
+ ('', '<a class="guide-sidebar-item" href="<ROOT>../index.html">back to pugl</a>'),
+ ('index.html', '<a class="guide-sidebar-item" href="<ROOT>index.html">the basics</a>'),
+]
+
+for section in sections:
+ sidebar_content.append(('', '<h3 class="guide-sidebar-heading">{}</h3>'.format(section.name)))
+ for item in section.items:
+ path = '{}/{}/{}'.format(INPUT_DIR, section.path, item)
+ file = open(path)
+ first_line = file.readline().strip()
+ file.close()
+ assert first_line.startswith(TITLE_PREFIX), 'file {} doesn\'t start with title prefix {}'.format(path, TITLE_PREFIX)
+ title = first_line[len(TITLE_PREFIX):].strip()
+ assert '"' not in path, 'path {} should not contain "'.format(path)
+ url = quote('{}/{}'.format(section.path, item))
+ sidebar_content.append((section.path + '/' + item, '<a href="<ROOT>{}" class="guide-sidebar-item guide-sidebar-item-indented">{}</a>'.format(url, html.escape(title))))
+
+def process_file(path):
+ count = path.count('/')
+ if count == 0:
+ guide_root = ''
+ elif count == 1:
+ guide_root = '../'
+ else:
+ assert False, 'whats goin on with ' + path
+ lines = readlines(INPUT_DIR + '/' + path)
+ assert lines[0].startswith(TITLE_PREFIX)
+ title = lines[0][len(TITLE_PREFIX):].strip()
+ contents = ''.join(lines[1:])
+ sidebar = []
+ for (p, item) in sidebar_content:
+ if p == path:
+ item = item.replace('class="', 'class="guide-sidebar-item-active ')
+ item = item.replace('<ROOT>', guide_root)
+ sidebar.append(item.replace('<ROOT>', guide_root))
+ output = '''<!DOCTYPE html>
+<!-- This file was auto-generated by make.py. DO NOT EDIT IT DIRECTLY. -->
+<html>
+<head>
+ <title>pugl - {title}</title>
+ <meta charset="utf-8">
+ <meta content="width=device-width,initial-scale=1" name="viewport">
+ <link rel="icon" href="{root}../favicon.ico">
+ <link rel="stylesheet" href="{root}../style.css">
+</head>
+<body id="guide-body">
+<div id="guide-sidebar">
+{sidebar}
+</div>
+<div id="guide-contents">
+{contents}
+</div>
+</body>
+</html>'''.format(title=title, sidebar=''.join(sidebar), contents=contents, root=guide_root)
+ f = open(OUTPUT_DIR + '/' + path, 'w')
+ f.write(output)
+ f.close()
+
+process_file('index.html')
+for section in sections:
+ for item in section.items:
+ process_file('{}/{}'.format(section.path, item))
diff --git a/guide-src/outline.txt b/guide-src/outline.txt
new file mode 100644
index 0000000..d59b039
--- /dev/null
+++ b/guide-src/outline.txt
@@ -0,0 +1,7 @@
+widget-inputs: Widget inputs
+/constants.html
+/builtins.html
+/vectors.html
+development: Development
+/index.html
+/js-features.html
diff --git a/guide-src/output-multiply-add.png b/guide-src/output-multiply-add.png
new file mode 100644
index 0000000..6bcb4f6
--- /dev/null
+++ b/guide-src/output-multiply-add.png
Binary files differ
diff --git a/guide-src/output-multiply-vector.png b/guide-src/output-multiply-vector.png
new file mode 100644
index 0000000..f1c2da1
--- /dev/null
+++ b/guide-src/output-multiply-vector.png
Binary files differ
diff --git a/guide-src/output-multiply.png b/guide-src/output-multiply.png
new file mode 100644
index 0000000..3fb3fe6
--- /dev/null
+++ b/guide-src/output-multiply.png
Binary files differ
diff --git a/guide-src/widget-inputs/builtins.html b/guide-src/widget-inputs/builtins.html
new file mode 100644
index 0000000..6434921
--- /dev/null
+++ b/guide-src/widget-inputs/builtins.html
@@ -0,0 +1,3 @@
+--- Built-in values
+
+<h1 style="color:red">TODO</h1>
diff --git a/guide-src/widget-inputs/constants.html b/guide-src/widget-inputs/constants.html
new file mode 100644
index 0000000..a2a89ac
--- /dev/null
+++ b/guide-src/widget-inputs/constants.html
@@ -0,0 +1,3 @@
+--- Constants
+
+<h1 style="color:red">TODO</h1>
diff --git a/guide-src/widget-inputs/vectors.html b/guide-src/widget-inputs/vectors.html
new file mode 100644
index 0000000..33bbea1
--- /dev/null
+++ b/guide-src/widget-inputs/vectors.html
@@ -0,0 +1,3 @@
+--- Vectors
+
+<h1 style="color:red">TODO</h1>
diff --git a/guide/index.html b/guide/index.html
deleted file mode 100644
index 643a12f..0000000
--- a/guide/index.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
- <title>pugl guide</title>
- <meta charset="utf-8">
- <meta content="width=device-width,initial-scale=1" name="viewport">
- <link rel="icon" href="../favicon.ico">
- <link rel="stylesheet" href="../style.css">
-</head>
-
-<body>
-<div id="page">
- <h2>guide</h2>
- <p>
- Lorem ipsum dolor sit amet
- </p>
-</div>
-
-</body>
-</html>
diff --git a/pugl.js b/pugl.js
index f1744dd..d10c00d 100644
--- a/pugl.js
+++ b/pugl.js
@@ -140,6 +140,32 @@ ${type} wtadd(${type} a, float aw, ${type} b, float bw) {
`,
).join('\n'),
`
+//! .name: Add
+//! .category: math
+//! .description: add two numbers or vectors
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} add(${type} a, ${type} b) {
+ return a + b;
+}
+`,
+ ).join('\n'),
+ `
+//! .name: Subtract
+//! .category: math
+//! .description: subtract one number or vector from another
+
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} sub(${type} a, ${type} b) {
+ return a - b;
+}
+`,
+ ).join('\n'),
+ `
//! .name: Multiply
//! .category: math
//! .description: multiply two numbers, scale a vector by a number, or perform component-wise multiplication between vectors
@@ -152,6 +178,18 @@ ${type} mul(${type} a, ${type} b) {
`,
).join('\n'),
`
+//! .name: Divide
+//! .category: math
+//! .description: divide one number or vector by another
+` +
+ GLSL_FLOAT_TYPES.map(
+ (type) => `
+${type} div(${type} a, ${type} b) {
+ return a / b;
+}
+`,
+ ).join('\n'),
+ `
//! .name: Power
//! .category: math
//! .id: pow
@@ -915,8 +953,8 @@ float worley(vec3 p, vec3 freq) {
` +
GLSL_FLOAT_TYPES.map(
(type) => `
-${type} _min(${type} x, ${type} y) {
- return min(x, y);
+${type} _min(${type} a, ${type} b) {
+ return min(a, b);
}`,
).join('\n'),
`
@@ -927,8 +965,8 @@ ${type} _min(${type} x, ${type} y) {
` +
GLSL_FLOAT_TYPES.map(
(type) => `
-${type} _max(${type} x, ${type} y) {
- return max(x, y);
+${type} _max(${type} a, ${type} b) {
+ return max(a, b);
}`,
).join('\n'),
];
diff --git a/style.css b/style.css
index 6d21621..4bcd692 100644
--- a/style.css
+++ b/style.css
@@ -246,6 +246,46 @@ input[type='number'] {
.ui-section label {
margin: auto;
}
+
+#guide-body {
+ display: flex;
+ margin: 0;
+}
+
+#guide-sidebar {
+ flex: 1;
+ border-right: 2px solid white;
+ height: 100vh;
+ position: sticky;
+ background: #333;
+}
+
+#guide-contents {
+ flex: 4;
+ padding: 4px;
+}
+
+.guide-sidebar-item,
+.guide-sidebar-heading {
+ border-bottom: 1px solid #fff2;
+ padding: 4px;
+ text-decoration: none;
+ display: block;
+ margin: 0;
+}
+
+.guide-sidebar-item:hover {
+ background: #8fc3;
+}
+
+.guide-sidebar-item-indented {
+ padding-left: 20%;
+}
+
+.guide-sidebar-item-active {
+ font-weight: bold;
+}
+
.inline-block {
display: inline-block;
}