First of all a small introduction about the matrices you need.
- viewMatrix: This matrix is a 4x4 matrix which stores the position and orientation of your camera with respect to the world origin. Multiplying a vector 4D to this matrix transforms this point with respect to your camera coordinate / orientation. So it is a basis change from world coordinate system to camera coordinate system.
- projectionMatrix: This matrix is a 4x4 matrix which stores the projection aspect of your camera. There are multiple projection types which I don't want to go into detail... you are interested in
perspective projection
. So your camera has a frustum formed like a truncated pyramid.The tip of the pyramid is inside your camera. The foot of the pyramid is where you look to. Everything within the pyramid is visible, everything outside the pyramid is NOT visible. Information like field of view``aspect ratio``near clipping plane
and far clipping plane
is encoded into that matrix. As long as these parameters don't change, you can reuse this matrix.
- modelMatrix: This matrix is a 4x4 matrix which stores information about the position, scaling, sheering and orientation of your model. So when having a model with tons of vertices, you don't need to move all vertices around. This matrix is doing it for you. When multiplying a vertex to this matrix, it will be transformed to world space.
When having a point (vertex) in 3D space, you can store it as a 4D vector by adding the number (1) to the 4th dimension. Like this: vector4d(positionX, positionY, positionZ, 1)
. This is called the homogeneous coordinate
As you noticed, we have 4x4 matrices and a 4 component vector. So we can multiply them to receive another 4D vector. You can do it this way:
$vertexWorldSpace = modelMatrix * vertex4D$ this transforms your vertex from model space to world space.
$vertexViewSpace = viewMatrix * vertexWorldSpace$ This transforms your vertex from world coordinate space to view space.
$vertexScreenSpace = projectionMatrix * vertexViewSpace$ This transforms your view space coordinate to a screen space coordinate.
usually you have to divide the result by its 4th component, but OpenGL and direct3D is doing this for you when passing the position from vertex to pixel/fragment shader.
Now you can write this multiplications into one equation:
$vertexScreenSpace = projectionMatrix * viewMatrix * modelMatrix * vertex4D$
And of cause all matrices can be combined to one matrix
$modelViewProjectionMatrix = projectionMatrix * viewMatrix * modelMatrix$
This modelViewProjectionMatrix can be loaded to the GPU and each vertex within that model can be multiplied by this matrix to receive the screen coordinate.
$vertexScreenSpace = modelViewProjectionMatrix * vertex4D$
Which matrices will change over time?
- As long as your camera parameters don't change, the projection matrix will not change. Camera position and orientation are NOT stored inside the projection matrix! But there is a near and a far clipping plane which is stored inside the projection matrix. everything in front of the near clipping plane and everything behind the far clipping plane will be clipped! So it is NOT visible. Have that in mind.
- The viewMatrix will only change, when moving or rotating the camera.
- The modelMatrix will change, when moving, rotating, scaling or
sheering the model.
Matrix multiplications should be avoided as mush as you can on GPU. That means, do not move all these matrices to the GPU to multiply them there...
You can do the multiplication on CPU to receive the modelViewProjectionMatrix. Then store this matrix to the GPU to do only one matrix multiplication per vertex. Rule of thump: Combine the parts of the matrices to one matrix which will be equal to all vertices in the render call. Have in mind: Matrix multiplications are NOT cummutative. So A * B is not B * A!
There is a very nice OpenGL tutorial about the matrix calculus in computer graphics OpenGL matrix tutorial. Be aware, that direct3D and vulkan uses different coordinates... So in case of using direct3D or vulkan please use another tutorial. But in principle it works the same way.
In your case the compute shader should calculate each stars new position(world space). Afterwards you can render the result by using vertex shader to apply the modelViewProjectionMatrix and pixel/fragment shader to color the result.
gl_PointSize
which can be used to enlarge the star with respect to the z-position (distance to camera) $\endgroup$