Skip to content

[p5.strands]: order of modifications changes between strands and outputted GLSL #7909

Open
@davepagurek

Description

@davepagurek

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
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

p5.js version

2.0.3

Web browser and version

Firefox

Operating system

MacOS

Steps to reproduce this

I was writing a strands shader that modifies position and also texture coordinates, and uses the position to modify the texture coordinate:

textureMaterial = baseMaterialShader().modify(() => {
  const t = uniformFloat(() => millis());
  getWorldInputs((inputs) => {
    let size = [600, 400];
    inputs.texCoord = inputs.position.xy / size + 0.5;
    inputs.position.y += 50 * sin(t * 0.001 + inputs.position.x * 0.01);
    return inputs;
  });
});

Importantly, I modify the position after using it to modify the texture coordinate. I expect the texture to stretch a lot as because the texture coordinates stay the same while the positions they're attached to move. However, the texture remains largely stable in the end result: https://editor.p5js.org/davepagurek/sketches/jCo1EFc07

When I call .inspectHooks(), I can see that the GLSL looks like this:

Vertex getWorldInputs(Vertex inputs) {
  vec3 temp_0 = inputs.position;
  temp_0 = vec3(temp_0.x, temp_0.y + (50.0000 * sin((t * 0.0010) + (temp_0.x * 0.0100))), temp_0.z);
  vec2 temp_3 = vec2(temp_0.x, temp_0.y);
  vec2 temp_4 = vec2(600.0000, 400.0000);
  vec2 temp_2 = temp_3 / temp_4;
  vec2 temp_1 = temp_2 + 0.5000;

  Vertex finalReturnValue;
  finalReturnValue.position = temp_0;
  finalReturnValue.normal = inputs.normal;
  finalReturnValue.texCoord = temp_1;
  finalReturnValue.color = inputs.color;
  return finalReturnValue;
} 

Here we can see that it created the modified position (temp0) before using it as an input to the texture coordinates in temp_3.

If I don't assign to a single component of the vector, it works as expected:

textureMaterial = baseMaterialShader().modify(() => {
  const t = uniformFloat(() => millis());
  getWorldInputs((inputs) => {
    let size = [600, 400];
    inputs.texCoord = inputs.position.xy / size + 0.5;
    inputs.position = [
      inputs.position.x,
      inputs.position.y + 50 * sin(t * 0.001 + inputs.position.x * 0.01),
      inputs.position.z
    ];
    return inputs;
  });
});
Vertex getWorldInputs(Vertex inputs) {
  vec2 temp_2 = vec2(inputs.position.x, inputs.position.y);
  vec2 temp_3 = vec2(600.0000, 400.0000);
  vec2 temp_1 = temp_2 / temp_3;
  vec2 temp_0 = temp_1 + 0.5000;

  Vertex finalReturnValue;
  finalReturnValue.position = vec3(inputs.position.x, inputs.position.y + (50.0000 * sin((t * 0.0010) + (inputs.position.x * 0.0100))), inputs.position.z);
  finalReturnValue.normal = inputs.normal;
  finalReturnValue.texCoord = temp_0;
  finalReturnValue.color = inputs.color;
  return finalReturnValue;
}

I think the issue with assigning to a component is that it currently modifies the original node that ComponentNodes reference:

set(newValue) {
this.componentsChanged = true;
if (isUnaryExpressionNode(this)) {
this.node.value = newValue;
} else {
value = newValue;
}
}
})

Instead, we might need to make setting a component replace the whole original node so that references to components from before the modification stay unchanged, and new references after the modification have access to a different, changed value.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions