-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Make shaders define what they get used for. #7256
base: dev-2.0
Are you sure you want to change the base?
Conversation
Great job so far, Garima! The idea is that when you call Currently, methods like
check which uniforms are defined, and if any are defined, the function returns true. This allows us to apply fill shaders when One possible solution would be to remove these methods that check whether uniforms and attributes are defined. Instead, we can directly set the appropriate user shader based on the method the user calls, such as Also, we should modify the function
We could probably return the user-defined fill shader if present, or light shader if no fill is set. I guess this should work for fill shaders since |
src/webgl/p5.Shader.js
Outdated
@@ -1012,6 +1012,10 @@ p5.Shader = class Shader { | |||
return this.uniforms.uStrokeWeight !== undefined; | |||
} | |||
|
|||
isImageShader() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need this method because we don't want our imageShader(yourShader)
method to work depending on some uniforms (uImageSampler
for your case). We could probably take this one out.
this._renderer._useNormalMaterial = false; | ||
} | ||
// Always set the shader as a fill shader | ||
this._renderer.userFillShader = s; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
Thanks for the suggestions @perminder-17 ! |
src/webgl/p5.RendererGL.js
Outdated
} | ||
return fill; | ||
if (this._tex) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the OR operator here and combine it into a single if statement? Something like:
if(this._enableLighting || this._tex)
return this._getLightShader();
Can this make the code cleaner instead of using two separate if blocks?
Great work @Garima3110 so far. I tested it, and it seems to be working well. But to be double sure, I'll test it again to make sure nothing is breaking. In the meantime, you should focus on completing the documentation for the fill shader to meet the first week's target. The documentation should include: (these are just my thoughts, feel free to add your own explanations if you have any).
Also, talking about the
You can remove the method and update the function here as well: (just you did for fill shaders)
and then we can move to the docs of Let me know if I think we also need to alter some tests created for shaders, will update you for the tests as we completes the docs and code of this project. Thanks again for your work. :) |
Thanks for the follow up @perminder-17 |
I have done all changes in docs and examples for fill shaders, please have a look @perminder-17 |
Just an update, previously i mentioned the wrong block of code by mistake. I just saw when you pushed it you need to remove the isStrokeShader() code. I have edited the above comment now.
|
src/webgl/p5.Shader.js
Outdated
@@ -579,9 +579,6 @@ p5.Shader = class Shader { | |||
const modelViewProjectionMatrix = modelViewMatrix.copy(); | |||
modelViewProjectionMatrix.mult(projectionMatrix); | |||
|
|||
if (this.isStrokeShader()) { | |||
this.setUniform('uPerspective', this._renderer._curCamera.useLinePerspective ? 1 : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we use uPerspective
uniform in our line.vert
file here:
p5.js/src/webgl/shaders/line.vert
Line 31 in 4fbbaf5
uniform int uPerspective;
So, we could keep them without the if block as well. Otherwise we would not be able to use uPerspective
unfiorm and could throw errors.
src/webgl/material.js
Outdated
* process each pixel on the canvas. This only affects the fill (the inside part of shapes), | ||
* not the strokes (outlines). | ||
* If you want to apply shaders to strokes or images, use the following methods: | ||
* - **[strokeShader()](#/p5/strokeShader)**: Applies a shader to the stroke (outline) of shapes, allowing independent control over the stroke rendering using shaders. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I was thinking to add these references at the last.
Like at first we could have our fill shader explanation.
At the middle we could have our example sketches how it works.
After the sketches we could have the references of strokeShader()
and imageShader()
. Let me know if that sound's okay to you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that too makes sense, I'll do that no worries!
As we're making breaking changes in this PR, we’ll end up with two distinct methods for applying shaders: The advantage of renaming it would be creating a clearer, more defined structure: Here's how it looks as of now: Screencast.from.15-09-24.01.13.59.AM.IST.webm |
Thank you for raising this discussion @perminder-17 ! Well, I would also like to add something to your suggestion, I see the potential value in renaming This approach aligns with how we’ve handled similar features, where the core functionality remains intuitively named, while specialized methods are introduced for distinct use cases. |
Looks good @perminder-17 ! I agree with @Garima3110, I don't think With |
I think I also agree with @lukeplowden and @Garima3110. Maybe the way to think about it is not in terms of fills and strokes, but in terms of materials and strokes. I suppose fill is actually just one component of an object's material, in addition to other properties like texture or shininess. Strokes are a separate system which adds something on top of the base material. In that view of everything, the material system is the main one you interact with and includes the most stuff, so treating it like the default in its naming feels right to me. One thing that's not super clean about the model I just described is that images are kind of just a separate system, and regular objects that have a material and stroke can't go through the image system, and likewise, images don't get materials and strokes. I think that's fine, since we want images to always draw an image, so making overriding of image() very separate and explicit probably will help avoid accidental overrides and confusion. So I see image shaders as maybe more of a convenient way for developers to change small bits about image drawing and still take advantage of the fit and fill options of image() rather than a core part of the material/stroke system I guess. |
Thankyou @lukeplowden @davepagurek and @Garima3110 for your thoughts.
We are now planning to create a method that will only affect image calls. In simple terms, we are separating our methods because in many scenarios, we have seen that sometimes fill gets applied to images and sometimes it doesn't, which causes problems and confusion see here: #6327 , #6564 . To avoid accidental shaders being applied and also to avoid confusion, we will create a new method called I’d also like your thoughts on something related to the question, which may seem obvious but I want to confirm. Do you think the |
Okay, @Garima3110 currently, the For example, if you see the code Line 1374 in 5fbde13
we check if For now, it’s worth disabling the fill shader effect for images, as @davepagurek's inclination was also towards not using fill shader for effecting image. For doing that, We can update the function p5.js/src/webgl/p5.RendererGL.js Line 1768 in 5fbde13
by adding an extra condition which could handle isTextureShader() .
Then, for Also, we could add example of by shaderHooks for only |
* The shader will be used for: | ||
* - Strokes only, regardless of whether the uniform `uStrokeWeight` is present. | ||
* | ||
* @method strokeShader |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A question @davepagurek, since we need to add docs for strokeShader utilising shaderHooks. I see we have a method with same name strokeShader
in shaderHooks as well. Do you think the method created in shaderHook PR will override this method (because they are with the same name)?
Thank you for bringing this up! @perminder-17
From my perspective, the motivation behind introducing a separate Considering the issues mentioned (#6327, #6564), I would say that the |
Ahh @perminder-17 you're right, those methods are going to clash, so we'll have to rename something. Maybe the hooks ones should be renamed to |
} | ||
} else if (!fill /* || !fill.isColorShader()*/) { | ||
return this._getColorShader(); | ||
if(fill && !fill.isTextureShader()){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aah....._getRetainedFillShader()
is for shapes, not images. You need to modify getImmediateFillShader()
, specifically where we are checking
if (this._tex) { ..... }
to properly handle images.
src/webgl/p5.RendererGL.js
Outdated
_getRetainedImageShader() { | ||
const imageShader = this.userImageShader; | ||
if (imageShader && imageShader.isTextureShader()) { | ||
return this._getLightShader(); // Return light shader if the shader is a texture shader | ||
} | ||
return imageShader || this._getColorShader(); // Default to color shader if no image shader is defined | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for these many conditions.
Just you have to do is:
If a texture is present, it then checks if the imageShader
is either missing or not set up for handling textures. If that’s the case, use light shader. Otherwise, it simply returns the existing imageShader
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, you should rename it to getImmidiateImageShader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p5.js/src/webgl/p5.RendererGL.Immediate.js
Line 510 in e624307
p5.RendererGL.prototype._drawImmediateFill = function(count = 1) { |
Also, we need to create something like _drawImmediateFill
for images where we could use _getImmidiateImageShader
in the function to make it working.
How about |
That also works for me. I guess the stroke one is the only naming conflict because the shader used internally for images is the material shader, and we're just using |
I don't think I mind it, but it could be confusing to have two terms for stroke. I noticed that you actually wrote However couldn't |
oops good catch @lukeplowden, I guess if I can confuse the two already then maybe that's a sign they'd be too similar.
Normally when we do that, it's for something that acts as both a setter and a getter, so if we do that here, I'd expect it to return whatever the active stroke shader is, which might be something set by users. We probably will still want a reliable way to get the default one though. Maybe that could mean |
That’s what I was imagining, but then again its also not ideal as it doesn’t align well with the other shader hook functions
|
yeah I think if we rename this one we'd probably also want to rename the others to have the same naming convention, |
Well. I find all three |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I am not technically 100% correct but what I feel is we are separating our shader in two parts (one with without image and one that will only handle image).
Since there's no method defined for images which you are using in the codebase and it throws errors. Also, there's a need to pass the function which you have made for images here:
p5.js/src/webgl/p5.RendererGL.Immediate.js
Line 195 in e624307
p5.RendererGL.prototype.endShape = function(
I am not 100% sure what could be the condition for that, but I think you can figure it out. That's the main reason why imageShader
is still not working for you.
src/webgl/p5.RendererGL.Immediate.js
Outdated
p5.RendererGL.prototype._drawImmediateImage = function(count = 1) { | ||
const gl = this.GL; | ||
let shader = this._getImmediateImageShader(); | ||
this._setImageUniforms(shader); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I run npm run build
this is throwing errors.
I don't think we currently have any method saying _setImageUniforms? Can you please check. Maybe it should be setFillUniform??
let shader = this._getImmediateImageShader(); | ||
this._setImageUniforms(shader); | ||
|
||
for (const buff of this.immediateMode.buffers.image) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this.immediateMode.buffers.image
is defined??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch it wasn't, I'll define it in the next code push. Thanks!
src/webgl/p5.RendererGL.Immediate.js
Outdated
shader.disableRemainingAttributes(); | ||
this._setTexUniforms(shader); | ||
this._applyColorBlend( | ||
this.curImageColor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be going to this.curImageColor
. I think that won't work, you need to use fill only for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well I think If we want separate control over the color of filled shapes and the color (or tint) of images, then keeping curImageColor
might be necessary.
But lets just use fill color for the time being.
src/webgl/p5.RendererGL.Immediate.js
Outdated
this._setTexUniforms(shader); | ||
this._applyColorBlend( | ||
this.curImageColor, | ||
this.immediateMode.geometry.hasImageTransparency() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasImageTransparency()
should be hasFillTransparency
. It would be really nice of you if could please check once, are these things for e.g. (hasImageTransparency()
) are defined in the codebase or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we have a separate hasImageTransparency()
and _setImageUniforms()
defined to have more control for imageShaders unlike just using the predefined fill methods here as you suggested?!
Or may be for the time being we can just test the working of imageShaders with predefined hasFillTransparency()
and _setFillUniforms
...
Let me know your thoughts on this @perminder-17 ?!!
Thanks @perminder-17 for the insights,I’m working on these changes ,will push the code super soon..! |
This is a work in progress addressing the issue ##6759
PR Checklist
npm run lint
passes