diff options
author | pommicket <pommicket@gmail.com> | 2023-08-28 11:50:57 -0400 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2023-08-28 11:50:57 -0400 |
commit | f4cc8ce7a8712e2e840b0c120a3f86eadb665626 (patch) | |
tree | 36f5ee546dce6395006decc50418ccf7505f4237 | |
parent | f790b4e1baa5dfe1296cf0887011583bee7afca8 (diff) |
add, sub, div, more work on the guide
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | README.md | 31 | ||||
-rw-r--r-- | guide-src/development/index.html | 27 | ||||
-rw-r--r-- | guide-src/development/js-features.html | 22 | ||||
-rw-r--r-- | guide-src/ex-multiply-add.png | bin | 0 -> 6404 bytes | |||
-rw-r--r-- | guide-src/ex-multiply-vector.png | bin | 0 -> 3176 bytes | |||
-rw-r--r-- | guide-src/ex-multiply.png | bin | 0 -> 3410 bytes | |||
-rw-r--r-- | guide-src/ex-posx.png | bin | 0 -> 2804 bytes | |||
-rw-r--r-- | guide-src/ex-vector.png | bin | 0 -> 2609 bytes | |||
-rw-r--r-- | guide-src/index.html | 69 | ||||
-rw-r--r-- | guide-src/make.py | 108 | ||||
-rw-r--r-- | guide-src/outline.txt | 7 | ||||
-rw-r--r-- | guide-src/output-multiply-add.png | bin | 0 -> 1203 bytes | |||
-rw-r--r-- | guide-src/output-multiply-vector.png | bin | 0 -> 1124 bytes | |||
-rw-r--r-- | guide-src/output-multiply.png | bin | 0 -> 1059 bytes | |||
-rw-r--r-- | guide-src/widget-inputs/builtins.html | 3 | ||||
-rw-r--r-- | guide-src/widget-inputs/constants.html | 3 | ||||
-rw-r--r-- | guide-src/widget-inputs/vectors.html | 3 | ||||
-rw-r--r-- | guide/index.html | 21 | ||||
-rw-r--r-- | pugl.js | 46 | ||||
-rw-r--r-- | style.css | 40 |
22 files changed, 328 insertions, 55 deletions
@@ -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 @@ -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 & 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 & 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. >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 Binary files differnew file mode 100644 index 0000000..1b826ad --- /dev/null +++ b/guide-src/ex-multiply-add.png diff --git a/guide-src/ex-multiply-vector.png b/guide-src/ex-multiply-vector.png Binary files differnew file mode 100644 index 0000000..e25ea1d --- /dev/null +++ b/guide-src/ex-multiply-vector.png diff --git a/guide-src/ex-multiply.png b/guide-src/ex-multiply.png Binary files differnew file mode 100644 index 0000000..1f3260d --- /dev/null +++ b/guide-src/ex-multiply.png diff --git a/guide-src/ex-posx.png b/guide-src/ex-posx.png Binary files differnew file mode 100644 index 0000000..52c4375 --- /dev/null +++ b/guide-src/ex-posx.png diff --git a/guide-src/ex-vector.png b/guide-src/ex-vector.png Binary files differnew file mode 100644 index 0000000..681c6fe --- /dev/null +++ b/guide-src/ex-vector.png 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>), +& 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 Binary files differnew file mode 100644 index 0000000..6bcb4f6 --- /dev/null +++ b/guide-src/output-multiply-add.png diff --git a/guide-src/output-multiply-vector.png b/guide-src/output-multiply-vector.png Binary files differnew file mode 100644 index 0000000..f1c2da1 --- /dev/null +++ b/guide-src/output-multiply-vector.png diff --git a/guide-src/output-multiply.png b/guide-src/output-multiply.png Binary files differnew file mode 100644 index 0000000..3fb3fe6 --- /dev/null +++ b/guide-src/output-multiply.png 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> @@ -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'), ]; @@ -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; } |