Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/core/filterShaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,20 @@ export function makeFilterShader(renderer, operation, p5) {
const sampleCoord = uv + p5.vec2(sample, sample) / inputs.canvasSize * direction;
const weight = quadWeight(sample, (numSamples - 1.0) * 0.5 * spacing);

avg += weight * p5.getTexture(canvasContent, sampleCoord);
const texSample = p5.getTexture(canvasContent, sampleCoord);
avg += weight * texSample * p5.vec4(
texSample.a, texSample.a, texSample.a, 1
);
total += weight;
}

return avg / total;
const blended = avg / total;
return p5.vec4(
blended.r / blended.a,
blended.g / blended.a,
blended.b / blended.a,
blended.a
);
});
}, { p5 });

Expand Down
3 changes: 3 additions & 0 deletions src/core/p5.Renderer3D.js
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,9 @@ export class Renderer3D extends Renderer {
//// TEXT SUPPORT METHODS
//////////////////////////////

_beforeDrawText() {}
_afterDrawText() {}

textCanvas() {
if (!this._textCanvas) {
this._textCanvas = document.createElement('canvas');
Expand Down
4 changes: 2 additions & 2 deletions src/strands/strands_for.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ export class StrandsFor {
const scopeEndBlock = CFG.createBasicBlock(cfg, BlockType.SCOPE_END);
CFG.addEdge(cfg, updateBlock, scopeEndBlock);

// Loop back to break check
CFG.addEdge(cfg, scopeEndBlock, breakCheckBlock);
// Connect end of for loop to the merge agter the loop
CFG.addEdge(cfg, scopeEndBlock, mergeBlock);

// Break condition exits to merge
CFG.addEdge(cfg, breakCheckBlock, mergeBlock);
Expand Down
18 changes: 15 additions & 3 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,17 @@ class RendererGL extends Renderer3D {
}
}

//////////////////////////////////////////////
// Text
//////////////////////////////////////////////

_beforeDrawText() {
this.GL.pixelStorei(this.GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
}
_afterDrawText() {
this.GL.pixelStorei(this.GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
}

//////////////////////////////////////////////
// Setting
//////////////////////////////////////////////
Expand Down Expand Up @@ -413,9 +424,10 @@ class RendererGL extends Renderer3D {
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
// Make sure all images are loaded into the canvas non-premultiplied so that
// they can be handled consistently in shaders.
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
// Make sure all images are loaded into the canvas premultiplied so that
// they match the way we render colors. This will make framebuffer textures
// be encoded the same way as textures from everything else.
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
this._viewport = this.drawingContext.getParameter(
this.drawingContext.VIEWPORT
);
Expand Down
13 changes: 7 additions & 6 deletions src/webgl/shaders/light_texture.frag
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ void main(void) {
}
else {
vec4 baseColor = isTexture
// Textures come in with non-premultiplied alpha. Apply tint.
? TEXTURE(uSampler, vVertTexCoord) * (uTint/255.)
// Colors come in with non-premultiplied alpha.
: vColor;
// Convert to premultiplied alpha for consistent output
baseColor.rgb *= baseColor.a;
// Textures come in with premultiplied alpha. To apply tint and still have
// premultiplied alpha output, we need to multiply the RGB channels by the
// tint RGB, and all channels by the tint alpha.
? TEXTURE(uSampler, vVertTexCoord) * vec4(uTint.rgb/255., 1.) * (uTint.a/255.)
// Colors come in with unmultiplied alpha, so we need to multiply the RGB
// channels by alpha to convert it to premultiplied alpha.
: vec4(vColor.rgb * vColor.a, vColor.a);
OUT_COLOR = vec4(baseColor.rgb * vDiffuseColor + vSpecularColor, baseColor.a);
}
}
7 changes: 6 additions & 1 deletion src/webgl/shaders/phong.frag
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ void main(void) {
inputs.texCoord = vTexCoord;
inputs.ambientLight = uAmbientColor;
inputs.color = isTexture
? TEXTURE(uSampler, vTexCoord) * (uTint/255.)
? TEXTURE(uSampler, vTexCoord) * (vec4(uTint.rgb/255., 1.) * uTint.a/255.)
: vColor;
if (isTexture && inputs.color.a > 0.0) {
// Textures come in with premultiplied alpha. Temporarily unpremultiply it
// so hooks users don't have to think about premultiplied alpha.
inputs.color.rgb /= inputs.color.a;
}
inputs.shininess = uShininess;
inputs.metalness = uMetallic;
inputs.ambientMaterial = uHasSetAmbient ? uAmbientMatColor.rgb : inputs.color.rgb;
Expand Down
6 changes: 5 additions & 1 deletion src/webgl/shaders/webgl2Compatibility.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@ out vec4 outColor;
#endif

#ifdef FRAGMENT_SHADER
#define getTexture TEXTURE
vec4 getTexture(in sampler2D content, vec2 coord) {
vec4 color = TEXTURE(content, coord);
if (color.a > 0.) color.rgb /= color.a;
return color;
}
#endif
3 changes: 2 additions & 1 deletion src/webgl/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ function text(p5, fn) {

// this will have to do for now...
sh.setUniform('uMaterialColor', curFillColor);

this._beforeDrawText();
this.glyphDataCache = this.glyphDataCache || new Set();

try {
Expand Down Expand Up @@ -827,6 +827,7 @@ function text(p5, fn) {
this.states.setValue('strokeColor', doStroke);
this.states.setValue('drawMode', drawMode);

this._afterDrawText();
this.pop();
}
};
Expand Down
4 changes: 2 additions & 2 deletions src/webgpu/p5.RendererWebGPU.js
Original file line number Diff line number Diff line change
Expand Up @@ -1818,12 +1818,12 @@ function rendererWebGPU(p5, fn) {
}

// Find the input parameter name from the main function signature (anchored to start)
const inputMatch = postMain.match(/^\s*\((\w+):\s*\w+\)/);
const inputMatch = main.match(/fn main\s*\((\w+):\s*\w+\)/);
if (inputMatch) {
const inputVarName = inputMatch[1];
initStatements = initStatements.replace(/INPUT_VAR/g, inputVarName);
// Insert after the main function parameter but before any other code (anchored to start)
postMain = postMain.replace(/^(\s*\(\w+:\s*\w+\)\s*[^{]*\{)/, `$1\n${initStatements}`);
postMain = initStatements + postMain;
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions test/unit/webgl/p5.Shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,40 @@ suite('p5.Shader', function() {
const pixelColor = myp5.get(25, 25);
assert.approximately(pixelColor[0], 127, 5); // 0.5 * 255 ≈ 127
});

test('handle statements after for loop before return', () => {
myp5.createCanvas(50, 50, myp5.WEBGL);

const testShader = myp5.baseMaterialShader().modify(() => {
myp5.getPixelInputs(inputs => {
let avg = myp5.vec3(0.0);
let total = 0.0;

// Simulate blur-like accumulation in for loop
for (let i = 0; i < 3; i++) {
const sample = myp5.vec3(0.2, 0.1, 0.3);
const weight = 1.0;
avg += weight * sample;
total += weight;
}

const blended = avg / total;

inputs.color = [blended.x, blended.y, blended.z, 1.0];
return inputs;
});
}, { myp5 });

myp5.noStroke();
myp5.shader(testShader);
myp5.plane(myp5.width, myp5.height);

// Expected result: (3 * [0.2, 0.1, 0.3]) / 3 = [0.2, 0.1, 0.3]
const pixelColor = myp5.get(25, 25);
assert.approximately(pixelColor[0], 51, 5); // 0.2 * 255 ≈ 51
assert.approximately(pixelColor[1], 25, 5); // 0.1 * 255 ≈ 25
assert.approximately(pixelColor[2], 77, 5); // 0.3 * 255 ≈ 77
});
});

suite('passing data between shaders', () => {
Expand Down
Loading