master
Miloslav Ciz 2 years ago
parent 3812818f01
commit e6348633fe

@ -1,44 +0,0 @@
# 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 follows, including the most simple, most advanced and some unconventional ones. Note that here we talk about methods and techniques rather than algorithms, i.e. general approaches that are often modified and combined into a specific rendering algorithm. For example the traditional triangle rasterization is sometimes combined with raytracing to add e.g. realistic reflections. The methods may also be further enriched with features such as [texturing](texture.md), [antialiasing](antialiasing.md) and so on. The table below should help you choose the base 3D rendering method for your specific 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 |
|reverse raytracing (photon tracing) |*OO off*, inefficient |
|[image based rendering](ibr.md) |generating inbetween views |
|[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*, e.g. Iridion II (GBA) |
|[raymarching](raymaching.md) |*IO off*, e.g. with [SDFs](sdf.md) |
|[raytracing](raytracing.md) |*IO off*, recursive 3D 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: Rescue On Fractalus!
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)

@ -0,0 +1,68 @@
# 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. If you are just interested in the [realtime](realtime.md) 3D rendering used in [gaymes](game.md) nowadays, you are probably interested in [GPU](gpu.md)-accelerated 3D [rasterization](rasterization.md) with [APIs](api.md) such as [OpenGL](opengl.md) and [Vulkan](vulkan.md).
## Methods
A table of some common 3D rendering methods follows, including the most simple, most advanced and some unconventional ones. Note that here we talk about methods and techniques rather than algorithms, i.e. general approaches that are often modified and combined into a specific rendering algorithm. For example the traditional triangle rasterization is sometimes combined with raytracing to add e.g. realistic reflections. The methods may also be further enriched with features such as [texturing](texture.md), [antialiasing](antialiasing.md) and so on. The table below should help you choose the base 3D rendering method for your specific 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 |
|reverse raytracing (photon tracing) |*OO off*, inefficient |
|[image based rendering](ibr.md) |generating inbetween views |
|[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*, e.g. Iridion II (GBA) |
|[raymarching](raymaching.md) |*IO off*, e.g. with [SDFs](sdf.md) |
|[raytracing](raytracing.md) |*IO off*, recursive 3D 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: Rescue On Fractalus!
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)
## Mainstream Realtime 3D
You may have come here just to learn about the typical realtime 3D rendering used in today's [games](game.md) because aside from research and niche areas this kind of 3D is what we normally deal with in practice. This is what this section is about.
Nowadays this kind of 3D stands for a [GPU](gpu.md) accelerated 3D [rasterization](rasterization.md) done with rendering APIs such as [OpenGL](opengl.md), [Vulkan](vulkan.md), [Direct3D](d3d.md) or [Metal](metal.md) (the last two being [proprietary](proprietary.md) and therefore [shit](shit.md)) and higher level engines above them, e.g. [Godot](godot.md), [OpenSceneGraph](osg.md) etc.
This mainstream rendering uses an [object order](object_order.md) approach (it blits 3D objects onto the screen rather than determining each pixel's color separately) and works on the principle of **triangle rasterization**, i.e. 3D models are composed of triangles (or higher polygons which are however eventually broken down into triangles) and these triangles are projected onto the screen according to the position of the virtual camera and laws of [perspective](perspective.md). Projecting the triangles means finding the 2D screen coordinates of each of the triangle's three vertices -- once we have thee coordinates, we draw (rasterize) the triangle to the screen just as a "normal" 2D triangle (well, with some asterisks).
Furthermore things such as [z-buffering](z_buffer.md) (for determining correct overlap of triangles) and [double buffering](double_buffering.md) are used, which makes this approach very memory ([RAM](ram.md)/[VRAM](vram.md)) expensive -- of course mainstream computers have more than enough memory but smaller computers (e.g. [embedded](embedded.md)) may suffer and be unable to handle this kind of rendering. Thankfully it is possible to adapt and imitate this kind of rendering even on "small" computers -- even those that don't have a GPU, i.e. with pure [software rendering](sw_rendering.md). For this we e.g. replace z-buffering with [painter's algorithm](painters_algorithm.md) (triangle sorting), drop features like [perspective correction](perspective_correction.md), [MIP mapping](mip_mapping.md) etc. (of course quality of the output will go down).
On PCs the whole rendering process is hardware-accelerated with a [GPU](gpu.md) (graphics card). GPU is a special hardware capable of performing many operations in [parallel](parallelism.md) (as opposed to a [CPU](cpu.md) which mostly computes sequentially with low level of parallelism) -- this is great for graphics because we can for example perform mapping and drawing of many triangles at once, greatly increasing the speed of rendering ([FPS](fps.md)). However this hugely increases the [complexity](complexity.md) of the whole rendering system, we have to have a special [API](api.md) and [drivers](driver.md) for communication with the GPU and we have to upload data (3D models, textures, ...) to the GPU before we want to render them. [Debugging](debugging.md) gets a lot more difficult.
GPU nowadays are kind of general devices that can be used for more than just 3D rendering (e.g. [crypto](crypto.md) mining) and can no longer perform 3D rendering by themselves -- for this they have to be programmed. I.e. if we want to use a GPU for rendering, not only do we need a GPU but also some extra code. This code is provided by "systems" such as [OpenGL](opengl.md) or [Vulkan](vulkan.md) which consist of an [API](api.md) (an [interface](interface.md) we use from a [programming language](programming_language.md)) and the underlying implementation in a form of a [driver](driver.md). Any such rendering system has its own architecture and details of how it works, so we have to study it a bit if we want to use it.
The important part of a system such as OpenGL is its **rendering [pipeline](pipeline.md)**. Pipeline is the "path" through which data go through the rendering process. Each rendering system and even potentially each of its version may have a slightly different pipeline (but generally all mainstream pipelines somehow achieve rasterizing triangles, the difference is in details of how they achieve it). The pipeline consists of **stages** that follow one after another (e.g. the mentioned mapping of vertices and drawing of triangles constitute separate stages). A very important fact is that some (not all) of these stages are programmable with so called **[shaders](shader.md)**. A shader is a program written in a special language (e.g. [GLSL](glsl.md) for OpenGL) running on the GPU that processes the data in some stage of the pipeline (therefore we distinguish different types of shaders based on at which part of the pipeline they reside). In early GPUs stages were not programmable but they became so as to give a greater flexibility -- shaders allow us to implement all kinds of effects that would otherwise be impossible.
Let's see a typical pipeline, similar to something we might see e.g. in OpenGL (we simulate this also in [software renderers](sw_rendering.md)):
TODO

@ -2,4 +2,4 @@
Blender is an "[open-source](open_source.md)" 3D modeling and [rendering](rendering.md) [software](software.md) -- one of the most powerful and "feature-rich" ones, even compared to [proprietary](proprietary.md) competition -- used not only by the [FOSS](foss.md) community, but also the industry (commercial [games](game.md), movies etc.), which is an impressive achievement in itself, however Blender is also a [capitalist](capitalist.md) software suffering from many not-so-nice features such as [bloat](bloat.md).
After version 2.76 Blender started requiring [OpenGL](opengl.md) 2.1 due to its "[modern](modern.md)" EEVEE renderer, deprecating old machines and giving a huge fuck you to all users with incompatible hardware (for example the users of [RYF](ryf.md) software). This new version also stopped working with the [free](free_software.md) [Nouveau](nouvea.md) driver, forcing the users to use NVidia's proprietary drivers. Blender of course doesn't at all care about this.
After version 2.76 Blender started REQUIRING [OpenGL](opengl.md) 2.1 due to its "[modern](modern.md)" [EEVEE](eevee.md) renderer, deprecating old machines and giving a huge fuck you to all users with incompatible hardware (for example the users of [RYF](ryf.md) software). This new version also stopped working with the [free](free_software.md) [Nouveau](nouvea.md) driver, forcing the users to use NVidia's proprietary drivers. Blender of course doesn't at all care about this. { I've been forced to use the extremely low FPS [software](sw_rendering.md) GL version of Blender after 2.8. ~drummyfish }

@ -2,8 +2,8 @@
Left and right are two basic opposing political sides that roughly come down to the pro-equality (left) and pro-hierarchy (right). There is a lot of confusion and vagueness about these terms, so let us now define them as used on this wiki:
- The (true) **left is pro social equality**, i.e. against social hierarchies. This includes equality of all living beings, period. Note that social equality does NOT imply people being made (or being made to appear) equal in other ways, e.g. physically -- true left accepts difference between people and [races](race.md) and doesn't hide them. Even if the perfectly ideally leftist society can't be completely achieved, true left tries to get **as close to it as possible**. The values of true left are for example sharing, [love](love.md), [selflessness](selflessness.md), [altruism](altruism.md), forgiveness and nonviolence. Groups and movements that are at least highly truly leftist include [anarcho pacifism](anpac.md), [free software](free_software.md), [free culture](free_culture.md) and of course [LRS](lrs.md).
- The **right is pro social hierarchy**, i.e. against social equality. This means some people standing above others, be it by strength, power, wealth, social status, privileges etc. The rightist values are mostly those associated with [evil](evil.md), i.e. violence, oppression, conflict, war, revenge, survival of the fittest etc. Among rightism can be included [fascism](fascism.md), [capitalism](capitalism.md), US republican party, states, the military etc.
- The (true) **left is pro social equality**, i.e. against social hierarchies. This includes equality of all living beings, period. Note that social equality does NOT imply people being made (or being made to appear) equal in other ways, e.g. physically -- true left accepts difference between people and [races](race.md) and doesn't hide them. Even if the perfectly ideally leftist society can't be completely achieved, true left tries to get **as close to it as possible**. The values of true left are for example sharing, [love](love.md), [selflessness](selflessness.md), [altruism](altruism.md), forgiveness and nonviolence. Groups and movements that are at least highly truly leftist include [anarcho pacifism](anpac.md), [veganism](veganism.md), [free software](free_software.md), [free culture](free_culture.md) and of course [LRS](lrs.md).
- The **right is pro social hierarchy**, i.e. against social equality. This means some people standing above others, be it by strength, power, wealth, social status, privileges etc. The rightist values are mostly those associated with [evil](evil.md), i.e. violence, oppression, conflict, war, revenge, survival of the fittest etc. Among rightism can be included [fascism](fascism.md) (i.e. extreme rightism), [capitalism](capitalism.md), US republican party, states, the military etc. One of right's identifying features is **hypocrisy**, i.e. it judges what's good/bad only by against whom it is targeted, e.g. violence is bad when targeted against "us" ("those Muslims are bad, they want to kill us!") but good when targeted against "them" ("we have to kill those Muslims because they're violent!"); so animals killing humans is judged as "bad" but humans killing animals is "good". In other words right has no sense of morality, only the sense of [self interest](self_interest.md).
- The **pseudoleft** is pretending to be left while in fact being right due to e.g. using non-leftist means (such as violence) or even having non-leftist goals (e.g. benefit of specific minority as opposed to benefit of everyone). Among pseudoleftist movements are [feminism](feminism.md), [LGBT](lgbt.md), [Antifa](antifa.md) or [Marxism](marxism.md). This fact is also supported by the [naming](name_matters.md) of these movements.
There exists a "theory" called a horse shoe. It says that the extremes of the left-right spectrum tend to be alike (violent, hating, radical), just as the two ends of a horse shoe. This is only an illusion caused by ignoring the existence of pseudoleft. The following diagram shows the true situation:

@ -2,7 +2,7 @@
*"I invented the term 'object oriented' and [C++](cpp.md) was not what I had in mind"* --[Alan Kay](alan_kay.md), inventor of OOP
Object-oriented programming (OOP, also object-obsessed programming) is a [programming paradigm](paradigm.md) that tries to model reality as a collection of abstract objects that communicate with each other and obey some specific rules. While the idea itself isn't bad and can be useful in certain cases, OOP has become extremely overused, extremely badly implemented and downright forced in programming languages which apply this [abstraction](abstraction.md) to every single program and concept, creating [anti-patterns](anti_pattern.md), unnecessary issues and of course [bloat](bloat.md). We therefore see OOP as a [cancer](cancer.md) of software development.
Object-oriented programming (OOP, also object-obsessed programming) is a [programming paradigm](paradigm.md) that tries to model reality as a collection of abstract objects that communicate with each other and obey some specific rules. While the idea itself isn't bad and can be useful in certain cases, **OOP has become extremely overused, extremely badly implemented and downright forced in programming languages** which apply this [abstraction](abstraction.md) to every single program and concept, creating [anti-patterns](anti_pattern.md), unnecessary issues and of course [bloat](bloat.md). We therefore see OOP as a **[cancer](cancer.md) of software development**.
Ugly examples of OOP gone bad include [Java](java.md) and [C++](cpp.md) (which at least doesn't force it). Other languages such as [Python](python.md) and [Javascript](javascript.md) include OOP but have lightened it up a bit and at least allow you to avoid using it.
@ -24,8 +24,8 @@ OOP furthermore comes with some basic principles such as:
## Why It's Shit
- OOP is just a bad abstraction for many problems that by their nature aren't object-oriented. OOP is not a [silver bullet](silver_bullet.md), yet it tries to behave as one. **The greatest issue of OOP is that it's trying to solve everything**. You may ask what else to use then? See the section below.
- For simple programs (which most programs should be) OOP is an unnecessarily high and overly complex abstraction.
- OOP is just a bad abstraction for many problems that by their nature aren't object-oriented. OOP is not a [silver bullet](silver_bullet.md), yet it tries to behave as one.
- Great number of the supposed "features" and design-patterns (setters/getters, singletons, inheritance, ...) turned out to actually be anti-patterns and burdens.
- OOP as any higher abstraction very often comes with overhead, memory footprint and performance loss ([bloat](bloat.md)) as well as more complex [compilers](compiler.md) and language specifications.
- The relatively elegant idea of pure OOP didn't catch up and the practically used OOP languages are abomination hybrids of imperative and OOP paradigms that just take more head space, create friction and unnecessary issues to solve. Sane languages now allow the choice to use OOP fully, partially or avoid it completely, which leads to a two-in-one overcomplication.
@ -36,4 +36,21 @@ OOP furthermore comes with some basic principles such as:
- If you want to program in object-oriented way and have a good justification for it, **you don't need an OOP language anyway**, you can emulate all aspects of OOP in simple languages like C. So instead of building the idea into the language itself and dragging it along forever and everywhere, it would be better to have optional OOP libraries.
- It generalizes and simplifies programming into a few rules of thumb such as encapsulation, again for the sake of inexperienced noobs. However there are no simple rules for how to program well, good programming requires a huge amount of experience and as in any art, good programmer knows when breaking the general rules is good. OOP doesn't let good programmers do this, it preaches things like "global variables bad" which is just too oversimplified and hurts good programming.
## But Which Paradigm To Use Instead Of OOP?
After many people realized OOP is kind of shit, there has been a boom of "OOP alternatives" such as [functional](functional.md), [traits](traits.md), [agent oriented programming](agent_oriented_programming.md), all kinds of "lightweight" OOP etc etc. Which one to use?
In short: NONE, **by default use the [imperative](imperative.md) paradigm** (also called "procedural"). Remember this isn't to say you shouldn't ever apply a different paradigm, but imperative should be the default, most prevalent and suitable one to use in solving most problems. There is nothing new to invent or "beat" OOP.
But why imperative? Why can't we simply improve OOP or come up with something ultra genius to replace it with? Why do you say OOP is bad because it's forced and now you are forcing imperative paradigm? The answer is that the **imperative paradigm is special because it is how computers actually work**, it is not made up but rather it's the **natural low level paradigm with minimum [abstraction](abstraction.md) that reflects the underlying nature of computers**. This makes it special among all other paradigms because:
- Its implementation is simple and [suckless](suckless.md)/[LRS](lrs.md) because it maps nicely and naturally to the underlying hardware -- basically commands in a language simply translate to one or more instructions. This makes construction of compilers easy.
- It's predictable and efficient, i.e. a programmer writing imperative code can see quite clearly how what he's writing will translate to the assembly instructions. This makes it possible to write highly efficient code, unlike high level paradigms that perform huge amounts of [magic](magic.md) for translating foreign concepts to machine instructions -- and of course this magic may differ between compilers, i.e. what's efficient code in one compiler may be inefficient in another (similar situation arose e.g. in the world of [OpenGL](opengl.md) where driver implementation started to play a huge role and which led to the creation of a more low level API [Vulkan](vulkan.md)).
- It doesn't force high amounts of unnecessary high level abstraction. This means we MAY use any abstraction, even OOP, if we currently need it, e.g. via a [library](library.md), but we aren't FORCED to use a weird high level concepts on problems that can't be described easily in terms of those concepts. That is if you're solving a non-OOP problem with OOP, you waste effort on translating that problem to OOP and the compiler then wastes another effort on un-OOPing this to translate this to instructions. With imperative paradigm this can't happen because you're basically writing instructions which has to happen either way.
- It is generally true that the higher the abstraction, the smaller its scope should be, so the default abstraction (paradigm) should be low level. This works e.g. in science: psychology is a high level abstraction but can only be applied to study human behavior, while quantum physics is a low level abstraction which applies to the whole universe.
Once computers start fundamentally working on a different paradigm, e.g. functional, we may switch to that paradigm as the default, but until then imperative is the way to go.
## History
TODO
Loading…
Cancel
Save