Is it possible to set a varying variable inside a fragment shader and have it persist? I'd like to use the depth component of the first fragment and use it on all the others, making the fragments all flat to the camera.

Secondary question: Is it the whole frag shader that runs per-fragment, or just the stuff inside main()? Is everything redeclared each time?


If you mean: Can I compute a variable in the first fragment and pass it around? No, not like that. The fragments are processed in parallel.

If you need to do that, compute the variable CPU side and pass it in as a uniform. If you needed to do a lot of computation you could output to a texture or a buffer and then read it back, but you only need one float from the sounds of it.

  • \$\begingroup\$ Ah ok, thank you. Guess I'll have to work out how to get the depth from the matrices; it's just frustrating when it can be accessed as simply as gl_FragCoord.z! \$\endgroup\$ – bonzairob May 1 '13 at 9:08

As Lewis said, fragments are processed in parrallel, each fragment shader is executed once per fragment. In GLSL there are three ways to communicate between your application and your shaders:

  1. uniform variables: variables that are set from user code, but only are allowed to change between different glDraw*​ calls. Uniforms can be queried and set by the code external to a particular shader.

  2. varying variables: are used as a communication between different shader stages, varying variables must be written in vertex shader, they will be interpolated by the graphics driver and then read from the fragment shader. (Please note that the qualifier "varying" has been deprecated and replaced with the more "descriptive" In/Out, yet the same functionality remains.

  3. vertex attributes: are values necessary to draw a model and change per vertex, they are fed to GLSL via user code and usually include Position, Normals, Tangents, Colors.

  4. if you mean Communication between different fragments processed by the same shader, well as said above GLSL executes a fragment shader once per fragment, but you can still share data between different fragments (for example to apply image processing effects) this usually done via Texture Samplers to access neighbor fragments. keep in mind that you usually need multipass algorithms for this, example usage may be: 1- Render you scene to texture. 2- apply it to a screen algined quad. 3- run your fragment shader on the quad and send the texture sampler to it. 4- access neighbor fragments by using offset when looking up texture coordinates ( e.g. glTexCoord.s+0.1).

  • \$\begingroup\$ Thanks, this answers my question about the structures of the shader! I was wondering how you'd access neighbouring pixels; having to do it in a second pass makes more sense. \$\endgroup\$ – bonzairob May 1 '13 at 9:09

You can achieve what you wish, but not the way you're thinking of doing it.

If you want to output a common depth for all fragments belonging to a primitive, you can add an extra vertex attribute - say, the midpoint of the primitive - which can be a per-instance attribute (if using instancing) or an extra per-vertex attribute (or even set via a glVertexAttrib3f call). The method used to set it doesn't matter much; what's important is that it has the same value for each vertex.

Duplicate your per-vertex calculations for position and for this extra attribute, then pass the extra attribute to your fragment shader as a varying. From there you just need to output depth from your fragment shader based on this extra attribute.

At this stage you're probably worrying a little about having to do the extra redundant calculations per-vertex, but this is not going to be a big deal compared to the overhead of outputting depth from your fragment shader, which will disable early-depth-testing for that shader, and which will be a requirement anyway if you want all fragments to have common depth.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.