Skip to content

Make the WebGL material system more easy to make libraries for #6144

Closed
@davepagurek

Description

@davepagurek

Increasing Access

There have been a number of requests related to the material system in p5, such as adding fog (#5878) or blend modes for ambient light (#6123), I've been working on a library for shader-based warping (https://github.com/davepagurek/p5.warp), and a GSoC project this year will involve working on image-based lighting as an alternative to point/directional/spot lights.

We intentionally don't add every feature into p5 core in order to keep the codebase maintainable, keep the API simple for beginners, and keep the runtime reasonably fast. It would be great to allow community libraries to fill these needs instead! However, the system is currently very difficult to add to externally; the only viable option right now is to package a p5 shader and distribute that, which means keeping your shader up-to-date with internal changes.

A dedicated way to hook into the material system would help people who are interested in contributing via a library test out their ideas, and would give users a larger variety of tools for different needs as new libraries are added.

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build Process
  • Unit Testing
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

Feature request details

The main difference between adding a material to p5 and writing a full shader is that for the former, you generally want to keep most of the existing shader. The best way to do that right now is copy-and-pasting, which goes stale over time and requires expertise of p5's internals to do in the first place. The design goal would be to allow people to replace specific parts of our shaders without needing to do that.

To narrow the scope, I think this only needs to apply to our fill material with lighting, not lines or text for now.

Some potential pieces a library might want to replace are:

Shader snippets

We can maybe think of our shaders as a collection of code snippets for both the fragment and vertex shader, which have two parts: a header (to specify inputs) and a body (which runs in main()), combined like this:

const shaderSource = `
  precision highp float;

  ${snippets.map(snippet => snippet.head).join('\n')}

  void main() {
    ${snippets.map(snippet => snippet.body).join('\n')}
  }
`;

If we break down our current shaders into snippets like that, then we could provide a minimal API for creating a new shader where one could replace just one part. Maybe something like:

const myMaterial = buildMaterial({
  vertexSnippets: [defaultPositioning],
  fragmentSnippets: [
    defaultDiffuseSpecular,
    myFogSnippet
  ]
})

Some downsides with this are the fact that it treats all snippets just as strings, so there may be naming collisions or type mismatches when making snippets work together. It would at least require relatively minimal code to implement, though.

Shader graph

There's this existing library for combining shader pieces to make one shader: https://www.npmjs.com/package/@gerhobbelt/shadergraph This does much of what the above snippet idea does, but in a much more complete but heavy way, where one can define snippets for small bits of code and build a complicated dependency graph to compile into a shader.

Using this benefits from not being built from scratch, but also adds a new dependency to p5, and means providing a more complicated API to library builders.

Providing access to default shader source

The barest-bones solution maybe just involves exposing the source code for our current material shaders via variables that libraries can reference. That way they could use our existing vertex shader but write their own fragment shader.

This doesn't solve the problem where one wants to use most of our lighting calculations (and therefore be able to integrate with point/directional/spot light calls made in p5) but would still be helpful.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    DONE! 🎉

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions