<p>I've been experimenting with raytracing using GLSL. I had success rendering a cube which encloses the object.</p>

<p>Now I want to do a full-screen raytrace, and I want to construct a quad which covers the screen. This isn't working.</p>

<p>First, for the working version, the shaders looked something like this:</p>

<p>Vertex shader:</p>

<pre><code>in vec3 v_position;

uniform mat4 u_proj_view;

void main ()
{
    gl_Position = u_proj_view * vec4 (v_position, 1.0);
}
</code></pre>

<p>Fragment shader, which computes the word coordinate <code>W</code> of the fragment, and given the eye coordinate <code>E</code> solves <code>P=E+t(W-E)</code> for <code>t</code> given some surface intersection constraint on <code>P</code>.</p>

<pre><code>vec3 W = screen_to_world (gl_FragCoord, inverse_proj_view, viewport);
vec3 EW = W - E;
// solve for t, etc etc.
</code></pre>

<p>The <code>screen_to_world</code> function I took from <a href="https://stackoverflow.com/questions/38938498/how-do-i-convert-gl-fragcoord-to-a-world-space-point-in-a-fragment-shader">here</a></p>

<pre><code>vec3 screen_to_world
(
    in vec4 screen_fragment_coordinate,
    in mat4 inverse_projection_view,
    in vec4 viewport
)
{
    vec4 S = screen_fragment_coordinate;
    vec4 NDC;

    NDC.xy = ((2.0 * S.xy) - (2.0 * viewport.xy))
        / (viewport.zw) - 1.0;

    NDC.z = (2.0 * S.z - gl_DepthRange.near - gl_DepthRange.far) /
        (gl_DepthRange.far - gl_DepthRange.near);

    NDC.w = 1.0;

    return vec4 (inverse_projection_view * (NDC / S.w)).xyz;
}
</code></pre>

<p>For the full-screen render, It would be nice to construct a quad directly in clip space, or directly in screen space. I tried using vertex data like this</p>

<pre><code>Vertex full_screen_quad [4] =
{
    {{-1, -1, 0.5}},
    {{+1, -1, 0.5}},
    {{-1, +1, 0.5}},
    {{+1, +1, 0.5}}
};
</code></pre>

<p>And changed the vertex shader to</p>

<pre><code>gl_Position = vec4 (v_position, 1.0);
</code></pre>

<p>which omits the projection-view transformation. I was hoping that this would still produce valid values for <code>screen_to_world</code> in the fragment shader, but no such luck. The screen is filled but the rays are wonky.</p>

<p>To investigate, I printed out the coordinates of the cube vertices when multiplied by the projection-view matrix and, when the cube was on screen, were something like</p>

<pre><code>vec4(-2.704530, -12.888471, 12.998095, 13.171925)
</code></pre>

<p>I was expecting values in the range <code>[0..1]</code>, so clearly I don't understand which coordinate space I'm working in, or I don't understand w-coordinates, or viewports, or something.</p>

<p>Are there <em>fixed</em> coordinates which I can <em>directly</em> pass to <code>gl_Position</code>, <em>untransformed</em>, which will effectively cover the near plane of the viewing frustum, exactly?</p>

<p>(When done correctly, passing such coordinates to the above <code>screen_to_world</code> will yield the world-space coordinates of the near frustum plane.)</p>

<p>Can I describe these independently of the projection-view matrix, and still have <code>screen_to_world</code> work correctly for each fragment?</p>

<p>Alternatively, and less ideally, can I hack some world-space coordinates, given the arguments to <code>glm::lookAt</code> and <code>glm::perspective</code> (which produce the <code>projection*view</code> matrix), such that they will cover the near frustum plane?</p>

CC BY-SA 4.0
2019-09-11T01:54:29.300Z
I'm unclear on the purpose of your `screen_to_world` function. Yes, I know what it does, but I'm not clear on why you're using it. You're drawing a quad; the *only reason* you're drawing a quad is to make the fragment shader execute for each pixel. What is the point of wanting the world-space position of the *quad*? If you're doing ray-tracing, then what you need is the ray (position and direction) from the camera to that pixel. And that has nothing to do with the actual geometry you drew (though `gl_FragCoord` can be helpful in computing it).
Nicol Bolas
CC BY-SA 4.0
2019-09-11T12:27:33.697Z
`screen_to_world` is used when a raytraced object is surrounded by a hull of polygons. I render the polygons (rather than the whole screen) and then use the world-space coordinate of the fragment of the polygon to construct a ray which may or may not hit the object behind it. If I can execute a fragment shader for every fragment of the screen and obtain the world-space coordinate of that fragment without using this function, then great. I was just showing you my approach so far, and how it fails for the full-screen case.
spraff
CC BY-SA 4.0
2019-09-11T13:26:21.597Z
My point is that you don't need the "the world-space coordinate of the fragment of the polygon" in order to "construct a ray". You only need the ray *itself*, which can [easily be constructed in camera-space](https://alfonse.bitbucket.io/oldtut/Illumination/Tut13%20Correct%20Chicanery.html), without ever knowing anything about the "hull of polygons". You're making everything much harder than it needs to be.
Nicol Bolas
CC BY-SA 4.0
2019-09-11T13:29:44.690Z
But I can only construct a ray in camera-space if I am raytracing an object which is also described in camera-space, right? And even then I still need the frament coordinate to be in camera-space, I still to transform gl_FragCoord to undo the projection.
spraff
CC BY-SA 4.0
2019-09-11T13:32:36.057Z
... why *wouldn't* your object/scene be in camera-space, if that's the space that's trivial to compute your ray in? Alternatively, if it's that important (and you want to disregard all the [warnings about direct usage of world-space](https://alfonse.bitbucket.io/oldtut/Positioning/Tut07%20The%20Perils%20of%20World%20Space.html)), world-space is a single matrix transform away from camera space. It's still less work than your `screen_to_world` function.
Nicol Bolas
CC BY-SA 4.0
2019-09-11T13:44:27.710Z
Because world-space is "natural" to me. But yeah I can do it in camera space. But then I want to convert gl_FragCoord to camera space [which looks like a lot of work](https://www.khronos.org/opengl/wiki/Compute_eye_space_from_window_space), so I'm confused as to why you think doing in camera space will be any simpler.
spraff
CC BY-SA 4.0
2019-09-12T14:30:03.180Z
@spraff If you just want to ray trace, it is enough that you have a quad, with no projection, view, or whatever transformation. Then you do everything in your shader, like in shadertoy.
lightxbulb
<opengl><transformations><glsl><projections>
What quad will fill the screen, which can be inverse-projection-view transformed to map to the near frustum plane?
spraff
# What quad will fill the screen, which can be inverse-projection-view transformed to map to the near frustum plane?

(Asked by: username_0 on 2019-09-10)

I've been experimenting with raytracing using GLSL. I had success rendering a cube which encloses the object.

Now I want to do a full-screen raytrace, and I want to construct a quad which covers the screen. This isn't working.

First, for the working version, the shaders looked something like this:

Vertex shader:

```
in vec3 v_position;

uniform mat4 u_proj_view;

void main ()
{
    gl_Position = u_proj_view * vec4 (v_position, 1.0);
}

```

Fragment shader, which computes the word coordinate `W` of the fragment, and given the eye coordinate `E` solves `P=E+t(W-E)` for `t` given some surface intersection constraint on `P`.

```
vec3 W = screen_to_world (gl_FragCoord, inverse_proj_view, viewport);
vec3 EW = W - E;
// solve for t, etc etc.

```

The `screen_to_world` function I took from [here](https://stackoverflow.com/questions/38938498/how-do-i-convert-gl-fragcoord-to-a-world-space-point-in-a-fragment-shader)

```
vec3 screen_to_world
(
    in vec4 screen_fragment_coordinate,
    in mat4 inverse_projection_view,
    in vec4 viewport
)
{
    vec4 S = screen_fragment_coordinate;
    vec4 NDC;

    NDC.xy = ((2.0 * S.xy) - (2.0 * viewport.xy))
        / (viewport.zw) - 1.0;

    NDC.z = (2.0 * S.z - gl_DepthRange.near - gl_DepthRange.far) /
        (gl_DepthRange.far - gl_DepthRange.near);

    NDC.w = 1.0;

    return vec4 (inverse_projection_view * (NDC / S.w)).xyz;
}

```

For the full-screen render, It would be nice to construct a quad directly in clip space, or directly in screen space. I tried using vertex data like this

```
Vertex full_screen_quad [4] =
{
    {{-1, -1, 0.5}},
    {{+1, -1, 0.5}},
    {{-1, +1, 0.5}},
    {{+1, +1, 0.5}}
};

```

And changed the vertex shader to

```
gl_Position = vec4 (v_position, 1.0);

```

which omits the projection-view transformation. I was hoping that this would still produce valid values for `screen_to_world` in the fragment shader, but no such luck. The screen is filled but the rays are wonky.

To investigate, I printed out the coordinates of the cube vertices when multiplied by the projection-view matrix and, when the cube was on screen, were something like

```
vec4(-2.704530, -12.888471, 12.998095, 13.171925)

```

I was expecting values in the range `[0..1]`, so clearly I don't understand which coordinate space I'm working in, or I don't understand w-coordinates, or viewports, or something.

Are there *fixed* coordinates which I can *directly* pass to `gl_Position`, *untransformed*, which will effectively cover the near plane of the viewing frustum, exactly?

(When done correctly, passing such coordinates to the above `screen_to_world` will yield the world-space coordinates of the near frustum plane.)

Can I describe these independently of the projection-view matrix, and still have `screen_to_world` work correctly for each fragment?

Alternatively, and less ideally, can I hack some world-space coordinates, given the arguments to `glm::lookAt` and `glm::perspective` (which produce the `projection*view` matrix), such that they will cover the near frustum plane?

**Tags:** opengl, transformations, glsl, projections

> **Comments:**
> **username_1**: I'm unclear on the purpose of your `screen_to_world` function. Yes, I know what it does, but I'm not clear on why you're using it. You're drawing a quad; the *only reason* you're drawing a quad is to make the fragment shader execute for each pixel. What is the point of wanting the world-space position of the *quad*? If you're doing ray-tracing, then what you need is the ray (position and direction) from the camera to that pixel. And that has nothing to do with the actual geometry you drew (though `gl_FragCoord` can be helpful in computing it).  
> **username_0**: `screen_to_world` is used when a raytraced object is surrounded by a hull of polygons. I render the polygons (rather than the whole screen) and then use the world-space coordinate of the fragment of the polygon to construct a ray which may or may not hit the object behind it. If I can execute a fragment shader for every fragment of the screen and obtain the world-space coordinate of that fragment without using this function, then great. I was just showing you my approach so far, and how it fails for the full-screen case.  
> **username_1**: My point is that you don't need the "the world-space coordinate of the fragment of the polygon" in order to "construct a ray". You only need the ray *itself*, which can [easily be constructed in camera-space](https://alfonse.bitbucket.io/oldtut/Illumination/Tut13%20Correct%20Chicanery.html), without ever knowing anything about the "hull of polygons". You're making everything much harder than it needs to be.  
> **username_0**: But I can only construct a ray in camera-space if I am raytracing an object which is also described in camera-space, right? And even then I still need the frament coordinate to be in camera-space, I still to transform gl_FragCoord to undo the projection.  
> **username_1**: ... why *wouldn't* your object/scene be in camera-space, if that's the space that's trivial to compute your ray in? Alternatively, if it's that important (and you want to disregard all the [warnings about direct usage of world-space](https://alfonse.bitbucket.io/oldtut/Positioning/Tut07%20The%20Perils%20of%20World%20Space.html)), world-space is a single matrix transform away from camera space. It's still less work than your `screen_to_world` function.  
> **username_0**: Because world-space is "natural" to me. But yeah I can do it in camera space. But then I want to convert gl_FragCoord to camera space [which looks like a lot of work](https://www.khronos.org/opengl/wiki/Compute_eye_space_from_window_space), so I'm confused as to why you think doing in camera space will be any simpler.  
> **username_2**: @username_0 If you just want to ray trace, it is enough that you have a quad, with no projection, view, or whatever transformation. Then you do everything in your shader, like in shadertoy.  

---

## 0 answers

