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

setAttribute() function for defining custom shader attributes #7276

Merged
merged 98 commits into from
Oct 1, 2024

Conversation

lukeplowden
Copy link

@lukeplowden lukeplowden commented Sep 20, 2024

Resolves #5120

In response to the issue above I've added a global setAttribute() function and a method of the same name on p5.Geometry.

2024-09-20.12-35-05.mp4

Attributes are per vertex data declared at the top of the vertex shader like so:

  attribute vec3 aPosition;

Currently, p5.js has a number of predefined attributes including aPosition, aVertexColor, aNormal, etc. These changes allow the user to define custom attributes in two ways, using an API similar to Shader.setUniform().

  1. By calling the global function setAttribute(attributeName, data) which applies the custom attribute to subsequent calls to vertex(), bezierVertex(), or curveVertex(), within a beginShape()->endShape() block, i.e. on immediate mode geometry. This is the same behaviour as fill() or normal() for per-vertex data.
  setAttribute('aCustom', [1, 0, 0]);
  1. By calling the member functionGeometry.setAttribute() in case the user wants to directly interface with p5.Geometry objects, i.e. on retained mode geometry. This essentially creates an array and pushes a new value on the p5.Geometry object, which is unlike other methods on p5.Geometry.
  myGeometry.setAttribute('aCustom', [1, 0, 0]);

The parameters for both functions are the same, a string attributeName and a number or array of numbers data.

PR Checklist

  • npm run lint passes
  • [Inline documentation] is included / updated
  • [Unit tests] are included / updated

This is a draft pull request as I'm finishing off the tests and documentation right now. Would like to hear other WebGL contributor's thoughts on progress @perminder-17 @Garima3110


Edge cases

There are a few edge cases related to the need for attributes to be properly set for each vertex. If attribute vec3 aCustom; is declared and used in a shader, there should be as many values for aCustom as there are for aPosition.

Global function (immediate mode)

  1. The user may call setAttribute() after the first vertex() call. In this case vertex() zero-fills the previous values for each call which came before. It behaves like this:
function draw(){
	shader(customAttributeShader);
	beginShape();
	vertex(-1,0,0); // This has no custom attribute set, so it is [0, 0, 0]
	setAttribute('aCustom', [1,1,1]); // Attribute set for following vertices
	vertex(1,0,0); // [1, 1, 1]
	vertex(0,1,0);// [1, 1, 1]
	endShape();
}
  1. The user may not set any attributes but their shader uses them. We could either give a friendly error that the shader is using undefined attributes, or fill all values with zero explicitly, or a combination.
function draw(){
	shader(customAttributeShader);
	beginShape();
	vertex(-1,0,0); // no value set for aCustom
	vertex(1,0,0);
	vertex(0,1,0);
	endShape();
}

Retained mode

Because the Geometry.setAttribute(attributeName, data) method pushes to an array Geometry[attributeName]:

let geo;

async function setup(){
	geo = new p5.Geometry();
	let v0 = new p5.Vertex(-1,0,0);
	let v1 = new p5.Vertex(1,0,0);
	let v2 = new p5.Vertex(0,1,0);
	geo.setAttribute('aCustom', [1,0,0]); // Only one custom attribute has been set
	geo.vertices.push(v0, v1, v2); // Three vertex attributes have been set
} 

In this case we plan to just give a Friendly Error saying that one of the vertex attributes has not been properly filled.

@lukeplowden lukeplowden marked this pull request as draft September 20, 2024 12:03
@davepagurek
Copy link
Contributor

It looks like we've got some changes from the main branch in here, do we have any conflicts if we git rebase dev-2.0? If it tries to replay some of the main branch commits, maybe we can skip the main branch commits by doing an interactive rebase with git rebase -i dev-2.0 and then deleting the lines with the unrelated commits?

@lukeplowden
Copy link
Author

It looks like we've got some changes from the main branch in here, do we have any conflicts if we git rebase dev-2.0? If it tries to replay some of the main branch commits, maybe we can skip the main branch commits by doing an interactive rebase with git rebase -i dev-2.0 and then deleting the lines with the unrelated commits?

Thanks for spotting that, should be good now!

Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this, especially getting the tessellation stuff to work!

src/webgl/p5.Geometry.js Outdated Show resolved Hide resolved
src/webgl/p5.RendererGL.Immediate.js Outdated Show resolved Hide resolved
src/webgl/p5.RendererGL.Immediate.js Outdated Show resolved Hide resolved
src/webgl/p5.RendererGL.Immediate.js Outdated Show resolved Hide resolved
src/webgl/p5.RendererGL.Immediate.js Outdated Show resolved Hide resolved
@lukeplowden
Copy link
Author

A thought on naming: would it be weird to not use attribute at all, and call it something like setVertexData(name, value)? (Or maybe vertexData(...) if we want to be consistent with fill(...) and normal(...)?) Or possibly vertexProperty to be clearer that it's adding something onto the vertex rather than being an alternative way to set a vertex?

Yeah I'm also happy with those, especially as attribute is replaced with in for 300 es. However vertexAttribute() or vertexProperty() are quite similar also.

@davepagurek
Copy link
Contributor

I think this is looking good to go! @perminder-17 how do you feel about vertexProperty as a potential changed api name? if we all feel ok about that, I think we can rename it and then merge this!

@perminder-17
Copy link
Contributor

Using the name vertexProperty makes it clear that we're adding something to the vertex, not replacing or setting the vertex itself. So, I think vertexProperty is a good name.

@lukeplowden
Copy link
Author

Thanks @davepagurek and @perminder-17, I've updated the code so that everything uses 'vertexProperty()' instead!

@davepagurek davepagurek merged commit 3131111 into processing:dev-2.0 Oct 1, 2024
2 checks passed
@davepagurek
Copy link
Contributor

Thanks everyone!

@davepagurek
Copy link
Contributor

@all-contributors please add @lukeplowden for code

Copy link
Contributor

@davepagurek

I've put up a pull request to add @lukeplowden! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants