This commit is contained in:
Miloslav Ciz 2022-06-27 15:49:38 +02:00
parent 01be9b8af5
commit c856794e38
4 changed files with 54 additions and 13 deletions

41
3D_rendering.md Normal file
View file

@ -0,0 +1,41 @@
# 3D Rendering
In [computer graphics](graphics.md) 3D rendering is concerned with computing images that represent a projected view of 3D objects through a virtual camera. There are many methods and [algorithms](algorithm.md) for doing so differing in many aspects such as computation complexity, implementation complexity, realism of the result, representation of the 3D data, limitations of viewing and so on.
A table of some common rendering methods, including the most simple and most advanced ones, follows. Note that here we talk about methods rather than algorithms, i.e. general approaches that are often modified and combined into a specific rendering algorithm. The table should help you craft an ideal 3D rendering algorithm for your program.
The methods may be tagged with the following:
- *2.5D*: primitive 3D, often called [pseudo 3D](pseudo_3d.md) or fake 3D, having significant limitations e.g. in degrees of freedom of the camera
- *off*: slow method usually used for offline (non-realtime) rendering (even though they indeed may run in real time e.g. with the help of powerful GPUs)
- *IO* vs *OO*: [image order](image_order.md) (rendering by pixels) vs [object order](object_order.md) (rendering by objects)
| method | notes |
|------------------------------------------|------------------------------------|
|[3D raycasting](raycasting.md) |*IO off*, shoots rays from camera |
|[2D raycasting](raycasting.md) |*IO 2.5D*, e.g. [Wolf3D](wolf3D.md) |
|[beamtracing](beamtracing.md) |*IO off* |
|[billboarding](billboard.md) |*OO* |
|[BSP rendering](bsp.md) |*2.5D*, e.g. [Doom](doom.md) |
|[conetracing](conetracing.md) |*IO off* |
|"[dungeon crawler](dungeon_crawler.md)" |*OO 2.5D*, e.g. Eye of the Beholder |
|ellipsoid rasterization |*OO*, e.g. Ecstatica |
|flat-shaded 1 point perspective |*OO 2.5D*, e.g. Skyroads |
|[image based rendering](ibr.md) | |
|[mode 7](mode7.md) |*IO 2.5D*, e.g. F-Zero |
|[parallax scrolling](parallax.md) |*2.5D*, very primitive |
|[pathtracing](pathtracing.md) |*IO off*, Monte Carlo, high realism |
|[portal rendering](portal_rendering.md) |*2.5D*, e.g. [Duke3D](duke3d.md) |
|prerendered view angles |*2.5D* |
|[raymarching](raymaching.md) |*IO off* |
|[raytracing](raytracing.md) |*IO off*, recursive raycasting |
|segmented road |*OO 2.5D*, e.g. Outrun |
|[shear warp rednering](shear_warp.md) |*IO*, volumetric |
|[splatting](splatting.md) |*OO*, rendering with 2D blobs |
|[triangle rasterization](rasterization.md)|*OO*, traditional in GPUs |
|[voxel space rendering](voxel_space.md) |*OO 2.5D*, e.g. Comanche |
|[wireframe rendering](wireframe.md) |*OO*, just lines |
TODO: find out how build engine/slab6 voxel rendering worked and possibly add it here (from http://advsys.net/ken/voxlap.htm seems to be based on raycasting)
TODO: VoxelQuest has some innovative voxel rendering, check it out (https://www.voxelquest.com/news/how-does-voxel-quest-work-now-august-2015-update)

View file

@ -223,6 +223,7 @@ Here is a list of some acronyms:
- **[MR](mr.md)** (merge request) - **[MR](mr.md)** (merge request)
- **[MS/M$](ms.md)** (Micro$oft) - **[MS/M$](ms.md)** (Micro$oft)
- **[MSB](msb.md)** (most significant bit) - **[MSB](msb.md)** (most significant bit)
- **[MSC](msc.md)** (master of science)
- **[MSG](msg.md)** (message) - **[MSG](msg.md)** (message)
- **[MUD](mud.mf)** (multi user dungeon) - **[MUD](mud.mf)** (multi user dungeon)
- **[NAN](nan.md)** (not a number) - **[NAN](nan.md)** (not a number)
@ -259,6 +260,7 @@ Here is a list of some acronyms:
- **[PR](pr.md)** (pull request) - **[PR](pr.md)** (pull request)
- **[PS](ps.md)** ([Photoshop](photoshop.md), [Postscript](postscript.md), [PlayStation](playstation.md)) - **[PS](ps.md)** ([Photoshop](photoshop.md), [Postscript](postscript.md), [PlayStation](playstation.md))
- **[PS2](ps2.md)** (personal system 2) - **[PS2](ps2.md)** (personal system 2)
- **[PTHC](pthc.md)** (preteen hardcore)
- **[QOS](qos.md)** (quality of service) - **[QOS](qos.md)** (quality of service)
- **[RAID](raid.md)** (redundant array of inexpensive discs) - **[RAID](raid.md)** (redundant array of inexpensive discs)
- **[RAM](ram.md)** (random access [memory](memory.md)) - **[RAM](ram.md)** (random access [memory](memory.md))

View file

@ -2,9 +2,9 @@
*"[Micro$oft](microsoft.md) <3 open source"* *"[Micro$oft](microsoft.md) <3 open source"*
Open source (OS) is a [capitalist](capitalist_software.md) movement forked from the [free software movement](free_software.md); it is advocating "openness", sharing and collaboration in software and hardware development and though legally it is mostly identical to free (as in freedom) software, in spirit it is very different by **abandoning the goal of freedom and ethics in favor of business**, due to which we see open source as inherently evil and recommend following free software instead. [Richard Stallman](rms.md), the founder of free software, distances himself from the open source movement. The term [FOSS](foss.md) is sometimes used to refer to both free software and open source without expressing any preference. Open source (OS) is a [capitalist](capitalist_software.md) movement forked from the [free software movement](free_software.md); it is advocating "openness", sharing and collaboration in software and hardware development and though legally it is mostly identical to free (as in freedom) software, in practice and in spirit it is very different by **abandoning the goal of freedom and ethics in favor of business** (to which ethics is an obstacle), due to which we see open source as inherently [evil](evil.md) and recommend following free software way instead. [Richard Stallman](rms.md), the founder of free software, distances himself from the open source movement. Fascist organizations such as Microsoft and Google, on the other hand, embrace open source (while restraining from using the term *free software*) and slowly shape it towards their goals. The term [FOSS](foss.md) is sometimes used to refer to both free software and open source without expressing any preference.
Open source is becoming more prevalent than free software, as it better serves [capitalism](capitalism.md) and abuse of people, and its followers are more and more hostile towards the free software movement. This is very dangerous, ethics and focus on actual user freedom is replaced by shallow legal definitions that can be bypassed, e.g. by [capitalist software](capitalist_software.md) and [bloat monopoly](bloat_monopoly.md). In a way open source is capitalism reshaping free software so as to weaken it and eventually make its principles of freedom ineffective. In practice open source has become something akin a **brand** which is stick to a piece of software to give users with little insight a feeling they're buying into something good -- this is called **[openwashing](openwashing.md)**. This claim is greatly supported by the fact that corporations such as [Microsoft](microsoft.md) and [Google](google.md) widely embrace open source ("Microsoft <3 open source" and the infamous [GitHub](github.md) acquisition). Open source is unfortunately (but unsurprisingly) becoming more prevalent than free software, as it better serves [capitalism](capitalism.md) and abuse of people, and its followers are more and more hostile towards the free software movement. This is very dangerous, ethics and focus on actual user freedom is replaced by shallow legal definitions that can be bypassed, e.g. by [capitalist software](capitalist_software.md) and [bloat monopoly](bloat_monopoly.md). In a way open source is capitalism reshaping free software so as to weaken it and eventually make its principles of freedom ineffective. Open source tries to shift the goal posts: more and more it offers only an illusion of some kind of ethics and/or freedom, it pushes towards mere partial openness ("open source" for proprietary platforms), towards high complexity, inclusion of unethical business-centered features ([autoupdates](autoupdate.md), [DRM](drm.md), ...), high interdependency, difficulty of utilizing the rights granted by the license, exclusion of developers with "incorrect" political opinions or bad brand image etc. In practice open source has become something akin a mere **brand** which is stick to a piece of software to give users with little insight a feeling they're buying into something good -- this is called **[openwashing](openwashing.md)**. This claim is greatly supported by the fact that corporations such as [Microsoft](microsoft.md) and [Google](google.md) widely embrace open source ("Microsoft <3 open source", the infamous [GitHub](github.md) acquisition etc.).
One great difference of open source with respect to free software is that **open source doesn't mind proprietary dependencies**: [Windows](windows.md) only programs or [games](game.md) in [proprietary](proprietary.md) engines such as [Unity](unity.md) are happily called open source -- this would be impossible in the context of free software because as Richard Stallman says software can only be free if it is free as a whole, it takes a single proprietary line of code to allow abuse of the user. One great difference of open source with respect to free software is that **open source doesn't mind proprietary dependencies**: [Windows](windows.md) only programs or [games](game.md) in [proprietary](proprietary.md) engines such as [Unity](unity.md) are happily called open source -- this would be impossible in the context of free software because as Richard Stallman says software can only be free if it is free as a whole, it takes a single proprietary line of code to allow abuse of the user.

View file

@ -56,23 +56,21 @@ The classic version of 2D raycasting -- as seen in the early 90s games -- only r
The core element to implement is the code for casting rays, i.e. given the square plan of the environment (e.g. game level), in which each square is either empty or a wall (which can possibly be of different types, to allow e.g. different textures), we want to write a function that for any ray (defined by its start position and direction) returns the information about the first wall it hits. This information most importantly includes the distance of the hit, but can also include additional things such as the type of the wall, texturing coordinate or its direction (so that we can [shade](shading.md) differently facing walls with different brightness for better realism). The environment is normally represented as a 2 dimensional [array](array.md), but instead of explicit data we can also use e.g. a function that [procedurally](procgen.md) generates infinite levels (i.e. we have a function that for given square coordinates computes what kind of square it is). As for the algorithm for tracing the ray in the grid we may actually use some kind of line [rasterization](rasterization.md) algorithm, e.g. the **[DDA](dda.md) algorithm** (tracing a line through a grid is analogous to drawing a line in a pixel grid). This can all be implemented with [fixed point](fixed_point.md), i.e. integer only! No need for [floating point](float.md). The core element to implement is the code for casting rays, i.e. given the square plan of the environment (e.g. game level), in which each square is either empty or a wall (which can possibly be of different types, to allow e.g. different textures), we want to write a function that for any ray (defined by its start position and direction) returns the information about the first wall it hits. This information most importantly includes the distance of the hit, but can also include additional things such as the type of the wall, texturing coordinate or its direction (so that we can [shade](shading.md) differently facing walls with different brightness for better realism). The environment is normally represented as a 2 dimensional [array](array.md), but instead of explicit data we can also use e.g. a function that [procedurally](procgen.md) generates infinite levels (i.e. we have a function that for given square coordinates computes what kind of square it is). As for the algorithm for tracing the ray in the grid we may actually use some kind of line [rasterization](rasterization.md) algorithm, e.g. the **[DDA](dda.md) algorithm** (tracing a line through a grid is analogous to drawing a line in a pixel grid). This can all be implemented with [fixed point](fixed_point.md), i.e. integer only! No need for [floating point](float.md).
**Note on distance calculation and distortion**: When computing the distance of ray hit from the camera, we usually DO NOT want to use the [Euclidean](euclidean.md) distance of that point from the camera position (as is tempting) -- that would create a so called fish eye effect, i.e. looking straight into a perpendicular wall would make the wall looked warped/bowled (as the part of the wall in the middle of the screen is actually closer to the camera position so it would, by perspective, look bigger). For non-distorted rendering we have to compute the perpendicular distance of the hit point from the camera plane -- we can see the camera plane as a "canvas" onto which we project the scene, in 2D it is a line (unlike in 3D where it really is a plane) in front of the camera at a constant distance (usually conveniently chosen to be 1) from the camera position whose direction is perpendicular to the direction the camera is facing. The good news is that with a little trick this distance can be computed even more efficiently than Euclidean distance, as we don't need to compute a square root! Instead we can utilize the similarity of triangles. Consider the following situation: **Note on distance calculation and distortion**: When computing the distance of ray hit from the camera, we usually DO NOT want to use the [Euclidean](euclidean.md) distance of that point from the camera position (as is tempting) -- that would create a so called fish eye effect, i.e. looking straight into a perpendicular wall would make the wall look warped/bowled (as the part of the wall in the middle of the screen is actually closer to the camera position so it would, by perspective, look bigger). For non-distorted rendering we have to compute a distance that's perpendicular to the camera plane -- we can see the camera plane as a "canvas" onto which we project the scene, in 2D it is a line (unlike in 3D where it really is a plane) at a certain distance from the camera (usually conveniently chosen to be e.g. 1) whose direction is perpendicular to the direction the camera is facing. The good news is that with a little trick this distance can be computed even more efficiently than Euclidean distance, as we don't need to compute a square root! Instead we can utilize the similarity of triangles. Consider the following situation:
``` ```
d I-_
/ .x / '-X
/ r.'/| / r.'/|
'-._ / ,' / | '-._ / ,' / |
P '-c_.' / | p '-C_.' / |
/,'|-.e | 1/,'|-./ |
/' | | /' | / |
V----a------b V-._-A/-----B
'J
``` ```
In the above *V* is the position of the camera (viewer) which is facing towards the point *d*, *P* is the camera plane perpendicular to *Vd* at the distance 1 from *V*. Ray *r* is cast from the camera and hits the point *x*. The length of the line *r* is the Euclidean distance, however we want to find out the distance *ex = cd*, which is perpendicular to *P*. There are two similar triangles: *Vca* and *Vdb*; from this it follows that *1 / Va = (1 + cd) / Vb*, from which we derive that *cd = Vb / Va - 1*. This can be used to calculate the perpendicular distance just from the ratio of the distances along principal axes (i.e. along axis X or Y). However watch out for the case when *Va = Vb = 0* to not divide by zero! In such case use the other principal axis (Y). In the above *V* is the position of the camera (viewer) which is facing towards the point *I*, *p* is the camera plane perpendicular to *VI* at the distance 1 from *V*. Ray *r* is cast from the camera and hits the point *X*. The length of the line *r* is the Euclidean distance, however we want to find out the distance *JX = VI*, which is perpendicular to *p*. There are two similar triangles: *VCA* and *VIB*; from this it follows that *1 / VA = VI / VB*, from which we derive that *JX = VB / VA*. We can therefore calculate the perpendicular distance just from the ratio of the distances along one principal axis (X or Y). However watch out for the case when *VA = VB = 0* to not divide by zero! In such case use the other principal axis (Y).
{ I hope the above is correct lol. ~drummyfish}
TODO: code TODO: code