<p>This isn't necessarily due to the orthographic projection per se, but rather the classic two-sided lighting problem together with a little optimization that the old OpenGL did. When the eye space origin is inside the object, you are basically <strong>looking at the object from the inside</strong> and it's only the peculiarities of orthographic projection and the near/far planes you chose that makes the outsides appear.</p>

<p>It depends on how you actually implement your shader. I <em>assume</em> though, when you compute your <code>viewDir</code>, you just use the vector from the eye space vertex to the origin (or rather the negative normalized eye space vertex position). You are basically trying to <strong>light the backfaces of the sphere</strong> and if you haven't taken account for that, the angle between the view vector and the normal will thus be larger than 90°, usually resulting in a negative or 0-clamped specular term (or whatever other unexpected results).</p>

<p>A common way to accomodate for that would be to negate the normal vector whenever it is facing away from the camera, or maybe the light, or when dealing with backfacing fragments,... But this depends on your specific use-case.</p>

<p>Now, <strong>why doesn't this happen in old deprecated OpenGL</strong> when using orthographic projection?</p>

<p>For this we have to look at the specificities of how it did its lighting computations. There was a function <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLightModel.xml" rel="nofollow noreferrer"><code>glLightModel</code></a> which controlled some of the global properties of lighting computations. Specifically, the paramter <code>GL_LIGHT_MODEL_LOCAL_VIEWER</code>. This controls an optimization where the specular computation does <em>not</em> use the actual vector from the vertex to the camera, but <strong>always just uses the z-axis</strong> instead. i.e. as you said it assumes an infinitely far away viewer along the z-axis. This is the reason why even in perspective projection the specular highlight on an object is always at the same position, even if you move it around in the view. If you change this setting from the default of <code>GL_FALSE</code> to <code>GL_TRUE</code>, it should perform an actual view vector computation and you should get the same results as with your own shader.</p>

<p>There was also another option that controls a property related to your general issue, too. <code>GL_LIGHT_MODEL_TWO_SIDE</code> enables two-sided lighting, which means that back-facing polygons will be lit like their front faces (however, possibly using different material settings) by using the inverted normal. If you activate this, this still won't change anything in your orthographic scene, since <strong>you <em>are</em> seeing the front faces</strong> of the sphere here. But once you change to perspective projection, the lighting should be black, but this time because you're seeing the backfaces, which you can enable lighting for with this option.</p>

CC BY-SA 3.0
2018-01-25T15:49:27.037Z
Awesome, Your comment about GL_LIGHT_MODEL_LOCAL_VIEWER seems right on. I checked our code and we don't set that, and it appears the default is 0 which means that our viewer is always infinitely far away, even in perspective mode (without shaders).  So I assume that even though the specular does move around when i rotate, its because it is rotating the direction of the z-axis.  However, when i translate, the specular doesn't move around, even in perspective.  Thanks!
default
CC BY-SA 3.0
2018-01-25T12:41:26.880Z
2018-01-25T12:41:26.880Z
Christian Rau
<p>I have a scene set up with an orthographic projection with the near / far set from -5000 to 5000.  The model view is centered at 0 in the z-axis.  I am rendering a sphere centered at z=0 with lighting, and the specular component appears as to be calculated as if the eye were infinity far back.  See image below, in which the light only has a red specular component, no diffuse or other parameters.  However, if i render this with a custom shader that implements <a href="https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model" rel="nofollow noreferrer">blinn</a> lighting, the sphere appears black, because the "viewDir" calculation is negative, since the eye is centered inside the sphere.  How does fixed function get around this?  Does it some how know about the ortho projection and get around it?  Sources I've seen online say lighting is not supposed to take the projection into account.</p>

<p><a href="https://i.sstatic.net/ire0b.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/ire0b.png" alt="fixed function specular with ortho projection"></a></p>

CC BY-SA 3.0
2018-01-24T17:54:16.477Z
"*However, if i render this with a custom shader that implements blinn lighting, the sphere appears black, because the "viewDir" calculation is negative, since the eye is centered inside the sphere.*" If you're able to see the sphere from the outside, then I submit that your "eye is centered inside the sphere" notion is incorrect. Either that, or you have a different understanding of what the word "eye" means.
Nicol Bolas
CC BY-SA 3.0
2018-01-24T18:25:31.790Z
I mean that the model view is centered inside the sphere.
default
CC BY-SA 3.0
2018-01-24T18:28:21.763Z
From the glOrtho docs: "Typically, the matrix mode is GL_PROJECTION, and left bottom - nearVal and right top - nearVal specify the points on the near clipping plane that are mapped to the lower left and upper right corners of the window, respectively, assuming that the eye is located at (0, 0, 0). - farVal specifies the location of the far clipping plane. Both nearVal and farVal can be either positive or negative."  So they even seem to confirm that the eye is at 0,0 but the near clip can be negative so you see stuff "behind" you.
default
<opengl><lighting>
How does opengl fixed function pipeline determine specular lighting with an orthographic projection
default
# How does opengl fixed function pipeline determine specular lighting with an orthographic projection

(Asked by: username_0 on 2018-01-24)

I have a scene set up with an orthographic projection with the near / far set from -5000 to 5000. The model view is centered at 0 in the z-axis. I am rendering a sphere centered at z=0 with lighting, and the specular component appears as to be calculated as if the eye were infinity far back. See image below, in which the light only has a red specular component, no diffuse or other parameters. However, if i render this with a custom shader that implements [blinn](https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model) lighting, the sphere appears black, because the "viewDir" calculation is negative, since the eye is centered inside the sphere. How does fixed function get around this? Does it some how know about the ortho projection and get around it? Sources I've seen online say lighting is not supposed to take the projection into account.

[![fixed function specular with ortho projection](https://i.sstatic.net/ire0b.png)](https://i.sstatic.net/ire0b.png)

**Tags:** opengl, lighting

> **Comments:**
> **username_1**: "*However, if i render this with a custom shader that implements blinn lighting, the sphere appears black, because the "viewDir" calculation is negative, since the eye is centered inside the sphere.*" If you're able to see the sphere from the outside, then I submit that your "eye is centered inside the sphere" notion is incorrect. Either that, or you have a different understanding of what the word "eye" means.  
> **username_0**: I mean that the model view is centered inside the sphere.  
> **username_0**: From the glOrtho docs: "Typically, the matrix mode is GL_PROJECTION, and left bottom - nearVal and right top - nearVal specify the points on the near clipping plane that are mapped to the lower left and upper right corners of the window, respectively, assuming that the eye is located at (0, 0, 0). - farVal specifies the location of the far clipping plane. Both nearVal and farVal can be either positive or negative."  So they even seem to confirm that the eye is at 0,0 but the near clip can be negative so you see stuff "behind" you.  

---

## 1 answers

### Answer by username_2 on 2018-01-25. Score: 2 | Accepted answer

This isn't necessarily due to the orthographic projection per se, but rather the classic two-sided lighting problem together with a little optimization that the old OpenGL did. When the eye space origin is inside the object, you are basically **looking at the object from the inside** and it's only the peculiarities of orthographic projection and the near/far planes you chose that makes the outsides appear.

It depends on how you actually implement your shader. I *assume* though, when you compute your `viewDir`, you just use the vector from the eye space vertex to the origin (or rather the negative normalized eye space vertex position). You are basically trying to **light the backfaces of the sphere** and if you haven't taken account for that, the angle between the view vector and the normal will thus be larger than 90°, usually resulting in a negative or 0-clamped specular term (or whatever other unexpected results).

A common way to accomodate for that would be to negate the normal vector whenever it is facing away from the camera, or maybe the light, or when dealing with backfacing fragments,... But this depends on your specific use-case.

Now, **why doesn't this happen in old deprecated OpenGL** when using orthographic projection?

For this we have to look at the specificities of how it did its lighting computations. There was a function [`glLightModel`](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLightModel.xml) which controlled some of the global properties of lighting computations. Specifically, the paramter `GL_LIGHT_MODEL_LOCAL_VIEWER`. This controls an optimization where the specular computation does *not* use the actual vector from the vertex to the camera, but **always just uses the z-axis** instead. i.e. as you said it assumes an infinitely far away viewer along the z-axis. This is the reason why even in perspective projection the specular highlight on an object is always at the same position, even if you move it around in the view. If you change this setting from the username_0 of `GL_FALSE` to `GL_TRUE`, it should perform an actual view vector computation and you should get the same results as with your own shader.

There was also another option that controls a property related to your general issue, too. `GL_LIGHT_MODEL_TWO_SIDE` enables two-sided lighting, which means that back-facing polygons will be lit like their front faces (however, possibly using different material settings) by using the inverted normal. If you activate this, this still won't change anything in your orthographic scene, since **you *are* seeing the front faces** of the sphere here. But once you change to perspective projection, the lighting should be black, but this time because you're seeing the backfaces, which you can enable lighting for with this option.

> **Comments:**
> **username_0**: Awesome, Your comment about GL_LIGHT_MODEL_LOCAL_VIEWER seems right on. I checked our code and we don't set that, and it appears the username_0 is 0 which means that our viewer is always infinitely far away, even in perspective mode (without shaders).  So I assume that even though the specular does move around when i rotate, its because it is rotating the direction of the z-axis.  However, when i translate, the specular doesn't move around, even in perspective.  Thanks!  

---

