diff --git a/src/data/examples/assets/shader_defaults.frag b/src/data/examples/assets/shader_defaults.frag new file mode 100644 index 0000000000..e0c93e2cd2 --- /dev/null +++ b/src/data/examples/assets/shader_defaults.frag @@ -0,0 +1,25 @@ +/* This is a modification of a shader by Adam Ferriss + https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/6_3d/6-2_vertexDisplacement +*/ + +/* WebGL requires that the first line of the fragment shader + specify the precision. + Precision is dependent on the the device. + Sometimes you'll see bugs if you use lowp so stick to mediump or highp. +*/ +precision mediump float; + +/* Get the normal from the vertex shader. + This is the same variable we declared in the vertex shader. + We need to declare it here too! +*/ +varying vec3 vNormal; + +void main() { + + // Normalize the normal + vec3 color = vNormal * 0.5 + 0.5; + + // Assign the color to be output to the screen + gl_FragColor = vec4(color, 1.0); +} diff --git a/src/data/examples/assets/shader_defaults.vert b/src/data/examples/assets/shader_defaults.vert new file mode 100644 index 0000000000..1b5a7643e8 --- /dev/null +++ b/src/data/examples/assets/shader_defaults.vert @@ -0,0 +1,82 @@ +/* This is a modification of a shader by Adam Ferriss + https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/6_3d/6-2_vertexDisplacement +*/ + +// Get the vertex position attribute of the geometry +attribute vec3 aPosition; + +// Get the vertex normal attribute of the geometry +attribute vec3 aNormal; + +/* When we use 3d geometry, we need to also use some builtin variables + that p5 provides. + Most 3d engines will provide these variables for you. + They are 4x4 matrices that define the camera position / rotation, + and the geometry position / rotation / scale. + + There are actually 3 matrices (model, view, projection), but + two of them have already been combined into a single one (modelView). + This pre combination is an optimization trick so that the vertex + shader doesn't have to do as much work. +*/ + +/* uProjectionMatrix is used to convert the 3d world coordinates into + screen coordinates +*/ +uniform mat4 uProjectionMatrix; + +/* uModelViewMatrix is a combination of the model matrix and the + view matrix + + The model matrix defines the object position / rotation / scale. + Multiplying uModelMatrix * vec4(aPosition, 1.0) would move the + object into it's world position. + + The view matrix defines attributes about the camera, such as + focal length and camera position. + Multiplying uModelViewMatrix * vec4(aPosition, 1.0) would move the + object into its world position in front of the camera. +*/ +uniform mat4 uModelViewMatrix; + +// Get the framecount uniform +uniform float uFrameCount; + +/* This is a variable that will be shared with the fragment shader. + We will assign the attribute aNormal to the varying vNormal to + move it from the vertex shader to the fragment shader. + It can be called whatever you want, but ofter people prefix it + with 'v' to indicate that it is a varying. +*/ +varying vec3 vNormal; + +void main() { + + // Copy the position data into a vec4, using 1.0 as the w component + vec4 position = vec4(aPosition, 1.0); + + // Frequency and Amplitude will determine the look of the displacement + float frequency = 20.0; + float amplitude = 0.1; + + /* Displace the x position withe the sine of the x + time. + Multiply by the normal to move it in the correct direction. + You could add more distortions to the other axes too. + */ + float distortion = sin(position.x * frequency + uFrameCount * 0.1); + position.x += distortion * aNormal.x * amplitude; + + + // Send the normal to the fragment shader + vNormal = aNormal; + + + /* Move our vertex positions into screen space. + + The order of multiplication is always, + projection * view * model * position + In this case model and view have been combined so we just do, + projection * modelView * position + */ + gl_Position = uProjectionMatrix * uModelViewMatrix * position; +} diff --git a/src/data/examples/en/20_3D/12_default_shader_inputs.js b/src/data/examples/en/20_3D/12_default_shader_inputs.js new file mode 100644 index 0000000000..9b25bf0aea --- /dev/null +++ b/src/data/examples/en/20_3D/12_default_shader_inputs.js @@ -0,0 +1,87 @@ +/* + * @name Default Shader Inputs + * @description + *

p5.js provides some default attributes and uniforms that can be used in your shader programs. Attributes provide per vertex information that can be used in a vertex shader. Uniforms provide information that can be used in both vertex and fragment shaders. (All vertices in a vertex shader, and all pixels in a fragment shader receive the same uniform value as input.)


+ *

Attributes

+ *

+ * aPosition
+ *   ◦ Type: vec3 (x, y, z)
+ *   ◦ Description: Position associated with a vertex
+ * aTexCoord
+ *   ◦ Type: vec2 (x, y)
+ *   ◦ Description: Texture coordinates associated with a vertex
+ * aNormal
+ *   ◦ Type: vec3 (x, y, z)
+ *   ◦ Description: Normal associated with vertex
+ * aMaterialColor
+ *   ◦ Type: vec4 (r, g, b, a)
+ *   ◦ Description: Color associated with a vertex
+ * The following attribute names are reserved:
+ *   ◦ aAmbientColor
+ *


+ *

Uniforms

+ *

+ * uViewMatrix
+ *   ◦ Type: mat4 (4x4 matrix)
+ *   ◦ Description: Contains information about the current camera such as position and rotation. Used to ?
+ * uProjectionMatrix
+ *   ◦ Type: mat4 (4x4 matrix)
+ *   ◦ Description: Contains information about the current projection such as near and far clipping planes. Used to convert 3D world coordinates into 2D screen coordinates
+ * uModelViewMatrix
+ *   ◦ Type: mat4 (4x4 matrix)
+ *   ◦ Description: Combination of the model and view matrices. Used to ?
+ * uModelViewProjectionMatrix
+ *   ◦ Type: mat4 (4x4 matrix)
+ *   ◦ Description: Combination of the model, view, and projection matrices. Used to ?
+ * uNormalMatrix
+ *   ◦ Type: mat3 (3x3 matrix)
+ *   ◦ Description: Transpose inverse of the model matrix. Typically used in lighting calculations
+ * The following uniform names are reserved:
+ *   ◦ uStrokeWeight
+ *


+ *

To learn more about using shaders in p5.js see p5.js Shaders


+ */ + +// This variable will hold our shader object +let shaderProgram; + +function preload() { + /* A shader is composed of two parts, a vertex shader, and a + fragment shader. + The vertex shader prepares the vertices and geometry to be drawn. + The fragment shader renders the actual pixel colors. + + loadShader() is asynchronous so it needs to be in preload. + loadShader() first takes as input the filename of a vertex shader, + and a fragment shader. + These file types are usually .vert and .frag, but you can actually + use anything. .glsl is another common one + */ + shaderProgram = loadShader("assets/shader_defaults.vert", "assets/shader_defaults.frag"); +} + +function setup() { + // Shaders require WEBGL mode to work + createCanvas(710, 400, WEBGL); + noStroke(); +} + +function draw() { + background(0); + + // shader() sets the active shader with our shader + shader(shaderProgram); + + // Send the frameCount to the shader + shaderProgram.setUniform("uFrameCount", frameCount); + + // Rotate our geometry on the X and Y axes + rotateX(frameCount * 0.01); + rotateY(frameCount * 0.005); + + // Draw some geometry to the screen + /* We're going to tessellate the sphere a bit so we have some more + vertices to work with + */ + sphere(width / 5, 200, 200); +}