| title | Tutorial tips and gotchas | |||
|---|---|---|---|---|
| description | A few collected tips for writing tutorials on the p5.js website | |||
| category | 2.0 | |||
| categoryIndex | 0 | |||
| featuredImage | ../images/featured/intro-to-p5-strands.png | |||
| featuredImageAlt | An abstract, cosmic scene with particles | |||
| relatedContent |
|
|||
| authors |
|
export const fourTicks="````";
import EditableSketch from "../../../components/EditableSketch/index.astro"; import { Code } from 'astro:components';
Experimentally it looks like the markdown converter is immediately eating two leading spaces from every line of a code span.
Input:
```jsx
<EditableSketch code={`
function setup(){
//two spaces start this line
//four spaces start this line
//six spaces start this line
}
`} />
```
Output:
function setup(){
//two spaces start this line
//four spaces start this line
//six spaces start this line
}Note, in the above output, two leading spaces have been eaten from every line that has them.
So far, the best solution to this is to add two intentionally sacrificial spaces at the start of each line in the code-block.
See also this PR where I did that for each EditableSketch (where the code is parsed with single-backticks (code)) processing/p5.js-website#1170
Here's a little change that can be made to <EditableSketch/> to show what's being sent through to that component. Essentially, we just echo the props.code into a `
element:Edit
src/components/EditableSketch/index.astro:<> <pre style="border:1px solid red; padding: 0px;">{props.code}</pre> <!-- <CodeEmbed {...removedStuff} /> --> </><EditableSketch code={ `let myShader;
function indentationExample() { four(); four(); three(); two(); }
function setup() { four(200, 200, WEBGL); eight(1); }
function draw() { two(); four(); eight(); twelve(); } `} />
<EditableSketch code={` let myShader;
function thisLineIsIndentedTwo() { four(); six(); eight(); ten(); }
function thisLineIsNotIndented() { four(200, 200, WEBGL); eight(1); }
`} />
If you want to demonstrate how to use component elements (tags), without rendering the component, put the element(s) inside of a code-fence with triple backticks, but it can't be naked, it has to be given a label, like jsx, after the opening three backticks.
```jsx <EditableSketch code={` your code goes here `} /> ```Surround the expression with ANOTHER code fence, with four backticks! (really). We can't show that here. <Code code={["
", "```jsx", " //your code here", "```", "" ].join("\n")} lang={"mdx"}/>When you write
<EditableCode code={` your code goes here `} />
<code></code>CodeContainer CodeContainerWithCopy CodeBlockWrapper
<iframe/>CodeFrame SketchEmbed CodeEmbed EditableSketchDefined in
src/components/CodeContainer/index.astroUses html<code></code>Defined in
src/CodeContainer/CodeContainerWithCopy.astroUses CodeContainer (and CodeCopyButton)Defined in
src/components/CodeBlockWrapper/index.astroUses CodeContainerWithCopyDefined in
src/components/CodeEmbed/index.jsxDescribe: Runs your code, allows editing, re-running Defined in
src/components/EditableSketch/index.astroUses CodeEmbedDefined in
src/components/SketchEmbed/index.astroUses CodeFrame
Defined in
src/components/CodeEmbed/frame.tsxUses html <iframe/>Defined in
src/components/AnnotatedCode/index.astroHere's an example of its use, from the intro to GLSL tutorial:
src/content/tutorials/en/intro-to-glsl.mdx### Vertex Shaders Here's a simple vertex shader that applies the transformations and camera perspective supplied by p5.js: <AnnotatedCode lang="glsl" code={({ begin, end }) => `${begin('precision')} precision highp float; ${end('precision')} ${begin('attributes')} attribute vec3 aPosition; ${end('attributes')} ${begin('uniforms')} // The transform of the object being drawn uniform mat4 uModelViewMatrix; // Transforms 3D coordinates to // 2D screen coordinates uniform mat4 uProjectionMatrix; ${end('uniforms')} ${begin('main')} void main() { // Apply the camera transform vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); // Tell WebGL where the vertex goes gl_Position = uProjectionMatrix * viewModelPosition; } ${end('main')}`}> <Fragment slot="precision"> The shader starts with a `precision` line. It can either be `lowp`, `mediump`, or `highp`. Using the highest quality is a good place to start to ensure your shaders look the same everywhere. On desktops and laptops, your GPU will likely use the highest quality regardless of what you write. On phones, using a lower quality might be faster, but it may make your shaders render differently. </Fragment> <Fragment slot="attributes"> The *attributes* of the shader contain values that change per vertex, which p5.js uses to share information like the position of each vertex. The attribute in this shader is a `vec3`, meaning it contains a value for x, y, and z. Attributes are special variable types that are only used in the vertex shader and are typically provided by p5.js. When you use p5.js methods like `rect()` or `vertex()`, p5.js passes the vertex information to the shader for you automatically. </Fragment> <Fragment slot="uniforms"> The *uniforms* of a shader are values that are constants for the whole shape being drawn. Each one in this shader happens to be a `mat4`, which is a type often used to represent transformations like translations, scales, and rotations. Multiplying a point by a `mat4` applies the transformation it represents to the point. The ones in this shader get provided automatically by p5.js, but we'll see later how you can provide your own custom uniforms. Note that the order of multiplication with matrices matters. In most cases you will write the matrix first and the value being multiplied by it second. </Fragment> <Fragment slot="main"> All vertex shaders require a function, `main()`, within which we position our vertices by assigning a value to `gl_Position`. This value is in *clip space*, where x, y, and z values go from -1 to 1 as they go from one side to the other. Multiplying a 3D point by `uProjectionMatrix` does this conversion for us using p5.js's camera settings. Before we do that, this shader also multiplies by `uModelViewMatrix` to apply the accumulated transformations that were set before drawing the shape. </Fragment> </AnnotatedCode>Some existing tutorials have non-breaking space unicode characters at the start of the lines (U+00a0). These may show up as outlined rectangles in your editor. It's not clear why these have been used - possibly because they've been initially authored in google docs.
It is fine - good - to replace them with whitespace but check the indentation is correct in their final in-browser render as the markdown parser does eat the first two whitespace characters from each line of certain types of code block. See elsewhere in this document.