Computer Graphics: Difference between revisions
(41 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Basics of Computer Graphics | Basics of Computer Graphics | ||
==Homogeneous Coordinates== | |||
[http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/] | |||
Points and vectors are represented using homogeneous coordinates in computer graphics. | |||
This allows affine transformations in 3D (i.e. rotation and translation) to be represented as a matrix multiplication. | |||
While rotations can typically be represented in a 3x3 matrix multiplication, a translation requires a [[wikipedia:Shear mapping | ''shear'']] in 4D. | |||
Points are <math>(x,y,z,1)</math> and vectors are <math>(x,y,z,0)</math>. | |||
The last coordinate in points allow for translations to be represented as matrix multiplications. | |||
;Notes | |||
* The point <math>(kx, ky, kz, k)</math> is equivalent to <math>(x, y, z, 1)</math>. | |||
Affine transformations consist of translations, rotations, and scaling | |||
===Translation Matrix=== | |||
<math> | |||
T = | |||
\begin{bmatrix} | |||
1 & 0 & 0 & X\\ | |||
0 & 1 & 0 & Y\\ | |||
0 & 0 & 1 & Z\\ | |||
0 & 0 & 0 & 1 | |||
\end{bmatrix} | |||
</math> | |||
===Rotation Matrix=== | |||
Rotations can be about the X, Y, and Z axis.<br> | |||
Below is a rotation about the Z axis by angle <math>\theta</math>.<br> | |||
<math> | |||
R = \begin{bmatrix} | |||
\cos(\theta) & -\sin(\theta) & 0 & 0\\ | |||
\sin(\theta) & \cos(\theta) & 0 & 0\\ | |||
0 & 0 & 1 & 0\\ | |||
0 & 0 & 0 & 1 | |||
\end{bmatrix} | |||
</math> | |||
To formulate a rotation about a specific axis, we use [[Wikipedia:Rodrigues' rotation formula]].<br> | |||
Suppose we want to rotate by angle <math>\theta</math> around axis <math>\mathbf{k}=(k_x, k_y, k_z)</math>.<br> | |||
Let <math> | |||
\mathbf{K} = [\mathbf{k}]_{\times} = | |||
\begin{bmatrix} | |||
0 & -k_z & k_y\\ | |||
k_z & 0 & -k_x\\ | |||
-k_y & k_x & 0 | |||
\end{bmatrix}</math><br> | |||
Then the rotation matrix is <math>\mathbf{R} = \mathbf{I}_{3} + (\sin \theta)\mathbf{K} + (1 - \cos \theta)\mathbf{K}^2</math><br> | |||
Here the 4x4 form is: | |||
<math> | |||
R = \begin{bmatrix} | |||
\mathbf{R} & \mathbf{0}\\ | |||
\mathbf{0}^T & 1 | |||
\end{bmatrix} | |||
</math> | |||
===Scaling Matrix=== | |||
<math> | |||
S = \begin{bmatrix} | |||
X & 0 & 0 & 0\\ | |||
0 & Y & 0 & 0\\ | |||
0 & 0 & Z & 0\\ | |||
0 & 0 & 0 & 1 | |||
\end{bmatrix} | |||
</math> | |||
===Transformation matrix=== | |||
<math> | |||
L = T * R * S | |||
</math> | |||
Depending on implementation, it may be more memory-efficient or compute-efficient to represent affine transformations as their own class rather than 4x4 matrices. For example, a rotation can be represented with 3 floats in angle-axis or 4 floats in quaternion coordinates rather than a 3x3 rotation matrix. | |||
For example, see | |||
* [https://eigen.tuxfamily.org/dox/classEigen_1_1Transform.html Eigen::Transform] | |||
===Barycentric Coordinates=== | |||
==MVP Matrices== | ==MVP Matrices== | ||
To convert from model coordinates <math>v</math> to screen coordinates <math>w</math>, you do multiply by the MVP matrices <math>w=P*V*M*v</math> | To convert from model coordinates <math>v</math> to screen coordinates <math>w</math>, you do multiply by the MVP matrices <math>w=P*V*M*v</math> | ||
* The model matrix <math>M</math> applies the transform of your object. This includes the position and rotation. <math>M*v</math> is in world coordinates. | * The model matrix <math>M</math> applies the transform of your object. This includes the position and rotation. <math>M*v</math> is in world coordinates. | ||
* The view matrix <math>V</math> applies the transform of your camera. | * The view matrix <math>V</math> applies the inverse transform of your camera. <math>V*M*v</math> is in camera or view coordinates (i.e. coordinates relative to the camera). | ||
* The projection matrix <math>P</math> applies the projection of your camera, typically an orthographic or a perspective camera. The perspective camera shrinks objects in the distance. | * The projection matrix <math>P</math> applies the projection of your camera, typically an orthographic or a perspective camera. The perspective camera shrinks objects in the distance. | ||
===Model Matrix=== | |||
[https://gamedev.stackexchange.com/questions/16719/what-is-the-correct-order-to-multiply-scale-rotation-and-translation-matrices-f Order of matrices]<br> | |||
The model matrix is the product of the element's scale, rotation, and translation matrices.<br> | |||
<math>M = T * R * S</math> | |||
===View Matrix=== | ===View Matrix=== | ||
Line 11: | Line 95: | ||
[https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function Lookat function]<br> | [https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/lookat-function Lookat function]<br> | ||
The view matrix is a 4x4 matrix which encodes the position and rotation of the camera.<br> | The view matrix is a 4x4 matrix which encodes the position and rotation of the camera.<br> | ||
Given a camera at position <math>p</math> looking at target <math>t | Given a camera at position <math>\mathbf p</math> looking at target <math>\mathbf t</math> and up vector <math>\mathbf u</math>.<br> | ||
We can calculate the forward vector (from target to position) as <math>\mathbf{f}=\mathbf{p} - \mathbf{t}</math>.<br> | |||
We can calculate the right vector as <math>\mathbf u \times \mathbf f</math>.<br> | |||
Then the view matrix is written as: | |||
<pre> | <pre> | ||
r_x r_y r_z 0 | r_x r_y r_z 0 | ||
Line 30: | Line 116: | ||
} | } | ||
</pre> | </pre> | ||
===Perspective Projection Matrix=== | |||
[https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/building-basic-perspective-projection-matrix] | |||
https://www.songho.ca/opengl/gl_projectionmatrix.html | |||
The projection matrix applies a perspective projection based on the field of view of the camera. This is done dividing the x,y view coordinates by the z-coordinate so that further object appear closer to the center. Note that the output is typically in normalized device coordinates (NDC) <math>[-1, 1]\times[-1, 1]</math> rather than image coordinates <math>{0, ..., W-1} \times {0, ..., H-1}</math>. Additionally, in NDC, the y-coordinate typically points upwards unlike image coordinates. | |||
The Z-coordinate in the projection matrix represents a remapped version of the z-depth, i.e. depth along the camera forward axis. In OpenGL, this maps z=-f to 1 and z=-n to -1 where -z is forward. | |||
Notes: In computer vision, this is analogous to the calibration matrix <math>K</math>. | |||
It contains the intrinsic parameters of your pinhole camera such as field of view and focal length. The focal length determines the resolution of your output. | |||
===Inverting the projection=== | |||
If you have the depth (either z-depth or euclidean depth), you can invert the projection operation. | |||
The idea is to construct a ray from the camera to the pixel on a plane of the viewing frustrum and scale the distance accordingly. | |||
See [https://gamedev.stackexchange.com/questions/108856/fast-position-reconstruction-from-depth/111885#111885 stackexchange]. | |||
==Shading== | ==Shading== | ||
{{main | Wikipedia:Shading}} | {{main | Wikipedia:Shading}} | ||
===Flat | ===Interpolation=== | ||
=== | |||
=== | * Flat shading - color is computed for each face/triangle. | ||
* Gourard shading - color is computed for each vertex and interpolated. | |||
* Phong shading - color is computed for each pixel with the normal vector interpolated from each vertex. | |||
===Lambert reflectance=== | |||
{{main | Wikipedia: Lambertian reflectance}} | |||
This is a way to model diffuse (matte) materials. | |||
<math>I_D = (\mathbf{L} \cdot \mathbf{N}) * C * I_{L}</math> | |||
* <math>\mathbf{N}</math> is the normal vector. | |||
* <math>\mathbf{L}</math> is the vector to the light. | |||
* <math>C</math> is the color. | |||
* <math>I_{L}</math> is the intensity of light. | |||
===Phong reflection model=== | |||
{{main | Wikipedia: Phong reflection model}} | |||
See [https://www.scratchapixel.com/lessons/3d-basic-rendering/phong-shader-BRDF scratchapixel phong shader BRDF]. | |||
This is a way to model specular (shiny) materials. | |||
Here, the image is a linear combination of ambient, diffuse, and specular colors. | |||
If <math>\mathbf{N}</math> is the normal vector, <math>\mathbf{V}</math> is a vector from the vertex to the viewer, <math>\mathbf{L}</math> from the light to the vertex, and <math>\mathbf{R}</math> the incident vector (i.e. <math>\mathbf{L}</math> rotated 180 around <math>\mathbf{N}</math>) then | |||
* Ambient is a constant color for every pixel. | |||
* The diffuse coefficient is <math>\mathbf{N} \cdot \mathbf{L}</math>. | |||
* The specular coefficient is <math>(\mathbf{R} \cdot \mathbf{V})^n</math> where <math>n</math> is the ''shininess''. | |||
The final color is <math>k_{ambient} * ambientColor + k_{diffuse} * (\mathbf{N} \cdot \mathbf{L}) * diffuseColor + k_{specular} * (\mathbf{R} \cdot \mathbf{V})^n * specularColor</math>. | |||
;Notes | |||
* The diffuse and specular components need to be computed for every visible light source. | |||
===Physically Based=== | |||
See [https://static1.squarespace.com/static/58586fa5ebbd1a60e7d76d3e/t/593a3afa46c3c4a376d779f6/1496988449807/s2012_pbs_disney_brdf_notes_v2.pdf pbs disney brdf notes] and the [http://www.pbr-book.org/ pbr-book] | |||
In frameworks and libraries, these are often refered to as ''standard materials'' or in Blender, ''Principled BSDF''. | |||
==Blending and Pixel Formats== | |||
===Pixel Formats=== | |||
===Blending=== | |||
To output transparent images, i.e. images with alpha, you'll generally want to blend using [[Premultiplied Alpha]]. Rendering in premultiplied alpha prevents your RGB color values from getting mixed with the background color empty pixels. | |||
===Rendering=== | |||
For rasterization, the render loop typically consists of: | |||
# Render the shadow map. | |||
# Render all opaque objects front-to-back. | |||
## Opaque objects write to the depth buffer. | |||
# Render all transparent objects back-to-front | |||
## Transparent objects do not write to the depth buffer. | |||
Rendering opaque objects front to back minimizes overdraw, where a pixel gets drawn to multiple times in a single frame. | |||
Rendering transparent objects back to front is needed for proper blending of transparent materials. | |||
==Anti-aliasing== | |||
For a high-quality anti-aliasing, you'll generally want to multiple multi-sampling (MSAA). | |||
This causes the GPU to render the depth buffer at a higher resolution to determine the contribution of your fragment shader's color to the final image. | |||
See https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing#:~:text=How%20MSAA%20really%20works%20is,buffer%20to%20determine%20subsample%20coverage for more details. | |||
==More Terms== | |||
* [[Wikipedia: Diffuse reflection | Diffuse reflection]] - reflection scattered in many directions (i.e. matte) | |||
* [[Wikipedia: Specular reflection | Specular reflection]] - mirror reflection | |||
* [[Wikipedia: Refraction | Refraction]] - change in direction of light as it passes through a material | |||
==Resources== | ==Resources== | ||
* [https://www.udacity.com/course/interactive-3d-graphics--cs291 Udacity Interactive 3D Graphics] | * [https://www.udacity.com/course/interactive-3d-graphics--cs291 Udacity Interactive 3D Graphics] |