ruhig brauner
ruhig brauner

Reputation: 963

Calculate vector intersections in GLSL (OpenGL)

I want to add fog to a scene. But instead of adding fog to the fragment color based on its distance to the camera, I want to follow a more realistic approach. I want to calculate the distance, the vector from eye to fragment "travels" through a layer of fog.

enter image description here

With fog layer I mean that the fog has a lower limit (z-coordinate, which is up in this case) and a higher limit. I want to calculate the vector from the eye to the fragment and get the part of it which is inside the fog. This part is marked red in the graphic.

The calculation is actually quite simple. However, I would have to do some tests (if then) with the easy approach.

calculate line from vector and camera position;
get line intersection with lower limit;
get line intersection with higher limit;

do some logic stuff to figure out how to handle the intersections;
calculate deltaZ, based on intersections;          
scale the vector (vector = deltaZ/vector.z)
fogFactor = length(vector);

This should be quite easy. However, what makes trouble is that I would have to add some logic to figure out how the camera and the fragment is located in relation to the fog. Also I have to be sure that the vector actually has an intersection with the limits. (It would makes trouble when the vectors z-Value is 0) The problem is that alternations are not the best friend of shaders, at least this is what the internet has told me. ;)

My first question: Is there an better way of solving this problem? (I actually want to stay with my model of fog since this is about problem solving.)

The second question: I think that the calculation should be done from the fragment shader and not the vertex shader since this is nothing which can be interpolated. Am I right with this?

Here is a second graphic of the scenario.

second graphic

Upvotes: 2

Views: 1923

Answers (1)

ruhig brauner
ruhig brauner

Reputation: 963

Instead of defining the fog with a lower limit and a higher limit, I define it with a center height and a radius. So the lower limit equals the center minus the radius, the higher limit is the center plus the radius.

With this, I came up with this calculation: (sorry for the bad variable names)

// Position_worldspace is the fragment position in world space
// delta 1 and 2 are differences in the  z-axis from the fragment / eye to
// the center height

float delta1 = clamp(position_worldspace.z - fog_centerZ, 
                     -fog_height, fog_height)
float delta2 = clamp(fog_centerZ - cameraPosition_worldspace.z, 
                     -fog_height, fog_height);

float fogFactor z = delta1 + delta2;

vec3 viewVector = position_worldspace - cameraPosition_worldspace;
float fogFactor = length(viewVector * (fogFactorZ / (viewVector ).z));

I guess this is not the fastest way of calculating this but it does the trick.

HOWEVER! The effect isn't really beautiful because the higher and lower limit of the fog are razor sharp. I forgot about this since it doesn't look bad when the eye isn't near those borders. But I think there is an easy solution to this problem. :)

Upvotes: 1

Related Questions