0

In my fragment/pixel shader I am trying to calculate a fragment's depth position in percent [0-1] in an given range. What I have is a bunch of shapes (there is no relative data given from them) but all the shapes have one thing in common and that is their depth is always 1000 pixels.

From the depth value I get from a fragment I want to be able to calculate where in this shape's range (1000.0 pixels) it is in a value between [0-1].

This means I could have a depth value for a current fragment of, say 2300, but I need to know where it is in the shape's depth of 1000 pixels.

So if the shape was lying exactly where the camera is I could calculate where the current fragments depth value is by doing:

float depth = (gl_FragCoord.z / gl_FragCoord.w);
float perc  = 1.0 - (depth / 1000.0);

This is all well and good but the problem is when the shape is lying further away from the camera. How can I from that depth position calculate where it is in the range of 1000 px. In a way the range would have to be treated as it was also lying further away from the camera but the problem is I only got a fragments depth value and the range available to use here.

An image explains more! Imagine it from being above, so it goes down the Z axis.

details

So is this even at all possible to work out? Or should I try another approach?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Placeable
  • 589
  • 8
  • 22
  • 1
    "*their depth is always 1000 pixels*" If all of the fragments depths are 1000 pixels, then their depths *don't change*. Are you perhaps saying *less* than 1000 pixels? – Nicol Bolas May 23 '13 at 14:19
  • Ah no the shape's depth is always 1000 px. The other axis are arbitrary but it has a depth of always 1000 px in "width" that goes down the camera. Imagine a box where its X and Y axis can change but its depth is always 1000 px. – Placeable May 23 '13 at 14:22
  • And by shape I mean the object sort of speak I am rendering. It always has a depth of 1000 px. Out from this shape when I am in the fragment shader I want to be able to go over each fragment in this shape, look over each fragments depth and see where it lies WITHIN the shape's depth/range of 1000 px. Sorry if this seem confusing a bit hard to explain :) – Placeable May 23 '13 at 14:25
  • Is each shape a separate draw call? If so you could just use a uniform set to the shape's min depth value then do perc = 1.0 - ((depth-u_depth_min) / 1000.0) – GuyRT May 23 '13 at 14:32
  • Sadly its not a separate draw call for each shape they are all drawn at the same time in the same fbo. – Placeable May 23 '13 at 14:33
  • 2
    pixels is not really an appropriate unit if talking about depth. In physics whenever we talk about some numeric value within some range without a particular unit attached we talk about "arbitrary units" or short *a.u.*. With depth an appropriate term might be "framebuffer depth units" (FDU) or similar. But not pixels. – datenwolf May 23 '13 at 14:52
  • Ah thank you I stand corrected on the terminology of course you are correct, my bad :) I have been struggling with this issue for a few hours and and I can find smart math to get what I want. The problem is very trivial but the solution... ugh. – Placeable May 23 '13 at 14:54
  • 2
    Can you add a vertex attribute set to the min depth for the shape the vertex belongs to? – GuyRT May 23 '13 at 15:10
  • That might be an idea. The way I am rendering the shapes are all in the same vertex buffer so I might have to look over how I am doing this rendering. its not very easy to work with as I have it now. Though ideal would be to just come up with some solution in the fragment shader. I might have to retreat that approach sadly. – Placeable May 23 '13 at 15:30
  • Vertex Attribute, Uniform or use gl_VertexID to construct the shape index if all the shapes have the same data size.. then send in the min data array though uniform/ubo or texture. – Grimmy May 23 '13 at 19:19
  • 1
    Note that the depth value is not the Z coordinate in camera space, but a distorted value depending on the far and near frustum properties. This is because of the projection matrix. `gl_FragCoord` are in clip space, but you want their values in camera space. In my current project I need to compute the Z value from the depth value. If I understand you correctly, you need the same. It can be computed (with far and near being uniforms in a shader) with the formula `cameraZ = (near * far) / (far - depthValue * (far - near))` – leemes May 24 '13 at 14:41
  • @leemes This is useful information but not the complete answer but thank you anyway. What I need is a min value/pos for each shape that I can send in as a uniform to my shader. This is probably the only way to solve what I am after though I had hoped it could be achieved in another way. – Placeable May 28 '13 at 08:35

1 Answers1

1

Alright I finally I solved it so I will type my answer here.

As suggested by the comments from the original question I find the min/max z-position of each shape I draw and send these two values in as uniforms to my fragment shader.

In the vertex shader I grab the current Z-position as a varying variable:

[Vertex Shader]

uniform mat4 mvp;
varying float zPos;

void main()
{
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_TexCoord[1] = gl_MultiTexCoord1;
    gl_FrontColor  = gl_Color;
    //gl_Position  = ftransform();
    gl_Position    = mvp * gl_Vertex;
    zPos           = gl_Vertex.z;
}

And in my fragment shader:

[Fragment Shader]

uniform float minZ;
uniform float maxZ;
varying float zPos;

void main(void)
{
    float mul = (abs(zPos)-minZ) / (maxZ - minZ);
    float col = 1.0 * mul;

    gl_FragColor = vec4(col, 0.0, 0.0, 1.0);
}

This yields a value for mul that is between [0-1] which I can use for alpha fading on my shapes no matter where they are relative to the camera. No need for the depth value at all.

The maxZ/minZ values that are calculated in the main program on the CPU I send in as positive values (I find it easier to treat them as such) but they are negative in source. That's why I use abs(...) on the zPos variable.

Some tweaks and adjustment is needed but what I am looking for is achieved. Thanks a lot for all the input.

Placeable
  • 589
  • 8
  • 22