# Area of surface contained in pixel

Let's say I have some surface rasterized and stored to a texture. How do I calculate the actual surface area that is visible in one of the rasterized pixels, from some other location?

So far, I'm assuming it's

A_visible = A * cos(theta) / d^2

where d = distance from viewer, theta = angle between normal and viewer-surface direction, A = ... I'm not even sure how to express it. I guess you could call it the "world space area" of the pixel.

Is the above equation even correct? How do I determine "A? Notice that I'm not only looking for the area strictly as visible from the (e.g. perspective) camera. I'd also like to compute this area as visible from other surfaces, i.e. other surface areas that receive light from all around its hemisphere above the surface.

• This looks line an X-Y problem. What are you actually trying to achieve through this calculation? Feb 4, 2014 at 4:12
• Maybe it helps if you consider a pixel <=> rectangle. Unproject rays from corners and intersect with geometry, then you know geometry footprint and can calculate its size. Feb 4, 2014 at 4:50
• What do you mean by surface, which units are you using? You mean the area visible on the monitor? Do you mean a pixel that is partially hidden or an exposed pixel? Feb 4, 2014 at 5:23
• @ArthurWulfWhite I'm not looking for the area on the monitor. I'm looking for the area as seen from, for example, a light source, with an arbitrary projection matrix. That includes hemispherical light sources, like other surface poitns. I need the information for global illumination, where I need to account for surface area somehow (since rendering equation only evaulates differential areas, of which I can only evaluate a limited amount). Units... I don't know. I use the metric system, of course, and in coordinates 1.0f = 1 meters, but I don't know how that would translate to pixel sizes. Feb 4, 2014 at 12:07
• You are looking for the angles bounding the pixel area, not the actual surface on the vertex textured by that pixel? Or you wish to project the rays from the textured vertex into another mesh and measure that? Feb 4, 2014 at 12:21

To find the area that a pixel contains you can use the solid angle equation where

A_s / ||d_s||^2 = A_near / ||d_near||^2
A_s    = the surface of the pixel at d_s distance
A_near = the surface of the pixel at the near plane


You know d_s and d_near so you have to find A_near

A_near = width * height = 4 * tan(FOV/2)^2 * d_near^2 / ( aspectRatio * Nx * Ny )
Where  width and height are the width and height of the pixel
FOV = Field of View of your projection matrix
AspectRatio = height to width ratio
Nx and Ny are the number of texels in horizontal and vertical directions of the image


This way you can find the A_s which is the surface area of your pixel when its normal is perpendicular to the viewing direction. To find the correct area surface you just have to multiply A_s with cos(theta) where theta is the angle of normal and view direction (actually -viewDirection).

• The last paragraph is incorrect. Viewing a texture from an oblique angle makes it appear smaller, i.e. the same surface is rendered in fewer pixels. The area covered by a single pixel increases. Multiplication by cos(theta) reflects the opposite. Feb 4, 2014 at 14:16
• @AnastasiosG How would I apply your calculations to a receiver with a hemispherical projection matrix, i.e. FOV = pi (or 180 degrees) and aspectRatio = 1? For example, surface areas that receive light would have such a projection matrix, I think. Feb 6, 2014 at 21:43
• @MarcksThomas You're right, you have to divide by cos(theta) instead of multiplying. Feb 7, 2014 at 2:41
• @TravisG You have to replace A_near and d_near by the area and distance of the pixel on the screen, whatever shape the "screen" is. There's no such thing as a hemispherical projection matrix AFAIK, but if you have some other method of mapping pixels to directions in space, you can work through the calculations for that. BTW, this calculation doesn't include the fact that for a standard perspective projection, pixels near the center of the screen cover a larger solid angle than pixels near the edge. Feb 7, 2014 at 2:44
• @NathanReed Thanks a lot, that made something click in my head. I'll try to figure this out now. Regarding the different covered solid angles: Sounds like the sin(...) factor required when integrating over stuff on a circle. I wonder if sin(angle between "forward vector" and pixel-eye vector) works? Feb 7, 2014 at 2:52