Skip to content

Commit

Permalink
Allow hooks to use split model and view matrices
Browse files Browse the repository at this point in the history
  • Loading branch information
davepagurek committed Dec 18, 2024
1 parent 3ebde70 commit 631a14d
Show file tree
Hide file tree
Showing 39 changed files with 503 additions and 154 deletions.
2 changes: 1 addition & 1 deletion src/accessibility/outputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ function outputs(p5, fn){
fn._getPos = function (x, y) {
const untransformedPosition = new DOMPointReadOnly(x, y);
const currentTransform = this._renderer.isP3D ?
new DOMMatrix(this._renderer.states.uMVMatrix.mat4) :
new DOMMatrix(this._renderer.calculateCombinedMatrix()) :
this.drawingContext.getTransform();
const { x: transformedX, y: transformedY } = untransformedPosition
.matrixTransform(currentTransform);
Expand Down
4 changes: 2 additions & 2 deletions src/webgl/GeometryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class GeometryBuilder {
if (!this.hasTransform) return normals;

return normals.map(
v => this.renderer.states.uNMatrix.multiplyVec(v) // this is a vec3
v => this.renderer.scratchMat3.multiplyVec(v) // this is a vec3
);
}

Expand All @@ -51,7 +51,7 @@ class GeometryBuilder {
.every((v, i) => v === this.identityMatrix.mat4[i]);

if (this.hasTransform) {
this.renderer.states.uNMatrix.inverseTranspose4x4(this.renderer.states.uModelMatrix);
this.renderer.scratchMat3.inverseTranspose4x4(this.renderer.states.uModelMatrix);
}

let startIdx = this.geometry.vertices.length;
Expand Down
263 changes: 188 additions & 75 deletions src/webgl/material.js
Original file line number Diff line number Diff line change
Expand Up @@ -1471,19 +1471,86 @@ function material(p5, fn){
* You can call <a href="#/p5.Shader/modify">`baseNormalShader().modify()`</a>
* and change any of the following hooks:
*
* Hook | Description
* -----|------------
* `void beforeVertex` | Called at the start of the vertex shader.
* `vec3 getLocalPosition` | Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version.
* `vec3 getWorldPosition` | Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version.
* `vec3 getLocalNormal` | Update the normal before transforms are applied. It takes in `vec3 normal` and must return a modified version.
* `vec3 getWorldNormal` | Update the normal after transforms are applied. It takes in `vec3 normal` and must return a modified version.
* `vec2 getUV` | Update the texture coordinates. It takes in `vec2 uv` and must return a modified version.
* `vec4 getVertexColor` | Update the color of each vertex. It takes in a `vec4 color` and must return a modified version.
* `void afterVertex` | Called at the end of the vertex shader.
* `void beforeFragment` | Called at the start of the fragment shader.
* `vec4 getFinalColor` | Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
* `void afterFragment` | Called at the end of the fragment shader.
* <table>
* <tr><th>Hook</th><th>Description</th></tr>
* <tr><td>
*
* `void beforeVertex`
*
* </td><td>
*
* Called at the start of the vertex shader.
*
* </td></tr>
* <tr><td>
*
* `Vertex getObjectInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn before any positioning has been applied. It takes in a `Vertex` struct, which includes:
* - `vec3 position`, the position of the vertex
* - `vec3 normal`, the direction facing out of the surface
* - `vec2 uv`, the texture coordinates associeted with the vertex
* - `vec4 color`, the per-vertex color
* The struct can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `Vertex getWorldInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `Vertex getCameraInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `void afterVertex`
*
* </td><td>
*
* Called at the end of the vertex shader.
*
* </td></tr>
* <tr><td>
*
* `void beforeFragment`
*
* </td><td>
*
* Called at the start of the fragment shader.
*
* </td></tr>
* <tr><td>
*
* `vec4 getFinalColor`
*
* </td><td>
*
* Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
*
* </td></tr>
* <tr><td>
*
* `void afterFragment`
*
* </td><td>
*
* Called at the end of the fragment shader.
*
* </td></tr>
* </table>
*
* Most of the time, you will need to write your hooks in GLSL ES version 300. If you
* are using WebGL 1 instead of 2, write your hooks in GLSL ES 100 instead.
Expand All @@ -1506,9 +1573,10 @@ function material(p5, fn){
* uniforms: {
* 'float time': () => millis()
* },
* 'vec3 getWorldPosition': `(vec3 pos) {
* pos.y += 20. * sin(time * 0.001 + pos.x * 0.05);
* return pos;
* 'Vertex getWorldInputs': `(Vertex inputs) {
* inputs.position.y +=
* 20. * sin(time * 0.001 + inputs.position.x * 0.05);
* return inputs;
* }`
* });
* }
Expand All @@ -1530,7 +1598,10 @@ function material(p5, fn){
* function setup() {
* createCanvas(200, 200, WEBGL);
* myShader = baseNormalShader().modify({
* 'vec3 getWorldNormal': '(vec3 normal) { return abs(normal); }',
* 'Vertex getCameraInputs': `(Vertex inputs) {
* inputs.normal = abs(inputs.normal);
* return inputs;
* }`,
* 'vec4 getFinalColor': `(vec4 color) {
* // Map the r, g, and b values of the old normal to new colors
* // instead of just red, green, and blue:
Expand Down Expand Up @@ -1566,19 +1637,86 @@ function material(p5, fn){
* You can call <a href="#/p5.Shader/modify">`baseColorShader().modify()`</a>
* and change any of the following hooks:
*
* Hook | Description
* -------|-------------
* `void beforeVertex` | Called at the start of the vertex shader.
* `vec3 getLocalPosition` | Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version.
* `vec3 getWorldPosition` | Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version.
* `vec3 getLocalNormal` | Update the normal before transforms are applied. It takes in `vec3 normal` and must return a modified version.
* `vec3 getWorldNormal` | Update the normal after transforms are applied. It takes in `vec3 normal` and must return a modified version.
* `vec2 getUV` | Update the texture coordinates. It takes in `vec2 uv` and must return a modified version.
* `vec4 getVertexColor` | Update the color of each vertex. It takes in a `vec4 color` and must return a modified version.
* `void afterVertex` | Called at the end of the vertex shader.
* `void beforeFragment` | Called at the start of the fragment shader.
* `vec4 getFinalColor` | Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
* `void afterFragment` | Called at the end of the fragment shader.
* <table>
* <tr><th>Hook</th><th>Description</th></tr>
* <tr><td>
*
* `void beforeVertex`
*
* </td><td>
*
* Called at the start of the vertex shader.
*
* </td></tr>
* <tr><td>
*
* `Vertex getObjectInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn before any positioning has been applied. It takes in a `Vertex` struct, which includes:
* - `vec3 position`, the position of the vertex
* - `vec3 normal`, the direction facing out of the surface
* - `vec2 uv`, the texture coordinates associeted with the vertex
* - `vec4 color`, the per-vertex color
* The struct can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `Vertex getWorldInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `Vertex getCameraInputs`
*
* </td><td>
*
* Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `Vertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `void afterVertex`
*
* </td><td>
*
* Called at the end of the vertex shader.
*
* </td></tr>
* <tr><td>
*
* `void beforeFragment`
*
* </td><td>
*
* Called at the start of the fragment shader.
*
* </td></tr>
* <tr><td>
*
* `vec4 getFinalColor`
*
* </td><td>
*
* Update the final color after mixing. It takes in a `vec4 color` and must return a modified version.
*
* </td></tr>
* <tr><td>
*
* `void afterFragment`
*
* </td><td>
*
* Called at the end of the fragment shader.
*
* </td></tr>
* </table>
*
* Most of the time, you will need to write your hooks in GLSL ES version 300. If you
* are using WebGL 1 instead of 2, write your hooks in GLSL ES 100 instead.
Expand All @@ -1601,9 +1739,10 @@ function material(p5, fn){
* uniforms: {
* 'float time': () => millis()
* },
* 'vec3 getWorldPosition': `(vec3 pos) {
* pos.y += 20. * sin(time * 0.001 + pos.x * 0.05);
* return pos;
* 'Vertex getWorldInputs': `(Inputs inputs) {
* inputs.position.y +=
* 20. * sin(time * 0.001 + inputs.position.x * 0.05);
* return inputs;
* }`
* });
* }
Expand Down Expand Up @@ -1642,56 +1781,35 @@ function material(p5, fn){
* </td></tr>
* <tr><td>
*
* `vec3 getLocalPosition`
*
* </td><td>
*
* Update the position of vertices before transforms are applied. It takes in `vec3 position` and must return a modified version.
*
* </td></tr>
* <tr><td>
*
* `vec3 getWorldPosition`
*
* </td><td>
*
* Update the position of vertices after transforms are applied. It takes in `vec3 position` and pust return a modified version.
*
* </td></tr>
* <tr><td>
*
* `float getStrokeWeight`
*
* </td><td>
*
* Update the stroke weight. It takes in `float weight` and pust return a modified version.
*
* </td></tr>
* <tr><td>
*
* `vec2 getLineCenter`
* `StrokeVertex getObjectInputs`
*
* </td><td>
*
* Update the center of the line. It takes in `vec2 center` and must return a modified version.
* Update the vertex data of the stroke being drawn before any positioning has been applied. It takes in a `StrokeVertex` struct, which includes:
* - `vec3 position`, the position of the vertex
* - `vec3 tangentIn`, the tangent coming in to the vertex
* - `vec3 tangentOut`, the tangent coming out of the vertex. In straight segments, this will be the same as `tangentIn`. In joins, it will be different. In caps, one of the tangents will be 0.
* - `vec4 color`, the per-vertex color
* - `float weight`, the stroke weight
* The struct can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `vec2 getLinePosition`
* `StrokeVertex getWorldInputs`
*
* </td><td>
*
* Update the position of each vertex on the edge of the line. It takes in `vec2 position` and must return a modified version.
* Update the vertex data of the model being drawn after transformations such as `translate()` and `scale()` have been applied, but before the camera has been applied. It takes in a `StrokeVertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
*
* `vec4 getVertexColor`
* `StrokeVertex getCameraInputs`
*
* </td><td>
*
* Update the color of each vertex. It takes in a `vec4 color` and must return a modified version.
* Update the vertex data of the model being drawn as they appear relative to the camera. It takes in a `StrokeVertex` struct like, in the `getObjectInputs` hook above, that can be modified and returned.
*
* </td></tr>
* <tr><td>
Expand Down Expand Up @@ -1810,20 +1928,15 @@ function material(p5, fn){
* uniforms: {
* 'float time': () => millis()
* },
* declarations: 'vec3 myPosition;',
* 'vec3 getWorldPosition': `(vec3 pos) {
* myPosition = pos;
* return pos;
* }`,
* 'float getStrokeWeight': `(float w) {
* 'StrokeVertex getWorldInputs': `(StrokeVertex inputs) {
* // Add a somewhat random offset to the weight
* // that varies based on position and time
* float scale = 0.8 + 0.2*sin(10.0 * sin(
* floor(time/250.) +
* myPosition.x*0.01 +
* myPosition.y*0.01
* inputs.position.x*0.01 +
* inputs.position.y*0.01
* ));
* return w * scale;
* inputs.weight *= scale;
* }`
* });
* }
Expand Down
Loading

0 comments on commit 631a14d

Please sign in to comment.