Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port work from 'dev' to master #32

Merged
merged 10 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions docs/shaders.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
MathBox offloads most of its computations onto the GPU. As it assembles shaders on the fly, you can easily insert your own pieces of shader code. This is either as part of the usual vertex/fragment shader, or as a (re)sampler, which processes pure data, whether it's values, colors, sprites, weights, and so on.

The `<shader>` node lets you add a GLSL shader you have written into Mathbox. The specific form of the shader will depend on the operator that uses the shader (`<resample>`, `<retext>`, `<mask>`, `<vertex>` or `<fragment>`). By default, they will link up with a preceding `<shader>`, but you can select any shader node using the `shader` prop.

The shader snippet it references will look something like this:

<script type="application/glsl" id="map-temporal-blur">
Expand Down Expand Up @@ -45,7 +45,13 @@ For example, for a `.shader({ code: "#multi-shader", sources: ["#array1", "#arra
}
</script>

This samples both arrays and combines it with the third (implied) source. The order of the function definitions is matched with the array, their names are ignored. Note that external sources always have the signature `vec4 function(vec4)`, unlike implied sources, which depend on use (see below).
This samples both arrays and combines it with the third (implied) source. The
order of the function definitions is matched with the array, their names are
ignored.

The callback signature depends on both indices and channels, mapping to
float/vec2/vec3/vec4. Indices specifies the type of the argument, channels the
return type. The example above is the default `{indices: 4, channels: 4}`:

## Resample

Expand All @@ -58,15 +64,15 @@ The callback signature depends on both indices and channels, mapping to float/ve
uniform vec3 dataSize; // dimensions
uniform vec3 targetResolution; //
uniform vec3 targetSize; //

vec4 getSample(vec3 xyz); // indices 3, channels 4
vec4 getFramesSample(vec3 xyz) { //
return getSample(xyz); //
}
</script>

Used e.g. as

mathbox
.matrix({ ... })
.shader({
Expand Down Expand Up @@ -103,7 +109,7 @@ Now you can take your array of source data, `#colors`, and retext your strings t
<script type="application/glsl" id="retext-shader">
vec4 getColorSample(vec4 xyzw);
vec4 getTextSample(vec4 xyzw);

vec4 resample(vec4 xyzw) {
vec4 rgba = getColorSample(xyzw);
float i = floor(rgba.r * 255.0 + .5);
Expand Down Expand Up @@ -191,7 +197,7 @@ Fragment is a raw fragment shader stage (per pixel/sample). It takes a color (rg
.fragment()
// Fragment shaded shapes
.end()

* Colors outside the range 0...1 may be used in a floating point render-to-texture.
* Set `.fragment({ gamma: false })` to operate directly in linear RGB rather than sRGB.
* Applying a fragment shader will disable the built-in shader for surfaces.
Expand All @@ -204,4 +210,3 @@ Fragment is a raw fragment shader stage (per pixel/sample). It takes a color (rg
* `vec4( v.yx, 0.5, 1.0 )` is shorthand for `vec4( v.y, v.x, 0.5, 1.0 )`
* `vec3( 7.0 )` is shorthand for `vec3( 7.0, 7.0, 7.0 )`
* Your shader does not need to call `getSample()` if it can compute its results just from the coordinates passed in to it.

109 changes: 109 additions & 0 deletions examples/math/exponential.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>MathBox - Complex Exponential</title>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"
></script>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"
></script>
<!--
- a minified version mathbox.min.js is also available;
- recommend using a specific version (not @latest) in public sites
-->
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/mathbox@latest/build/bundle/mathbox.js"
></script>
<script src="https://cdn.jsdelivr.net/npm/dat.gui@latest/build/dat.gui.min.js"></script>
<link rel="stylesheet" href="../../build/mathbox.css" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1" />
</head>
<body>
<script>
var blue = 0x3090ff;
var white = 0xffffff;

var props = {
projectionAngle: 90,
};
var gui = new dat.GUI();
gui.add(props, "projectionAngle").min(0).max(360).step(0.5);

var mathbox = MathBox.mathBox({
plugins: ["core", "controls", "cursor"],
controls: {
klass: THREE.OrbitControls,
},
});

mathbox.three.camera.position.set(3, 2, 5);
mathbox.three.renderer.setClearColor(new THREE.Color(0xffffff), 1.0);

var view = mathbox
.set({
scale: 500,
})
.cartesian()
.transform4(
{},
{
matrix: function () {
var a = (props.projectionAngle * MathBox.τ) / 360;
return [
1,
0,
0,
Math.cos(a),
0,
1,
0,
0,
0,
0,
1,
Math.sin(a),
0,
0,
0,
1,
];
},
}
);

view
.area({
rangeX: [-3, 1],
rangeY: [-2 * MathBox.π, 2 * MathBox.π],
width: 129,
height: 65,
expr: function (emit, x, y, i, j) {
var r = Math.exp(x);

emit(Math.cos(y) * r, Math.sin(y) * r, x, y);
},
channels: 4,
})
.surface({
color: white,
zBias: -0.25,
})
.line({
color: blue,
width: 4,
})
.transpose({
order: "yxzw",
})
.line({
color: blue,
width: 4,
});
</script>
</body>
</html>
Loading