uniform vs. attribute variables in shaders
category: code [glöplog]
Hi,
I recently rediscovered - after 10 years of nothing - a certain interest in pc and demo programming. Things sure changed a lot by the time, and I suddenly feel old and antiquated...
However, following the advice "just start coding and make something appear on the screen", I begun messing with WebGL and I wrote a standard minimal framework for shaders, just to teach me how to pass variables to shaders and stuff like this.
That's a simple Monjori intro port running on WebGL, but I don't understand how I should pass the "time" variable to the fragment shader in order to write something slightly optimized: the Orange GLSL book states that a variable qualified as unifrom should be used when its value changes "relatively infrequently"... but how much is relatively unfrequently? That's the approach I chose for passing the time value to the shader, but it changes at least once per frame.
The alternative - correct? - way would be to pass the time as an attribute qualified variable to the vertex shader that then is passed to the fragment shader, but this approach seems very convolute!
Sorry for the noob question!
I recently rediscovered - after 10 years of nothing - a certain interest in pc and demo programming. Things sure changed a lot by the time, and I suddenly feel old and antiquated...
However, following the advice "just start coding and make something appear on the screen", I begun messing with WebGL and I wrote a standard minimal framework for shaders, just to teach me how to pass variables to shaders and stuff like this.
That's a simple Monjori intro port running on WebGL, but I don't understand how I should pass the "time" variable to the fragment shader in order to write something slightly optimized: the Orange GLSL book states that a variable qualified as unifrom should be used when its value changes "relatively infrequently"... but how much is relatively unfrequently? That's the approach I chose for passing the time value to the shader, but it changes at least once per frame.
The alternative - correct? - way would be to pass the time as an attribute qualified variable to the vertex shader that then is passed to the fragment shader, but this approach seems very convolute!
Sorry for the noob question!
I'm not an expert also, but the general idea is this: pass everything that is constant over bunch of data (vertices/fragments/whatever) as uniform. Time is a very good example for that.
Everything else that changes between elements in the same draw call (normals, tex coords, whatever other custom stuff you come up with) should be passed as an attribute.
Everything else that changes between elements in the same draw call (normals, tex coords, whatever other custom stuff you come up with) should be passed as an attribute.
Just use uniforms for all constants that come from outside the shader and do not change during the execution.
Basically what w23 said. Attributes are just that: "vertex" attributes like (per-vertex-)normal, (per-vertex-)color, etc.
Uniforms are what you pass to a shader to set up global values that doen't change during one rendering call. You can create sets uniforms ("Uniform Buffer Object"s) to share them between program, quickly switch them etc.
Uniforms are what you pass to a shader to set up global values that doen't change during one rendering call. You can create sets uniforms ("Uniform Buffer Object"s) to share them between program, quickly switch them etc.
Passing time as a uniform should be fine. I do it all the time.
That's pretty much how everyone's doing it. :)
I thought "everyone" is passing time as z coordinate of the one fullscreen quad nowadays :)
(don't listen to me. Uniform is the way to go. :)
(don't listen to me. Uniform is the way to go. :)
uniforms can't be changed during a draw call, so everything that's specific to parts of a mesh (like a single vector) you are sending to the gpu has to be modelled as vertex attribute (as w23 said: normals, tex coords). time changes "relatively infrequently", that is once per frame, i.e. once per shader program usage. more often would be something like material ids for different object you are rendering using the same shader, i don't know if that's what the orange book still mentions as "relatively infrequently". but i'm not really an expert either.
kb_: or as a color along with some envelopes or other data :)
kb_: or as a color along with some envelopes or other data :)
kb_: i usually pass time as scale by using glRectf(-t, -t, t, t) (where t=ticks_in_ms/1000.f+1.f) on the code side, and restore it as p.w=length(gl_Vertex.xy) in vertex shader.
zerothehero: if something changes only once per frame (like time!) and it represents a small amount of data (say, few floats, like time!), then that's a candidate for being a uniform. instead, if something changes per vertex (or every few vertices) in your mesh/redner call, make it an attribute/varying. there are more mechanism (buffers, textures...), but for i'd say that for now you are good with that rule of thumb.
THANKS!
This doubt I had, came from the only example I met in the Orange Book so far, that is a trivial vertex+fragment shader which evaluates the color of a surface depending on its tempearature; the uniform variables that are passed are the temperature range and the the coolest temp, which are obviously prone to not be changed frequently - more constant values than real variables.
That why I thought that the time variable would be a candidate for being a "frequently value changing" variable.
Now it's clear, thanks again!
This doubt I had, came from the only example I met in the Orange Book so far, that is a trivial vertex+fragment shader which evaluates the color of a surface depending on its tempearature; the uniform variables that are passed are the temperature range and the the coolest temp, which are obviously prone to not be changed frequently - more constant values than real variables.
That why I thought that the time variable would be a candidate for being a "frequently value changing" variable.
Now it's clear, thanks again!
While there's a definite consensus that time should be a uniform (and it's the way I've always done it), this thread got me thinking that a different time value per vertex could be fun.
psonice: congrats, you just discovered how to do raymarched jello cubes basically for free ;)
woohoo! I can make that twister at last!