How to use the data manipulated in OpenGL Compute Shader

I can see a few things wrong here.

First, you're setting your GL buffer size to sizeof(vertices) * vertices.size()
This looks wrong. What is vertices? A std::array of vec4? Then you want vertices.size() * sizeof(glm::vec4), or just sizeof(vertices)

Second, as wandering-warrior said, you want to be binding to GL_ARRAY_BUFFER before calling glVertexAttribPointer

Third, I don't know what you're doing with bufferOffset in the second part of the code. This is a valid approach if the data is laid out sequentially in one large buffer (vertices then normals then tangents etc. etc.). But in your case you're using a separate buffer for each data set - so each attribute should start reading from the beginning of its own buffer, i.e. bufferOffset should always be 0.

Fourth, you don't seem to be actually using your compute shader anywhere. It's not enough to just call glUseProgram, you need to call glDispatchCompute after you bind your buffers to actually run it.

Also, it's not common practice to store binormals in an array, since they can be reconstructed in the fragment shader from the tangent and normal using a cross product.

I would do it something like this (using OpenGL 4.5 with the new Direct State Access functions to save all those buffer bindings).

int bufferSize = sizeof(vertices);

glCreateBuffers(1, &vbo_Previous);
glNamedBufferData(vbo_Previous, bufferSize, &vertices[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vbo_Previous);

glCreateBuffers(1, &vbo_Current);
glNamedBufferData(vbo_Current, bufferSize, &vertices[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, vbo_Current);

glCreateBuffers(1, &vbo_Next);
glNamedBufferData(vbo_Next, bufferSize, &vertices[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, vbo_Next);

glCreateBuffers(1, &vbo_Normal);
glNamedBufferData(vbo_Normal, bufferSize, &normals[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, vbo_Normal);

glCreateBuffers(1, &vbo_Tangent);
glNamedBufferData(vbo_Tangent, bufferSize, &tangents[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, vbo_Tangent);

glCreateBuffers(1, &vbo_Texcoords);
glNamedBufferData(vbo_Texcoords, sizeof(texCoords), &texCoords[0],
GL_STATIC_DRAW);

glCreateBuffers(1, &ebo);
glNamedBufferData(ebo, sizeof(elements), &elements[0], GL_STATIC_DRAW);
//you have element data in an array, right?

glCreateVertexArrays(1, &vao);
glBindVertexArray(vao);

glBindVertexBuffer(0, vbo_Next, 0, 0);
glVertexAttribBinding(0,0);
glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
glBindVertexBuffer(1, vbo_Normal, 0, 0);
glVertexAttribBinding(1,1);
glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 0);
glBindVertexBuffer(2, vbo_Tangent, 0, 0);
glVertexAttribBinding(2,2);
glVertexAttribFormat(2, 4, GL_FLOAT, GL_FALSE, 0);
glBindVertexBuffer(3, vbo_Texcoords, 0, 0);
glVertexAttribBinding(3,3);
glVertexAttribFormat(3, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayElementBuffer(vao, ebo);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);

computeShader.use();
glDispatchCompute (/*number of groups*/)
computeShader.unUse();

glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);

renderShader.use();
glDrawElements(GL_TRIANGLES, elements.size(), GL_UNSIGNED_INT, 0);
renderShader.unUse();


I think you're right and the subtraction is a mistake. The code should rather be multiplying the fraction of photons not absorbed into the weight. Something like:

float fraction_absorbed = sigma_a / sigma_t;
absorption += w * fraction_absorbed;
w *= (1.0f - fraction_absorbed);

This makes absorption the total fraction of photons absorbed so far, and w the fraction of photons remaining.


How do I extrude a 2D Bezier curve representation into a 3D solid using Python?

You can't create a solid by extruding a single curve or set of curves. Even if they are closed. Think about a circle on on the XY plane. If you extrude the circle along the Z axis you have an uncapped cylinder.
Let's walk it back a bit though. If you have a single Bezier curve and extrude it you create a Bezier surface. You can quickly get your head around a Bezier surface if you understand a Bezier curve.
https://en.wikipedia.org/wiki/B%C3%A9zier_surface
You can think of the Bezier surface as a blend through a set of curves. To extrude the curve you simply duplicate your original curve, and set the control points Z value to your extrusion distance. The original curve and new extruded curve create the control points for your surface.
I actually have a Bezier surface example I wrote in Python. The only dependencies are Numpy and Matplotlib. It also uses the Bernstein Basis function imported from another file in the repository. You can play with the control points to see how modifying them effects the resulting surface. There's no error checking so you'll have to know what you're doing.
https://github.com/jrz371/IntroToNurbsPython/blob/master/BezierSurface.py
As for parameterizing the span and chord length you'll have to derive those yourself. I'm unfamiliar with your requirements. Understanding the Bezier curves and surfaces thoroughly should help you resolve that.
Some of the comment suggest evaluating the curve and creating triangles. This is a bad approach. Tessellating a Bezier surface causes you to lose a lot of information. The Bezier surface is smooth whereas a set of triangles is not. For drawing a Bezier surface they are ultimately tessellated for the display, but they are kept in the original Bezier representation for modification.
Bezier curves are also not the best representation for curves and surfaces. BSplines and NURBS are able to represent more complex surfaces and curves. Understanding Beziers is fundamental prerequisite before tackling those.
Good luck!


Why cant I use `#include` after upgrading my driver

The error message gives a clue in the wording:

#version must occur before any other program statement

Is there a reason that the previous 2 lines need to appear before the #version line? If not, you can avoid the error by moving this line to the beginning, since the actions of the lines are independent of their order in this instance.

The #version needing to be at the beginning of the file is not a new requirement. I don't know why you were able to run this code previously.


The function in your third code snippet is checking for the winding order to be consistent between two neighboring triangles. It does this by looking at the order in which vertices are listed in their shared edge. If the two triangles have consistent winding (both counterclockwise for instance), they will have opposite orientations for the shared edge.

A diagram may help see this:

The vertex order is indicated by the blue arrows:

t0: v0, v1, v2
t1: v1, v3, v2

If you look at the shared edge (v1–v2), it appears in the first triangle with order v1, v2, and in the other with order v2, v1 (cycling around the end of the vertex list back to the beginning).

The function in your snippet takes a triangle and looks at one of its neighbors, checks all three possibilities for which edge in the second triangle is the shared one, and checks that the vertices in that (other triangle's) edge appear in the reverse order to the vertices in the current triangle's edge. It returns true if this is the case, and false otherwise.


This is a potentially confusing re-use of terminology. Ambient Occlusion is not in itself a post processing effect. Screen Space Ambient Occlusion is a post processing effect using the depth buffer to approximate the effects produced by Ambient Occlusion.

Ambient Occlusion is a relatively expensive global method, while Screen Space Ambient Occlusion is the cheaper alternative for real time animation. Only the latter is considered post processing.


Algebraically speaking, it's not too hard to modify $d$ in order to scale $z$. If you want to scale $z$ by a factor of $c$, giving $z' = cz$, then
$$
\begin{aligned}
d' &= a \frac{1}{z'} + b \\
&= a \frac{1}{cz} + b \\
(d' - b)c &= a \frac{1}{z} \\
&= d - b \\
d' &= \frac{d - b}{c} + b
\end{aligned}
$$
In short, to scale $z$ by a factor of $c$, you would take the depth value and subtract $b$, scale by $1/c$, then add $b$ back again.
Note that if you use a projection with reversed Z and an infinite far plane, then $b = 0$, which simplifies this to just $d' = d/c$.


"decent" is quite subjective and if you are restricting the capture to certain types of surfaces and controlled lighting conditions. For example normals and other SVBRDF parameters for shiny metallic surfaces are very difficult to capture compared to non-metallic, matte and bright surfaces without texture.

There are tools proposed in comments (CrazyBump, AwesomeBump) that try to do what you ask for and may generate normal maps sufficient to your requirements, but you could argue how "decent" the results are and how robust these tools are in capturing different types of surfaces. I don't know about the algorithms these tools use, but I believe they use more of an "artistic" than robust/accurate methods in generating the results.

There is some recent work to estimate normal map and other SVBRDF parameters using two images or from a single image (using neural networks), which is probably your best bet. However these algorithms assume a level of repeating pattern in the input images, but this might be ok for you since you mention rock wall as an example. There are likely other constraints as well such as requiring the captured surface to be dielectric hard surface material.

For more robust SVBRDF capturing you can check paper on frequency domain capture, but this is more complex capturing setup and far from a single image capture.

To my knowledge there's no known generic algorithm to accurately extract SVBRDF parameters from a single image of a non-repeating surface because of the fundamental issue that a single image can't unambiguously represent SVBRDF parameters. E.g. two different normal & albedo combinations of a Lambertian surface may result in same pixel color in a single image.


What algorithm is used in this animation from Tatami Galaxy?

It looks like a voronoi diagram with a non-Euclidean distance metric. Probably not Manhattan L1 but something close related, but maybe Mahalanobis with some kind of restriction on seed point generation and movement.

A similar result may be calculated with Weight-proportional Space Partitioning Using Adaptive Voronoi Diagrams when reducing spatial resolution of the domain.

I guess yo'll find similar examples in ShaderToy if you look for voronoi examples, which code you could study, and could be much simpler than the algorithm in the paper.


What is the relation between colour spaces and what is actually displayed on our screens?

Several reasons. Im listing them in random order

There are entire industries that do other things than display things on computer screens. If you were to print a booklet, make a package, movie projection or paint a car you would probably be wise to be able to mathematically model it for design, quality control and documentation purposes.

Not all screen suck and not all are good. Quite many screens out there can show wider color ranges than sRGB, or wider but still not entire sRGB. See sRGB is well suited for the designs it was designed for namely crt screens. LCD screens have had  hard time coming to sRGB gamut, but we are getting there. So many screens can not even do sRGB and many now exceed it.
The RGB color on each screen is different! Unless you have a screen that has been calibrated to sRGB odds are low that it shows sRGB (even if it does bet goes off in few weeks). Now for most people this is ok they arent aware how much off their screen is (i remember calibrating for first time o was quite shocked).
Anyway point is that you might be interested is describing the color so that you can do same color, not just same numeric value, on a different screen or display technology.

You might be doing color science and communicating measurements to others, or calculate how fast humans can separate the colors.

You might be developing a light simulator, i dunno like for movie special effects and or technical design and your interested in the light spectrums.

You might need to do distributions of colors visually

And so on...
As for gamna encoding your screen is not linear. If your screen were tuned linear it would be crappy indeed. And in anycase good screens have 10 to 12 bits of color to work with so gamma correcting is no problem.
As for spectral colors CIE is not dealing with spectrums... Not at all. All 3 component color is dealing with human perception. Spectrums are way different things, the thing you call orange on screen and what your physics book called wavelength are different things.


It is possible to do what you describe, but I'm afraid it is not a trivial process. Actually, this will be very tied to the Operating Systems you are targeting and possibly also requiring specific tweaks for the given game/application.

I would start looking into DLL injection techniques, which should allow, for instance, intercepting calls to the Direct3D (Windows) or OpenGL APIs, which you can then use to copy de framebuffers of the application. A quick Internet search turns up this and this with detailed explanation.

I once wrote a small-scale OpenGL interceptor on MacOS by injecting a custom shared module, but it was under very controlled circumstances and making a lot of assumptions, such as having root privileges in the system, so for a production tool, it would be a lot more complicated. You can find another very interesting project here about intercepting the D3D API to install an automated AI bot on Starcraft, which should touch on very similar concepts to what you are looking for.

Once you manage to intercept the underlying rendering API, you could then perhaps hook your code into each SwapBuffers or equivalent call to just copy the previous framebuffer before the swap, then save it (this is where something like glReadPixels would come into play).

Copying and saving the framebuffer in an efficient manner is also challenging. The easy way is to just dump each frame as an uncompressed RGB image, but then you'll wind up with hundreds of gigabytes of data for just a couple of minutes of gameplay, so unless you have a nice HDD array sitting at the corner of your table ;), you'll need to look into compressing the frames somehow.

The downside of compressing the frames now is that it takes a lot of processing, so a naive approach might turn the once interactive application you are trying to record into an interactive slide-show :(. So at this stage you'd have to start thinking about optimizations.

Don't know of any projects out there providing a library for efficient frame capture for games, but this would certainly be something nice to have! I think one thing that might be holding such project back is, like I mentioned at the beginning, that this is a very system dependent thing, so cases of use will most likely be limited to a single platform or OS.


Delta angle of two vectors about positive x axis

Generally when wanting the smallest angle between two vectors, the dot product is used.
$$
\vec A \cdot{} \vec B = \cos{\angle \alpha}
$$
Where $\vec A$ and $\vec B$ are vectors with the length of $1.0$.

However, you do not have access to the actual vectors themselves, if I understand your question correctly. You just have access to the angles between the vectors and a common direction.

There is a different way you could calculate that angle. You take the absolute value of the difference between the two angles, given that both angles are from a common direction and either both clock-wise or both counter clock-wise.
$$
\angle \phi = |\angle \alpha - \angle \beta|
$$
Where

$\angle \phi$ is the smallest positive angle between the two vectors.
$\angle \alpha$ and $\angle \beta$ are angles in the range from $[0, 360)$, between a common direction and the vector, and either both clock-wise or both counter clock-wise.

What do I mean with how I defined those angles?
First off all, that both angles are between a common direction and the vector. In this case it means that the angles should be between the vector and the red vector where the red vector is the common direction. Which is the case for the angles you provided. It is difficult for me to properly explain why they need to share a common direction, but it should be self explanatory.

What do I mean with that they should be either both clock-wise or both counter clock-wise? When having an angle between two directions, it can either be clock-wise or counter clock-wise. The angle between red and green is 60° and if you start at the red vector (which will be the common direction) you go counter clock-wise with an angle of 60°. The other angle should then also be counter clock-wise. This is the case between red and blue with an angle of -170°. If you look at the red vector, then you go clock-wise. However, the angle is negative, so you go backwards. This means that you actually go counter clock-wise.

And lastly, the angles should be in the range from $[0, 360)$. This makes the formula work a bit better. It is not needed, but then you would have to do some stuff with $\angle \phi$ instead. Basically, if the angle is larger than 360° you just keep subtracting 360° until it is within the range. If the angle is smaller than 0° you keep adding 360° until it is within the range.

Let us try this method with your example.

We have three vectors. $\vec Red$, $\vec Blue$ and $\vec Green$. We now the angles between $\vec Red$ and $\vec Blue$ and between $\vec Red$ and $\vec Green$.
$$\angle RB = -170$$
$$\angle RG = 60$$

$\angle RG$ is within our range, but $\angle RB$ is not. So we add 360° to $\angle RB$ and we get.
$$\angle RB = 190$$

They also both have a common direction, $\vec Red$ and are both counter clock-wise.

When adding them into the formula, we get;
$$\angle \phi = |190-60| = 130$$

And there we have it. The answer.

I do not know if this is a formula with a name or something like that. This method is something I just came up with.

Good luck!


Data structures for tile-based (deferred) rendering

That blog post that John mentions is a pretty good start (if I do say so myself!), but there's a bit of extra detail that might be helpful.

For the PowerVR architecture, the intermediate data structure -- variously called the primitive list or parameter buffer (PB) -- that stores the per-tile data, after all vertex shading and the tiling process is complete, is actually mostly generated and managed by the hardware, rather than the driver.

The PB's in-memory structures are physically split into two. First, blocks of transformed vertex data, including vertex attributes. The blocks are compressed, and as you can imagine they're just packed and compressed floating point data for the most part. The second in-memory structure is the tiling data, which is effectively a list of lists.

The top level list in that data structure is called a region, and it can encode a set of tiles rather than single tile at a time, for a given primitive block. A region is therefore a set of locations of screen tiles, tile states, and then a list of the compressed blocks that hold geometry in that region. Regions are what the rasteriser works on, and you can imagine that empty tiles are just automatically skipped, although there's a good reason in some cases for the rasteriser to visit empty regions.

The memory the GPU uses for the PB is dynamically allocated in all modern PowerVR implementations. A pointer to that memory is provided by the driver, and the driver, with the GPU's help, will size it as required. That mechanism is a tradeoff between having to reallocate frequently and minimising the amount of allocated PB space.

Modern GPUs try really hard to minimise memory indirection, but walking the PB to feed the rasterisation stage is one of those cases where it's really difficult and there's no other choice. Thankfully the pointer chasing wraps up large blocks that cache well and are streamed into the core.

Other architectures don't work exactly the same as PowerVR, because part of the reason the PB is the way it is in our architecture is to help the fully deferred pixel shading concept we implement, but the general concept applies to all other tilers in the mobile space that I'm aware of.


The theoretical ideal antialiasing filter for discretely sampled data is a sinc filter, because it perfectly removes all frequencies higher than the Nyquist frequency, while leaving alone all the lower ones. So, to some extent, we can expect antialiasing filters that more closely resemble the sinc filter to produce better-quality images.

The tent filter (triangle filter) certainly resembles the central peak of the sinc filter more closely than does the box filter:

A bicubic filter (e.g. Mitchell-Netravali) could capture the shape of the sinc even more precisely, including its first two negative lobes.

The reality of filter selection is a bit more subtle than "approximate sinc as well as possible", since there are different kinds of artifacts that can be generated by "non-ideal" antialiasing filters, such as aliasing, overblurring, and ringing. Also, different filters may be more or less computationally expensive. So it's a game of trying to trade off the different artifacts against each other and against performance. Different scenes/images may favor one choice or another, and it's also partly an aesthetic judgement.

As for why smallpt uses a tent filter in particular, I would guess for a combination of performance (it's a quick filter to evaluate) and brevity—it can be done in a couple lines of code, while a bicubic filter would take a bunch more code.

Incidentally, smallpt actually uses a 2x2 subpixel grid and places a tent filter at each subpixel, then averages together the results of the four subpixels. So the overall effect is, curiously, that of the sum of four tents, which ends up looking like a pyramid with a flat top:

I'm not sure if this was intentional, or just happened to be the way it worked out. My guess is this results in a somewhat sharper image than if a single tent filter per pixel were used (because of the narrower support), but probably also more visible aliasing.


How are the three plane equations derived in the NVIDIA's CG Tutorial chapter 8?

In this context, deriving the plane equations does not refer to the equations themselves, but to the coefficients $A$, $B$, $C$ and $D$.

The equations are simply plane equations for a plane defined by three points, where the first plane is defined by the three points $(x_i,s_i,t_i)_{i=1..3}$, the second plane is defined by $(y_i,s_i,t_i)_{i=1..3}$ and the third plane by $(z_i,s_i,t_i)_{i=1..3}$. They can be seen as auxiliary objects in deriving equations for $x$, $y$ and $z$ in terms of $s$ and $t$.


To what degree, if at all, can custom code be embedded in a PNG, GIF, or JPG?

Common graphics formats such as JPEG, PNG and GIF are not designed to have any form of code inside them. They just store a compressed array of pixels—they can't generate anything on command or contact a web service, etc.

(There have occasionally been vulnerabilities discovered in image decoders, that would allow a maliciously constructed image to cause code execution when viewed, via a buffer overflow exploit or similar. But this is of course not part of the design of the format.)

Some vector graphics formats such as EPS and SVG actually do allow embedding code. However, being vector formats instead of bitmap ones, these formats often aren't supported by ordinary image viewers (although SVG is supported by browsers), and can't be edited in ordinary paint programs. One needs specialized vector graphics programs to work with them.

In order to generate an image that updates with new data, you could create a web service that regenerates the image on the server each time it's requested. However, if a client caches the resulting image rather than re-requesting it each time it's viewed, they would see old data.


Has anyone found an analytic solution to the product of spherical gaussians from Xu et al?

Consider $f(v) := S(v;z_1)\cdot S(v;z_2)$ with $z_1=z_2=<1,0,0>$. Then
$$f(v) = \max(v_1,0)\cdot\max(v_1,0) = 0, \qquad \text{ if } v_1<0, $$
$$f(v) = \max(v_1,0)\cdot\max(v_1,0) = v_1^2 \qquad \text{ if } v_1\ge 0. $$
We want to find a $\tilde z$ such that $f(v) \stackrel{!}{=} S(v;\tilde z) = \max(v\cdot\tilde z,0)$ for all unit vectors $v$. But $v=<0,\pm 1,0>$ implies $\tilde z_2 = 0$ and similarly $v=<0,0,\pm 1>$ implies $\tilde z_3=0$. Consequently, $S(v;\tilde z) = \max(v_1 \tilde z_1, 0)$ and it is not possible to choose $\tilde z_1$ such that
$$\max(v_1\tilde z_1,0) = f(v)$$
for all unit vectors $v$.


Figured it out :) The dominos are now being placed along the X and Y coordinates generated by the function.

The original code in the question was plotting a wave of points outwards from the centre position or origin and was not what I wanted. What I needed was for each point to follow the Archimedean spiral with a certain space between the spirals.

Initially I used integer values to store the x and y coordinates but this was causing a precision error by truncating the floating point value in order to store it in the integer data type.

The below example generates points along the spiral continuously, relative to the maxPoints value.

float x = 0;
float y = 0;
float angle = 0.0f;

// Space between the spirals
int a = 2, b = 2;

for (int i = 0; i < maxPoints; i++)
{
    angle = 0.1 * i;
    x = (a + b * angle) * cos(angle);
    y = (a + b * angle) * sin(angle);

    plot(x, y);
}

Code for the project is on GitHub, you will need Bullet and freeglut


This is a recursive function (it calls itself). Each time it calls itself it does so with depth + 1 instead of depth. When it is called with depth > MAX, it simply returns Black rather than call itself again. This ensures that the function will eventually stop recursing and return a value. It is the colour equivalent of returning zero.

You can visualise this as a light ray reflecting from multiple surfaces successively. Each time the ray reflects from a surface the same function is used to calculate the colour of the light in that direction. If you set MAX to 0, there will be no reflections in your resulting image. If you set MAX to 2, there will be reflections of reflections which will look more realistic, but take longer to calculate.

Intuitively, MAX is the number of surfaces the ray will bounce off before it is decided what colour should be displayed.


Why is browser-resized image crispy and manually-resized image blurry?

There are many filters that can be used when resizing images. These filters have names like "box", "tent", "gaussian", "sinc", "lanczos", and many others. Believe it or not scaling an image down in size is actually much more challenging then scaling it up in size. It is easy to lose high frequency information when resampling an image. Look for the filters in the scaling software, but most software does a good job of choosing default filters so unless you changed the filter then the issue might be...
The next possible issue: jpg is not a lossless format and choosing the right size to compression setting is a trade off. Usually with jpg images a medium quality setting gives the best compression to quality ratio and only makes the image a few k bigger. This is a potential culprit. Try a "high quality" setting for the jpg to see if that helps, or even try a lossless format to remove image format as a potential problem.
To be more direct...the jpg is being sent at a larger size, with more info in it, the browser resamples giving a nice crispy image. But if you resize then that extra info is thrown away and isn't available for the browser to resample it. This is why using a higher quality jpg may help.
"Optimized" jpg's only affect the size of the file, making it slightly smaller in size.
But serving images up from the web has a lot of middleware getting involved, and if these suggestions don't fix the problem then it may be the middleware which is beyond the scope of this forum.
BTW: the two images look almost identical in my browser.


human visual: relation of Distance and DPI

According to a review by Legge & Bigelow the arc or degrees of visual angle ($\alpha$) is,

$$
\alpha = 57.3 \times S/D,
$$

where S is height of object and D is distance to object. [1] $S/D$ is the small angles approximation of $2 \times arctan(S/2D)$ which follows form geometry.

Image 1: the equation comes straight from trigonometric definitions.

Since humans continuously scan the page with the fovea, small angles assumption is a good approximation for entire pages. The factor $57.3$ is simply $180/\pi$ or conversion form radians to angles.

So given that we do not know the nature of $tg$, then its hard to say. Looks a bit fishy, but if tg is some sort of inversion of S then its plausible.

[1] G. Legge & C Bigelow. 2011. Jornal of vision. Does print size matter for reading? A review of findings from vision science and typography.


Where can I find those visual effect demonstration?

The Unreal Engine documentation has good explanations for their various post-processing effects like Bloom. You can find more information about it here: https://docs.unrealengine.com/en-us/Engine/Rendering/PostProcessEffects/Bloom

In the case of UE4, bloom becomes observable once color values push beyond the 1.0 value.


Full screen quad texture coordinates mapping

I may have misunderstood, but it sounds like the frame buffer you're rendering to is only 2×2 pixels? In that case, the fragment shader will be evaluated at each pixel center, which will be at 0.25 and 0.75 in UV space. So with a threshold of 0.95 you will indeed not get any pixels green.

If you use a larger framebuffer, say 100×100, then the last 5 pixels of each row should come out green.


UV Coordinate Interpolation in Compute Shader

You seem to do things more complicatedly than you need to, as adressed in the comments. What you actually want to do is simple the opposite of the normal render flow. Rather than drawing your mesh in world space and mapping the texture into it, you draw it in texture space and map its vertices onto it and let your graphics hardware worry about interpolation. I'll give the general outline here, as I honestly don't know the actual DirectX terms for the stuff here, but it should be easy to map onto real HLSL if you know your way around DirectX (which I'm sure you do when messing with Compute Shaders).

You basically render into your output texture using an offscreen render target. You then render your mesh using its texture coordinates as positions rather than its model space vertices, which you just pass through to the pixel shader, where you finally transform them into screen space and write out as the pixel's colour:

[Vertex Shader]

PER VERTEX float2 uv;
PER VERTEX float4 v_point;

TO PS float4 modelPos;

void VSMain() {
    CLIP_POSITION = uv;
    modelPos = v_point;
}

[Pixel Shader]

CONSTANT float4x4 MVP;
CONSTANT float2 viewportSize;

FROM VS float4 modelPos;

void PSMain() {
    float4 clipPos = MVP * modelPos;
    float3 ndcPos = clipPos.xyz / clipPos.w;
    float3 screenPos = float3(viewportSize * (screePos.xy * 0.5 + float2(0.5)), ndcPos.z);
    OUT_COLOR = screenPos;
}

Feel free to adjust this to the realities of proper DirectX screen-space transformations and matrix multiplication orders, but the general idea should be clear.


Can I run polygon insetting on the surface of a mesh?

This is more of a long comment

Yes you can do this. The problem lies in how you measure the surface. I tried to do this manually by progressively extruding tubes along the edges, and finding their intersection with the surface. It would work but is a bit hard to compute. Obviously you may want to take more steps than i did for a more accurate solution.

Image 1 Straight skeleton (magenta)  and insets by finding the intersection of tubes along edges, and then the created edges on mesh (blue)
From this experiment I can conclude that are many complex cases to consider.


Why MOCAP data don't use simple point coordinates?

Joint coordinates alone don't give you enough information about rotation.

For example, hold out your arm to your side. Notice that you still have one degree of freedom to twist the arm without affecting the positions of your elbow or wrist. Thus, if you had a motion capture format that stored only those coordinates, you would not be able to distinguish these poses.


Why isn't multi-gpu handled by the driver?

Your assumption is wrong
It actually was this way, in fact, things have changed the other direction.
History
Currently (pre nvidia link consumer graphics) you've got to copy the memory over from separate GPUs to render in cross fire and SLI, as global memory transfer speeds will slow down scaling, and as far as I can tell it did not work as a general direct memory acessor, with only 2G/s bandwidth even with the HB version, it is only meant to be a framebuffer copier.   You otherwise had to send the same information across all GPUs via PCIE.

SLI allows two, three, or four graphics processing units (GPUs) to share the workload when rendering real-time 3D computer graphics. Ideally, identical GPUs are installed on the motherboard that contains enough PCI-Express slots, set up in a master-slave configuration. All graphics cards are given an equal workload to render, but the final output of each card is sent to the master card via a connector called the SLI Bridge. For example, in a two graphics card setup, the master works on the top half of the scene, the slave the bottom half. Once the slave is done, it sends its render to the master to combine into one image before sending it to the monitor.

(emphasis mine).
But you didn't typically actually treat this set up as one GPU in the way you want in old times because if you wanted to cooporate work loads instead of merely splitting workloads that required GPU->GPU communication, which necessarily had to be done VIA pcie, which would be very slow.
At least for opengl, SLI/Xfire rendering was handled via Driver treating the two as the same. https://stackoverflow.com/a/43812678/2036035 You didn't have the option of treating them as separate if they were linked.
Modern
Today however, vulkan and DX12 essentially give more control.

One feature in particular goes a long way toward filling a Vulkan gap relative to Microsoft's API: explicit multi-GPU support, which allows one program to spread its work across multiple GPUs. Unlike SLI and Crossfire of old, where the task of divvying up the rendering between GPUs was largely handled by the driver, this support gives control to the developer. With the addition, developers can create "device groups" that aggregate multiple physical GPUs into a single virtual device and choose how work is dispatched to the different physical GPUs. Resources from one physical GPU can be used by another GPU, different commands can be run on the different GPUs, and one GPU can show rendered images that were created by another GPU.

(emphasis mine)
Today you can look at these GPUs separately.


Are draw calls executed in parallel or sequentially or both?

The result should be as if it was executed sequentially one triangle at a time. This is important so that each frame is deterministic. If it wasn't then drawing the same frame multiple times could create different results and create a flickering image on screen.

However that does not mean parallelization is impossible. Vertices can be computed in parallel. Their results will be ordered and fed to the rasterizer which will feed the fragment shader stage.

The same happens with pixels. Typically a group of pixels from a triangle can be computed in parallel and blended. A non-overlapping triangle can then also be filled at the same time however if triangle overlaps one currently busy then the result of the fragment shader must be buffered until the corresponding pixels of the previous triangle are done so blending can happen in the correct order.


Z-Buffer algorithm vs Painter's algorithm?

In the painter's algorithm, you first sort all graphics elements
on depth (deepest first) and
then one-by-one fully paint them into the image on top of each other.
That way, deeper elements are obscured by less deep element.
(Intersecting graphics element require special attention.)
In the depth-buffering algorithm,
you store the current depth of each pixel in the image
(in addition to other pixel info),
and fully paint each graphics element pixel-by-pixel,
where an image pixel is updated
only if its depth is more than that of the new pixel.

So, there is a time-memory tradeoff:

The painter's algorithm requires an extra sorting step (costs time),
but avoids storing additional (depth) information per pixel (saves memory).
Depth-buffering avoids sorting (saves time),
but stores extra (depth) information per pixel (costs memory).


What are the side effects of biasing brightness in continuous spectrum raytracing?

Generally, uniformly-weighted samples with a variable distribution (importance sampling) gives lower variance in the final average than uniformly-distributed samples with variable weights.  This is a common rule of thumb in Monte Carlo raytracing.

However, another thing to consider is that you'll eventually be converting the images to RGB for display (I assume).  So a potential problem might be that if a light source has very little energy in the blue part of the spectrum, for instance, then you'll put few samples in the blue frequencies, and the blue channel of the final RGB image could end up excessively noisy compared to the other channels.

One way to resolve this might be to consider the product of the light source's spectrum with the RGB color-matching curves used to generate the output.  You could normalize the three against each other to ensure you get enough samples in all three channels, but still distribute the samples to the most important frequencies for each channel.

On balance, I suspect that simply using a uniform frequency distribution of samples will be simpler and give good results as long as the light source spectra are fairly smooth.  But if you have spectra with sharp spikes (e.g. LEDs, lasers, fluorescent lamps) then spectral importance sampling will probably be necessary.


Does WebGL 2 support linear depth texture sampling?

The spec says depth textures are not filterable.

  3.8.13

  ...

  Using the preceding definitions, a texture is complete unless any of the following conditions hold true:

  The effective internal format specified for the texture arrays is a sized internal depth or depth and stencil format (see table 3.14), the value of TEXTURE_COMPARE_MODE is NONE, and either the magnification filter is not NEAREST or the minification filter is neither NEAREST nor NEAREST_-
  MIPMAP_NEAREST


memory consumption for a true color frame buffer

True color is 8 bits per color channel, so 3 bytes per pixel.  1024x768 is 785,408 pixels.  At 3 bytes per pixel that is 2,356,224 bytes.  Since it's double buffered we double that number to 4,712,448 bytes which is about 4.5MB.


Is a cubic Lagrange interpolation tensor product the same as bicubic interpolation?

It turns out that no, while you can use bicubic Lagrange interpolation for bicubic texture sampling, it isn't the highest quality option, and probably not actually likely to be used.

Cubic hermite splines are a better tool for the job.

Lagrange interpolation will make a curve that passes through the data points, thus preserving C0 continuity, but hermite splines preserve the derivatives at the edges while also passing through the data points, thus preserving C1 continuity and looking much better.

This question has some great info on cubic hermite splines:
https://dsp.stackexchange.com/questions/18265/bicubic-interpolation

Here is the cubic hermite version of the code I posted in the question:

//=======================================================================================
vec3 CubicHermite (vec3 A, vec3 B, vec3 C, vec3 D, float t)
{
    float t2 = t*t;
    float t3 = t*t*t;
    vec3 a = -A/2.0 + (3.0*B)/2.0 - (3.0*C)/2.0 + D/2.0;
    vec3 b = A - (5.0*B)/2.0 + 2.0*C - D / 2.0;
    vec3 c = -A/2.0 + C/2.0;
    vec3 d = B;

    return a*t3 + b*t2 + c*t + d;
}

//=======================================================================================
vec3 BicubicHermiteTextureSample (vec2 P)
{
    vec2 pixel = P * c_textureSize + 0.5;

    vec2 frac = fract(pixel);
    pixel = floor(pixel) / c_textureSize - vec2(c_onePixel/2.0);

    vec3 C00 = texture2D(iChannel0, pixel + vec2(-c_onePixel ,-c_onePixel)).rgb;
    vec3 C10 = texture2D(iChannel0, pixel + vec2( 0.0        ,-c_onePixel)).rgb;
    vec3 C20 = texture2D(iChannel0, pixel + vec2( c_onePixel ,-c_onePixel)).rgb;
    vec3 C30 = texture2D(iChannel0, pixel + vec2( c_twoPixels,-c_onePixel)).rgb;

    vec3 C01 = texture2D(iChannel0, pixel + vec2(-c_onePixel , 0.0)).rgb;
    vec3 C11 = texture2D(iChannel0, pixel + vec2( 0.0        , 0.0)).rgb;
    vec3 C21 = texture2D(iChannel0, pixel + vec2( c_onePixel , 0.0)).rgb;
    vec3 C31 = texture2D(iChannel0, pixel + vec2( c_twoPixels, 0.0)).rgb;

    vec3 C02 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_onePixel)).rgb;
    vec3 C12 = texture2D(iChannel0, pixel + vec2( 0.0        , c_onePixel)).rgb;
    vec3 C22 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_onePixel)).rgb;
    vec3 C32 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_onePixel)).rgb;

    vec3 C03 = texture2D(iChannel0, pixel + vec2(-c_onePixel , c_twoPixels)).rgb;
    vec3 C13 = texture2D(iChannel0, pixel + vec2( 0.0        , c_twoPixels)).rgb;
    vec3 C23 = texture2D(iChannel0, pixel + vec2( c_onePixel , c_twoPixels)).rgb;
    vec3 C33 = texture2D(iChannel0, pixel + vec2( c_twoPixels, c_twoPixels)).rgb;

    vec3 CP0X = CubicHermite(C00, C10, C20, C30, frac.x);
    vec3 CP1X = CubicHermite(C01, C11, C21, C31, frac.x);
    vec3 CP2X = CubicHermite(C02, C12, C22, C32, frac.x);
    vec3 CP3X = CubicHermite(C03, C13, C23, C33, frac.x);

    return CubicHermite(CP0X, CP1X, CP2X, CP3X, frac.y);
}

Here is a picture showing the difference between sampling methods.  From left to right: Nearest Neighbor, Bilinear, Lagrange Bicubic, Hermite Bicubic


What is Ray Marching? Is Sphere Tracing the same thing?

TL;DR
They belong to the same family of solvers, where sphere tracing is one method of ray marching, which is the family name.
Raymarching a definition
Raymarching is a technique a bit like traditional raytracing where the surface function is not easy to solve (or impossible without numeric iterative methods). In raytracing you just look up the ray intersection, whereas in ray marching you march forward (or back and forth) until you find the intersection, have enough samples or whatever it is your trying to solve. Try to think of it like a newton-raphson method for surface finding, or summing for integrating a varying function.
This can be useful if you:

Need to render volumetrics that arenot uniform
Rendering implicit functions, fractals
Rendering other kinds of parametric surfaces where intersection is not known ahead of time, like paralax mapping
Etc

Image 1: Traditional ray marching for surface finding
Related posts:

how-do-raymarch-shaders-work (GameDev.SE)

Sphere tracing
Sphere tracing is one possible Ray marching algorithm. Not all raymarching uses benefit form this method, as they can not be converted into this kind of scheme.
Sphere tracing is used for rendering implicit surfaces. Implicit surfaces are formed at some level of a continuous function. In essence solving the equation
F(X,Y,Z) = 0

Because of how this function can be solved at each point, one can go ahead and estimate the biggest possible sphere that can fit the current march step (or if not exactly reasonably safely). You then know that next march distance is at least this big. This way you can have adaptive ray marching steps speeding up the process.

Image 2: Sphere tracing* in action note how the step size is adaptive
For more info see:

Sphere tracing: a geometric method for the antialiased ray tracing of implicit surfaces

* Perhaps in 2d it's should be called circle tracing :)


Revisiting this question from awhile ago. It turns out this sort of histogram is created by iterating through every pixel value in both the normal image and gradient magnitude image plotting it in the 2d image. (x intensity, y gradient magnitude). The count/occurrences of the 2d histogram are represented by the intensity of the grayscale in figure b. So the brighter a pixel in figure b is, the more pixels with that (intensity, gradient magnitude).

For volume rendering this is called a 2d transfer function which lets users filter out or assign lower opacities to pixels with large/small gradient magnitudes. This is especially helpful in real time volume rendering with lighting. Real time volume rendering typically uses a BSDF at every point along a ray march as an approximation (Assuming that light reaches every point in the volume). IE: Dot product of the incoming light direction with the gradient as the normal. Using the gradient as the normal means that homogeneous areas are not well represented as they have low gradient magnitudes. Small noise in these areas can easily cause the gradient and normal to flip.


Threads lockstep and conditions in compute shader

Not all threads will execute in lockstep but they are split into groups whose threads are locked to each other.

This means that if only 1 thread out of all threads enters a branch then only 1 group will need to enter that branch while all the others will skip it.

In that group that has to execute both branches it will actually execute both branches but threads will throw away the result of the branch that it didn't need to go into.

For more information see this question.


How many Direct/Compute/Copy Queues are meaningful?

Ship your application with a benchmarking sequence testing the actual platform. (Possible answer for many questions I guess...)

I suspect the performance is highly dependent on how you use the hardware. Since the hardware is unlikely to somehow instrument your application backwards, telling you what to do, I´d go with whatever looks good in your design.

  "...command queues can be executed concurrently by the device..."

Keyword is CAN. I see no reason why any vendor would screw this up. In the end it is the platform provider (Intel/AMD/Nvidia) who is responsible of making you a good enough driver for you not to consider switching vendor. If they do have a "know issue" with this functionality (which by the way has no functional meaning, only performance) then they should also solve it using what they know. I mean for crying out loud, the fallback is something they have already implemented; synchrounous execution.

Hardware is enough voodoo as it is for us developers.


The most common way I saw is to have photons of several different wavelengths. One then renders with each wavelength and blends the results into the final image.

"Existing work": Psychopath Renderer and The Secret Life of Photons.


Two big ones you're missing:

Angle-dependent reflection.  This is one possible cause of your "transparent in places and not in others" effect, and the most likely cause of the missing wetness.
Ice cubes usually have air bubbles trapped inside.  This shows up as a white volumetric haze denser in the center of the cube (for small bubbles) or distinct bubbles (for large ones).  This is the other likely cause of your "transparent in places and not in others".

The techniques for modeling these depend on what rendering method you're using.


"Anchor" vehicle to 3D path with OpenGL / SDL

I think the most common way to have a the "up and down" movement of a vehicle is to actually build a physics simulation.
It does not have to be a very sophisticated one and how much realism you want is up to you.

But just in each frame update the velocity of the car in downward direction (gravity) until it hits the road. Then if the road has an upward slope it will also push the car up (by colliding with the car).

Now you have a new problem and that is the problem that the car remains parallel to the ground-plane. And the physical calculation behind this is a bit more complex.

When detecting if your car hit the ground you would have to detect the exact position of the hit (which part of the car hit the floor?). Then using the gravity, mass and some material properties (all of which you could just set globally and assume as easy values for simplicity) you can calculate how the reaction force to the collision will be. And you know that the force will be exerted on the collision point.
Now when you have the center of mass of the car, and the collision point, and the force created by the ground-collision, you can calculate how to rotate the car.

This is only a very rough sketch of how I learned to handle such things in a "real" way. I hope this was not too confusing, if you have additional questions I can rework the answer later.


Understanding fragment shader coordinate system

Everything in this code functions as intended, until I try to translate the entire grid (grid lines) to the center of the screen by adding v_Resolution.x / 2 to uv.x.

Not sure what your intention is here since the Shadertoy example you referenced generates an infinite grid. So maybe you can clarify that.
However, I think I can help you with this problem:

... the ShaderToy example, the coordinates are not normalized at all, and it functions perfectly fine! I feel like I'm missing a very important concept here.

I think the basic problem here is, that you do not really understand how the mesh is generated and why the Shadertoy example isn't normalizing the uv-coordinates. If I can help you understand it, you can probably fix your other problems by yourself.
So let's walk through the Shadertoy code and what it actually does:
vec2 uv = fragCoord.xy;

// Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).
uv.x *= 1.0 / spacing;
uv.y /= spacing;

Here you first copy the frag coordinates into uv and afterward divide it by the spacing of your lines. Not sure why the author used those 'complicated' last two lines, but you can replace them simply with uv /= spacing;.
The purpose of this step is to transform into a new space where the lines of your grid are located at every whole number. If your spacing is 20, like in the shader toy example, only the fragments with one of its frag coordinates being one of 0, 20, 40, etc. would produce a whole number and would be located on a line. Maybe you can already see where this is going.
// Adjust the origin of each line thicker than one pixel to its center.
uv.xy += (lineWidth > 1) ? width * 0.5 : width;

// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.
uv.y -= (iResolution.y - 600.0) / spacing;

// Apply camera translation.
uv.x -= translation.x / spacing;
uv.y += translation.y / spacing;

Here he is just translating the grid to consider several things like line thickness and camera position. The camera position is probably what you are interested in. I have no clue, about the purpose of the second line, even though the comment specifies it, but it is just a y-shift of your grid. However, note that all translations must be in the "grid-space" like the uv coordinates. Hence he always divides by spacing. For width, he already applied the transformation several lines above -> float width   = float(lineWidth)   / spacing;
float grid = 0.0;
grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)
grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)

vec4 col = vec4(grid);

Now here comes the magic that actually produces the grid. Let's dissect the second line. fract(uv.x) just returns the fractional part of uv.x. So a value of 12.125 is reduced to 0.125. The step function returns 0 if the second value is smaller than the first and 1 otherwise. So the point of step(fract(uv.x), width) frac is to get a 1 if the uv coordinate is on a vertical line and 0 if not. The max in this line is pretty pointless since grid (which is set to 0.0) is either equal to the returned value or less. The third line does the same thing for horizontal lines, but here the max is actually needed.
So to sum it up, grid is 1 if the fragment lies on a horizontal and/or vertical line and 0 if not.
The last line just turns that into a vector. So you either get pure white ((1.0, 1.0, 1.0, 1.0)) as pixel color if the fragment is part of a line or pure black ((0.0, 0.0, 0.0, 0.0)) if not. Note that if alpha blending is enabled, black is actually translucent since the alpha channel is also 0.
if (col.r != 0.0 && col.g != 0.0 && col.b != 0.0) {
    float mx = mod(uv.x, float(darkenMultiple));
    float my = mod(uv.y, float(darkenMultiple));

    // Make lines that are a multiple of `darkenMultiple` darker than the rest.
    col.a = (mx < width || my < width) ? 0.2 : 0.15;
} else {
    // Turn all pixels that aren't apart of the grid invisible as to not cover the rest of the scene.
    col.a = 0.0;
}

col = showNyanCat(col, fragCoord);

fragColor = col;

This just adjusting the color of the grid and plotting the cat and not relevant to your question.
I optimized the shader from the Shadertoy example a little bit by removing obsolete instructions, postponing the transformation into "grid space" after applying the translations, and vectorizing some operations. Maybe it makes it easier for you to understand what is happening. I kept the original comments and added some own ones:
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    // Define some variables we use ---------------------------------------------
    // Simulate camera translation, just for this example.
    vec2 velocity = vec2(-30.0, 10.0);
    translation += scale * iTime * velocity;

    float spacing = float(lineSpacing) * scale;
    float width   = float(lineWidth)   / spacing;

    // Add all translations to uv -----------------------------------------------
    // Apply camera translation.
    vec2 uv = fragCoord - translation;

    // Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.
    uv.y -= (iResolution.y - 600.0);

    // Adjust the origin of each line thicker than one pixel to its center.
    uv += (lineWidth > 1) ? float(lineWidth) * 0.5 : float(lineWidth);

    // Transform to "grid space" ------------------------------------------------
    // Correct the coordinates by taking into account the aspect ratio (turns the grid into perfect squares).
    uv /= spacing;

    // Identify if pixel is on a line -------------------------------------------
    float grid =     step(fract(uv.x), width)       ; // X lines (horizontal)
    grid       = max(step(fract(uv.y), width), grid); // Y lines (vertical)

    // Set the correct color ----------------------------------------------------
    vec4 col = vec4(grid);
    if (grid != 0.0) {
        float mx = mod(uv.x, float(darkenMultiple));
        float my = mod(uv.y, float(darkenMultiple));

        // Make lines that are a multiple of `darkenMultiple` darker than the rest.
        col.a = (mx < width || my < width) ? 0.2 : 0.15;
    }

    // Plot the cat -------------------------------------------------------------
    col = showNyanCat(col, fragCoord);

    fragColor = col;
}

In this version, you can simply add your translations in pixels without any need to transform them to "grid space" or to normalize them. Hope that helps. You can copy it into the Shadertoy example to see that the results are the same.

Now, if I remember correctly, the origin in a GLSL fragment shader is bottom left, so why do I have to subtract v_Resolution.x / 2.f instead of adding it?

Probably because you use different signs here:
// Apply camera translation.
uv.x += v_CamPos.x / v_CellSize;
uv.y -= v_CamPos.y / v_CellSize;

(also, why is the x-component not normalized, like the y-component?)

I guess you fiddled around until "something" produced the expected image rather than knowing what happens. I see no point in investigating the "why" here. Understand the Shadertoy code (or my version) and then apply your changes while actually knowing what you are doing. If you use my version, all you have to add are the translations in pixels that you want to apply.

Update
Regarding the comment of Andrew Woo:

I really appreciate the in-depth explanation, it helped a lot in my understanding, however it doesn't really answer my [original] question, which was why the x-component of uv isn't normalized.

I was addressing that at the end of the original answer when I said that you fiddled around until "something" worked and I didn't saw any point in investigating why "obviously wrong" code produces the correct result.
Well, let's get something clear: uv coordinates are not screen coordinates. So gl_FragCoord.y / v_Resolution.y is not the general definition of v. I would rather call them "normalized screen coordinates". uv coordinates are (usually) used to map regular 2-dimensional data like an image onto a surface. You can read more about them on Wikipedia. Don't be fooled by the fact that the author of the question you linked used the "normalized screen coordinates" as uv coordinates. They might be the same if you want to map an image to your screen, but usually, they are not.
In the shadertoy example, the uv coordinates are used to map a single cell of your grid. You start using uv coordinates of the grid after you divided the frag coordinates by the cell size. Before that, they are no uv coordinates, at least not in relation to the grid.
So let's summarize what the shader does: You start with pixel coordinates inside your shader with values between 0 and the screen resolution in either direction and you want to calculate the uv coordinates of the grid in order to draw it. That's the whole purpose of the code we discussed. Do we need to divide by the screen resolution for that? No, we don't. We could if it would make our life easier to get from A to B, but we simply do not need it here and the original shadertoy algorithm doesn't do it.
So the question shouldn't be "why the x-component of uv isn't normalized" but:
"Why do I get the correct result when I use normalized screen coordinates instead of fragment coordinates for the y-component and wrong ones if not"?
I have not tested your code, but by just looking at it, I would say by normalizing the y component here: (gl_FragCoord.y / v_Resolution.y) + (v_Resolution.y / 2.f) you are more or less "removing" them from the line. Just insert the numbers:

gl_FragCoord.y / v_Resolution.y is a number between 0 and 1
v_Resolution.y / 2.f is 309

So at this point, you have v-values between 309 and 310. It is almost a constant. Simply remove gl_FragCoord.y / v_Resolution.y and you should still get the same result. Now the question arises, why is the grid still rendered correctly? I guess because of this line:
// Make the grid resolution independent by offsetting the Y coordinates based on the current viewport height.
    uv.y -= gl_FragCoord.y / v_CellSize;

Note that you use gl_FragCoord.y while the Shadertoy code used iResolution.y, which is a constant. What you do here is correcting the effective removal of gl_FragCoord.y I explained before. You need to divide by v_CellSize because the uv coordinates were also divided by v_CellSize 2 instructions before (uv.y /= v_CellSize;).
How to correct it?
Simply remove this line:
uv.y -= gl_FragCoord.y / v_CellSize;

Then remove the division through v_Resolution.y from here:
vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y / v_Resolution.y + v_Resolution.y / 2 - v_CellSize / 2);

It should look like this:
void main() {

    float width = lineWidth / v_CellSize;

    vec2 uv = vec2(gl_FragCoord.x, gl_FragCoord.y + v_Resolution.y / 2 - v_CellSize / 2);

    uv.x *= 1.0 / v_CellSize;
    uv.y /= v_CellSize;

    // Adjust the origin of each line thicker than one pixel to its center.
    uv.xy += (lineWidth > 1) ? width * 0.5 : width;

    // Apply camera translation.
    uv.x += v_CamPos.x / v_CellSize;
    uv.y -= v_CamPos.y / v_CellSize;

    float grid = 0.0;
    grid = max(step(fract(uv.x), width), grid); // X lines (horizontal)
    grid = max(step(fract(uv.y), width), grid); // Y lines (vertical)

    vec4 col = vec4(grid);

    // ... insert rest of your code
}

Now you should have the "correct" result and the x and y components are treated identically.


How updating a depth buffer works in GPU?

In a real GPU, instead of having multiple cores trying to read/write the same region of the depth buffer and attempting to synchronize between them, the depth buffer is divided into tiles (such as 16×16 or 32×32), and each tile is assigned to a single core. That core is then responsible for all rasterization in that tile: any triangles that touch that tile will be rasterized (within that tile) by the owning core. Then there is no interference between cores, and no need for them to synchronize when accessing their part of the framebuffer.

This implies that triangles that touch multiple tiles will need to be rasterized by multiple cores. So, there is a work redistribution step between geometry processing (operations on vertices and triangles) and pixel processing.

In the geometry stage, each core might process a chunk of input primitives; then for each primitive, it can quickly determine which tiles the primitive touches (this is called "coarse rasterization"), and add the primitive to a queue for each core that owns one of the affected tiles.

Then, in the pixel stage, each core can read out the list of primitives in its queue, calculate pixel coverage for the tiles the core owns, and proceed to depth testing, pixel shading and updating the framebuffer, with no need of any further coordination with other cores.


With an old-style Phong shader (as in your example), they really are just added together. Each of those things is a contribution to the overall amount of light, so they're just added together, the same way you add together the contribution from each light source.

Your intuition is right that you often end up with overexposed specular highlights with this style of shading. In a modern, physically-based pipeline, it's common to instead use an energy-conserving shader. The contributions of each layer (specular, clear-coat/lacquer, diffuse, subsurface) are still added together, but the amount of light in each layer reduces the input amount of light for the next layer. That is, if the surface is giving a strong specular reflection, it's reflecting most of the light, so less light is available for the diffuse layer. In the same way, any light that's reflected by the diffuse layer reduces the amount of light available for subsurface scattering.


It's essentially because not all GPUs can support function calls—and even if they can, function calls may be quite slow or have limitations such as a very small stack depth.

Shader code and GPU compute code may appear to have function calls all over the place, but under normal circumstances they're all 100% inlined by the compiler. The machine code executed by the GPU contains branches and loops, but no function calls. However, recursive function calls cannot be inlined for obvious reasons. (Unless some of the arguments are compile-time constants, in such a way that the compiler can fold them and inline the entire tree of calls.)

In order to implement true function calls, you need a stack.  Most of the time, shader code doesn't use a stack at all—GPUs have large register files and shaders can keep all their data in registers the whole time.  It's difficult to make a stack work because (a) you would need a lot of stack space to provide for all the many warps that can be in flight at a time, and (b) the GPU memory system is optimized for batching together a lot of memory transactions to achieve high throughput, but this comes at the expense of latency, so my guess is stack operations like saving/restoring local variables would be awfully slow.

Historically, hardware-level function calls haven't been too useful on the GPU, as it has made more sense to inline everything in the compiler.  So GPU architects haven't focused on making them fast.  Probably some different tradeoffs could be made, if there is a demand for efficient hardware-level calls in the future, but (as with everything in engineering) it will incur a cost somewhere else.

As far as raytracing is concerned, the way people usually handle this sort of thing is by creating queues of rays that are in the process of being traced.  Instead of recursing, you add a ray to a queue, and at the high level somewhere you have a loop that keeps processing until all the queues are empty.  It does require significant reorganization of your rendering code if you're starting from a classic recursive raytracer, though.  For more info, a good paper to read on this is Wavefront Path Tracing.


Ok, so I made little example of how to do this.

Short version

You need to allocate additional buffer with heap type D3D12_HEAP_TYPE_READBACK and resource state set to D3D12_RESOURCE_STATE_COPY_DEST. Then create command list with type D3D12_COMMAND_LIST_TYPE_COPY. After dispatch compute shader use fence to check if buffer is ready, then copy from this buffer to buffer on D3D12_HEAP_TYPE_READBACK heap. Check again with fence if copying is finished and call Map on this buffer.

I would suggest that you stop reading here and try implement it from description above and check longer version if its still doesn't work. Copy/Past isn't the best way to learn :)

Longer version

First lets create new command list.

ID3D12CommandQueue* copyQueue;
ID3D12CommandAllocator* copyAllocator;
ID3D12GraphicsCommandList* copyList;

D3D12_COMMAND_QUEUE_DESC descCopyQueue = {};
descCopyQueue.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
descCopyQueue.Type = D3D12_COMMAND_LIST_TYPE_COPY;
device->CreateCommandQueue(&descCopyQueue, IID_PPV_ARGS(&copyQueue));
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&copyAllocator));
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, copyAllocator, nullptr, IID_PPV_ARGS(&copyList));

Notice type D3D12_COMMAND_LIST_TYPE_COPY.

Next thing is new buffer.

D3D12_HEAP_PROPERTIES const heapPropertiesReadback =
{
    /*Type*/                    D3D12_HEAP_TYPE_READBACK
    /*CPUPageProperty*/         ,D3D12_CPU_PAGE_PROPERTY_UNKNOWN
    /*MemoryPoolPreference*/    ,D3D12_MEMORY_POOL_UNKNOWN
    /*CreationNodeMask*/        ,0
    /*VisibleNodeMask*/         ,0
};

D3D12_RESOURCE_DESC buffersDesc = {};
buffersDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
buffersDesc.Alignment = 0;
buffersDesc.Width = sizeof( unsigned int ) * 5;
buffersDesc.Height = 1;
buffersDesc.DepthOrArraySize = 1;
buffersDesc.MipLevels = 1;
buffersDesc.Format = DXGI_FORMAT_UNKNOWN;
buffersDesc.SampleDesc.Count = 1;
buffersDesc.SampleDesc.Quality = 0;
buffersDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
buffersDesc.Flags = D3D12_RESOURCE_FLAG_NONE;

ID3D12Resource* bufferReadback;

device->CreateCommittedResource(&heapPropertiesReadback, D3D12_HEAP_FLAG_NONE, &buffersDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&bufferReadback));

Remember to set D3D12_RESOURCE_DESC ::Width to size of your buffers.

Then after you Dispatch compute list and call ExecuteCommandLists on compute queue you need to use fence, copy buffer and use fence again.

computeQueue->Signal(fence, fenceValue);
fence->SetEventOnCompletion(fenceValue, fenceEvent);
++fenceValue;
WaitForSingleObject(fenceEvent, INFINITE);

copyList->CopyResource(bufferReadback, bufferB);
copyList->Close();
copyQueue->ExecuteCommandLists(1, (ID3D12CommandList**)(&copyList));

copyQueue->Signal(fence, fenceValue);
fence->SetEventOnCompletion(fenceValue, fenceEvent);
++fenceValue;
WaitForSingleObject(fenceEvent, INFINITE);

After this you can call Map on resource.

unsigned int* data;
bufferReadback->Map(0, nullptr, reinterpret_cast<void**>(&data));

I hope this will help, let me know if you have any questions.


Bump mapping with triangles and height maps

The normal of a given point on the height map is perpendicular to the 2 vectors defined by gx and gy. The original surface normal is not relevant to this. So in tangent space, the normal is:

Vector tangent = Vector(1, 0, gx);
Vector bitangent = Vector(0, 1, gy);
Vector normal = normalize(cross(tangent, bitangent));

You then need to convert the normal from tangent space to world space. For this you need the so-called "TBN matrix" (tangent, bitangent, normal matrix). There are plenty of articles around explaining this. But the gist is:

Vector T = normalize(To_World_Matrix * intersection.tangent());
Vector B = normalize(To_World_Matrix * cross(intersection.tangent(), intersection.normal()));
Vector N = normalize(To_World_Matrix * intersection.normal());
mat3 TBN = mat3(T, B, N); // GLSL syntax

The last thing is to do a change of basis to move the normal from tangent space to world space:

Vector normal_world_space = normalize(TBN * normal);

Keep in mind that the order of some cross-products might be inverted in what I wrote if you get normals pointing inside the surface.


mapping 3d texture on view frustum (or part of it)

In techniques I've seen that use a frustum-aligned voxel grid (so-called "froxels"), it looks like option 2 in your diagram. The voxels are cuboids in post-projective screen space, so when transformed back to world space they look like mini-frusta, automatically expanding as they get farther from the camera.

Marching along eye rays is then very easy: you just step along the grid's Z axis. Summing optical density or in-scattered light along an eye ray is just a matter of iterating over the Z dimension of the texture. (Or you could try to apply methods like parallel prefix sum as well, but it may not be worthwhile, depending on the texture size.)

If you're rendering some geometry and you want to know which voxel it's in, you don't have to do any matrix transformations. Just use gl_FragCoord, which represents the screen-space position (including depth) of the current fragment. It comes in window units (i.e. pixels) so you'll have to remap it to [0,1] for texture sampling, or to voxel units if you're doing an image store.

Otherwise, for mapping world-space positions into the voxel grid, use the usual sequence of transformations. It looks to me like you got it right in your code snippet, assuming fragPos is in world space. For getting from the voxel grid back to world space, you'll need to invert that sequence of transformations.


Pixel density / color channel depth ratio for dithered gradients

There has been quite some research into this using Barten contrast sensitivity function. It is the current formula behind the Dolby Perceptual Quantizer as featured in SMPTE 2084 and HDR10.

This, coupled with a colour appearance model such as the work behind Dr. Mark Fairchild's CIECAM02, can result in very accurate predictions of quantization depth.


Convert triangulated object to a polygonized object

I guess what you wanna achieve is mesh simplification. Then those materials can be useful for you.

http://graphics.stanford.edu/courses/cs468-10-fall/LectureSlides/08_Simplification.pdf

https://pages.mtu.edu/~shene/COURSES/cs3621/SLIDES/Simplification.pdf


Issue with image load stores and compute shaders

Originally mistmatching image formats (GL_RGB32F instead of GL_RGBA32F) were used in the creation of textures and the call to glBindImageTexture.

This error was hard to track down because the format (without alpha) only mattered (in this case) in the compute shader.

Using GL_RGBA32Feverywhere fixed the issue.


Computing camera front direction from Euler angles

This kind of navigation works well for situations that are centered about objects. It keeps the up vector always pointing upward which makes it less possible for confusion.

Bringing quaternions into this mix is not necessarily a good idea. People often totally exaggerate the problems of Euler angles (or taint Tait–Bryan angles). Its true that Euler did not even consider the implications in interpolating the angles. True you can get into big problems if you rotate angles into certain positions and interpolate angle by angle. But this didn't bother Euler so much as he did mathematical modeling where the problem cancels itself out.

So Euler angles are perfectly fine for storing the rotation, also ok in differential rotation. And in case as no gimbal lock can really happen anyway, you get other problems before it. Euler angles are just not good at linear interpolation in a curved space.

In this case there should not be any bigger problems. Euler angles are much easier to understand. Unless you need to interpolate between 2 recorded positions. However this is a no issue as your collection and interpolation dont need to be based on the same model.

Its possible to look at this model in another light, you can think of it as a vector that records camera position in relation to a center as long as you keep the vector equal length you achieve same thing. You can then just form the matrix by multiplying by up vector and then that by front to get new up. This is even easier to interpolate unless you move trough the actual center but again you can keep normalizing the vector to a length.


Getting rid of branching to check if a variable is within a range in GLSL

This could be done that way:

First condition is float val = 1.0-step(shouldY, ActualY);

Then, the condition: state >= 20.0 && state < 40.0 can be changed to

step(20.0, state) - step(40.0, state). This equals 0.0 if outside of range and 1.0 if inside.

Let a = step(20.0, state) - step(40.0, state)

Then we know that mix function:

genType mix(genType x,
    genType y,
    genType a);

Is $$x * (1 - a) + y * a  = val * (1 - a) + (1 - val) * a  = val - 2*a*val + a$$

So final code is:

float val = 1.0-step(shouldY, ActualY);
float a = step(20.0, state) - step(40.0, state);
return val - 2.0*a*val + a;


How do you deal with clipping when rendering to a limited colorspace?

Effectively, before you start to think about clipping/clamping, you'll need a general approach to map the much wider color range you are working in onto the [0,1] triplets you want to output. There are various way to do this, look up HDR tone mapping to get a good first impression of what is possible. Simply clipping things to [0,1] will leave you with a very cramped color space to work in, throwing away much of the advantages of raytracying in "high dynamic range" (floats).

On to the actual problem at hand, to prevent clamped colours from shifting hue, a naive but functional approach is:

Take the max component m from (R, G, B)
If m > 1, scale all three components by 1 / m.

This does not take the relative luminance of the color components into account, but if you eventually end up doing something like tone-mapping anyway that would be a better time to tackle that problem.


correct rgb or cmyk code from some proportion of cyan, magenta and yellow

First off, the CMYK model includes black as its own channel, so you typically don't mix a combo of cyan, magenta & yellow to get black, you add black directly as its own independent element. There are a number of reasons for using black directly & without knowing your context, it's difficult to advise you on how to get by without it. What kind of black should I use when designing for CMYK print? on the graphic design SE has some in depth answers regarding use of black by itself & as a mixture (sometimes called composite black).

Second, CMYK is a subtractive model for mixing inks based on the notion of reducing brightness. RGB is an additive model based on mixing lights. Because they use different models & are both context dependent, there isn't a generalized conversion formula. The RGB to CMYK and back algorithm question on SO has a number of in depth answers regarding possible conversion algorithms. Again, it's hard to know what to suggest when you haven't clarified what you're using the colors for.


Texture baking can be accomplished by simply rendering the mesh in texture space.  In other words, you set up a render target matching the size of your texture, and draw the mesh with a vertex shader that sets the output position to the vertex's UV coordinate (appropriately remapped from [0, 1] UV space to [−1, 1] post-projective space).

The vertex shader can still calculate the world-space position, normals, and whatever else it needs and send those down to the pixel shader.  Then the pixel shader can do its thing without even being aware that it's rendering into texture space instead of the usual screen space.  Lighting and shading calculations will work as usual as long as the pixel shader inputs are hooked up correctly.

You don't have to do any complicated inversion operation; you just take advantage of the GPU rasterization hardware, which is happy to draw your triangles at any coordinates you choose.

Naturally, this requires that your mesh already has a non-overlapping UV mapping that fits within the unit square, but texture baking doesn't really make sense without that.


What exactly is the orthographic projection used by Matlab

All of the above. If you look on matlabs page a little further down, it becomes apparent that matlab initializes a canvas (the screen), then looks for each pixel what is directly behind that screen. This gets rid of perspective. When you set the camera angle to 45 degrees down and 45 degrees left/right, you will get an implicit isometric projection. So really the "projection" just depends on your camera angle.

Sidenote: if you would want to keep a 3d perspective, you would need to draw the ray from the camera origin to the position on the canvas. That gives the ray the direction it needs to create perspective.


Where should the ray origin be put in perspective camera ray tracing?

I don't get what you don't understand. All rays originate from the camera so It's basically the start of the camera's pyramid or more technically the viewing frustum.

Depends on the system you are using. Maybe your camera is fixed at the origin and only the world rotates/moves. In this case, usually the camera is fixed at the origin looking in either the +Z or -Z direction depending on if it's left or right handed coordinates system. So the ray origins will be fixed at (0,0,0).

If your camera moves, however, the ray origins  also move to where you place the camera.


Expressing a reflected ray at a point as a function of the incoming ray and the normal to the surface at that point

$N \cdot L$ is the scalar length of the projection of $L$ on $N$ (assuming $|N|=1$).

$(N \cdot L)N$ is the actual vector with the length of $N \cdot L$ in the direction of $N$.

There is often a confusion when people say "projection of this on that" whether they mean just its length, or the actual vector resulting from the projection. In this case you want to combine it with another vector, so you need the vector version. The correct reflection formula is thus: $$R = 2(N \cdot L)N - L$$


First of all, you can get caustics just by Path Tracing. Caustics isn't a difficult phenomenon in computer graphics. Almost any global illumination algorithm can render it. It's just a matter of the converging speed.

While (naive) Path Tracing can render caustics, it takes a long time to clean the rendered image due to how the algorithm works. Photon Mapping makes the converging speed faster by doing some tricks on how light paths are interpolated. Bi-Directional Path Tracing on the other hand tries to make some difficult-to-sample light paths easier.

Besides the two algorithms, Metropolis Light Transport can render caustics efficiently by finding the most significant light path in the scene and exploring other possibilities around it.

Here are some good lectures on:

Ray based rendering algorithms
Path Tracing
Photon Mapping

There is the original paper of BDPT. It's not too difficult if you can implement explicit light sampling and multiple importance sampling by your self.

Also, I recommend the book Physically Based Rendering: From Theory to Implementation. It talks about all the algorithms above and more. It is basically a must have if you want to dive deep into computer graphics.


Why for perfect reflections a surface must have G2 continuity?

What you see on reflects is the n-continuity of normals, which are the derivative of positions. -> a G1-only surface would have G0-only normal field, i.e.,  with sudden change of gradient in the normals (and thus, the reflects), that the eyes can notice. G2 surfaces have G1 normals fields, which is smooth enough for your eyes.


Are lookup textures still used for anything?

Yes, lookup textures are still used. For example, pre-integrated BRDFs (for ambient lighting, say), or arbitrarily complicated curves baked down to a 1D texture, or a 3D lookup texture for color grading, or a noise texture instead of a PRNG in the shader.

ALU is generally cheaper than a texture sample, true, but you still have a limited amount of ALU per frame. GPUs are good at latency hiding and small lookup textures are likely to be in the cache. If your function is complicated enough, it may still be worth using a lookup texture.


Additive blending with weighted-blended order independent transparency

I have worked with this specific formula for the OVER operator but not with additive blending. I'll use the paper's nomenclature in the following discussion:

$$ C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}\alpha_i \cdot w(z_i, \alpha_i)}(1 - \prod_{i=1}^{n}(1 - \alpha_i)) +  C_0\prod_{i=1}^{n}(1 - \alpha_i) $$

This is not explicitly stated in the paper, but the term $$C_i$$ is the premultiplied-alpha color (i.e. color.rgb * color.a)

As described in the paper, the term
$$ C_0\prod_{i=1}^{n}(1 - \alpha_i) $$
provides the "revealage" of the background color. If all the transparent surfaces are transparent, the product will be 1 and the background will be fully visible. The rest of the equation provides an approximation of the result of sorting the transparent surfaces by distance and using the OVER operator with pre-multiplied alpha colors.

However, the equation for additive blending (using glBlendFunc(GL_SRC_ALPHA, GL_ONE) and glBlendEquation(GL_FUNC_ADD)) without weights is:
$$ C_f = \sum_{i=1}^{n}\alpha_iRGB_i + C_0 $$

This equation is already order independent! In order to add weights to the transparent surfaces with a normalization step in the end, the equation can then be simplified to:

$$ C_f = \frac{\sum_{i=1}^{n}C_i \cdot w(z_i, \alpha_i)}{\sum_{i=1}^{n}w(z_i, \alpha_i)} +  C_0 $$

If you'd rather keep the same equation as before, you can achieve the same result by changing the shader outputs in listing 3 to:

gl_FragData[0] = vec4(Ci, 1) * w(zi, ai);
gl_FragData[1] = vec4(0);


Raytracing: why are the spheres in the image below appear stretched?

Shapes appearing stretched in the periphery is a consequence of perspective projection. The wider the field of view (FOV) is, the stronger the stretching effect gets.

To demonstrate the effect I wrote a quick example on ShaderToy: https://www.shadertoy.com/view/MltBW2

As you can see on the images below (corresponding to FOV of 40, 80 and 120; if I didn't make any mistake), this becomes especially noticeable with wide FOV, like 90° and above.


How do you interpolate UV mapping coords in a quad tessellation evaluation shader?

The problem was else-where, the same interpolation works for UV coords.

vec2 uv1 = mix(teUv[0], teUv[1], gl_TessCoord.x);
vec2 uv2 = mix(teUv[2], teUv[3], gl_TessCoord.x);
fUv = mix(uv2, uv1, gl_TessCoord.y);


Non jagged line algorithm for javascript canvas

The problem you are seeing, i.e. "jaggies" or "staircasing", is an example of the more general problem known as "aliasing" and, in the graphics field, the term you want to search for is "Antialiasing".

Aliasing occurs when you undersample a signal. If a signal contains frequencies at or above the Nyquist Frequency, which is 1/2 the sampling frequency, those higher frequencies will come back "in disguise" i.e. "under an alias".

The example I often give to new starters to explain the problem is:

  Imagine you've started at a new job and work solidly, 9 to 5, except for a 1hr break from 12 to 1.
  The boss, however, regularly walks around the building at 12:30 and never sees you at your desk. He therefore concludes you are lazy and so don't get a pay rise

That is an example of aliasing. The boss needs to sample at a (much) higher rate. (Randomised/stratified sampling would also help :-) )

In your line drawing example, I expect you are taking one sample per pixel, but if you do a Fourier analysis of a line, you will see it contains an infinite spread of frequencies. It's these higher frequencies (plus the reconstruction of the sampled results - which I've ignored) that can lead to the jaggy results.

The ideal solution is to low pass filter your incoming signal before sampling it, but that's 'nontrivial' with geometric data.

There are, however, multiple practical approaches to mitigating the problem, including supersampling (SSAA) and multispampling (MSAA), but in your case, perhaps something like Wu's method for antialiased line drawing will suffice.


The edge between the sphere and the background is actually the one that is incorrect; you need to initialize your normal texture with a unit normal to get correct results.

The two pixels thickness is a limitation of the Sobel based edge detection and other 3x3 convolution filters: you can only detect edges twice as big as your pixels. The Robert operator uses a 2x2 convolution filter with weights making a cross, so it yields thinner edges but they are still thicker than one pixel.

If you absolutely want one pixel width, you could use filtered texture sampling and sample every half pixel when applying the Sobel operator, but the detection will probably miss some features.


How to compare anti-aliasing effects on images ?

What you want to do is compare your anti aliased results against a "ground truth" image.

The ground truth image is the same image but without aliasing.

There are many ways to make an alias-free image, but a straight forward way would be by doing super sampling.

Super Sampling

When we render, we usually take a single sample at the center of the pixel (rasterize / shader / etc it to make the color).

Super sampling works by taking $N$ samples for that pixel, in random parts of the pixel and averaging the result.

The more samples you take, the closer you get to the ideal "alias free" image.

One simple way to do super sampling is to render the image at a higher resolution and then shrink it down to a smaller image.  For instance, if you render at double the height and width and then shrink the image down, that's the same as taking 4 samples per pixel.  However, going this route, the samples are evenly spaced on a grid, not randomly placed within each pixel.  Making the samples random instead of evenly spaced is really important to this monte carlo integration working, but evenly spacing them on a grid is a cheaper method that is better than nothing (aka useful in realtime situations sometimes).

Another way to do super sampling would be to render the image at normal resolution $N$ times, but in each render, you randomly offset the camera by a sub-pixel amount.  You then average your $N$ images together.  That will give you the random sample points, but of course each pixel has the same random sample points.

This is why you will often see sub-pixel jittering of the camera when doing temporal anti aliasing: it allows for better anti aliased results (a better integration) over time when combining multiple frames.  If they were all in the same position every frame, you wouldn't get any more information about the pixel.

Doing these methods will give you your ground truth alias free image, if using enough samples.

Comparing vs Ground Truth

The next step would be to compare the other anti aliased techniques against the super sampled ground truth.

There are lots and lots of ways that you might want to analyze this data, but I'll give a few ideas.

One way could be to make a texture where each pixel is the absolute value of the difference between the images for that pixel.  This would let you see the entire image as a whole and get an idea of how different it was from the ground truth.

Another way could be to calculate the mean and standard deviation of the difference of the images. This would give you an idea of how much on average pixels differed in the images, while also giving you an idea of how much variance there was in the difference. A high variance means some places are much worse than other places, so isn't very consistent.  Ideally, the best AA method will have the lowest mean, and the lowest variance.

Lastly, since aliasing is ultimately a "frequency" thing, you might find interesting data in doing a discrete Fourier transform on your images and comparing the frequencies in the AA method images vs the frequencies in the super sampled image.

More info on taking DFT of images here: https://blog.demofox.org/2016/07/28/fourier-transform-and-inverse-of-images/


Why sending data from gpu to cpu is slower than cpu to gpu?

The actual sending of data is the same. The PCIe bus is the same speed in both directions.

However when programming there is a big difference namely that when you send you can immediately start doing something else (including queuing other operations using that new data) while the actual transfer is going on. But when receiving you need to synchronize on the completion of the transfer before you can use the data that was sent.


Skybox is rendered on the model instead of surroundings

A skybox is a (large) cube that encompasses the entire scene and contains 6 images of a surrounding environment, giving the player the illusion that the environment he's in is actually much larger than it actually is.

In order to do this, you need to draw a Cube (or a Sphere) in your Scene that will represent the Skybox. You then need to sample the Skybox Texture (shaderTexture in your shader) to project it into the geometry.
This is exactly what you are doing with your Sphere Model in your Pixel Shader.

The problem you have, is that your Model is too small and your Camera is outside of the Skybox. You need to make the Skybox way bigger, and place your camera inside of it.
The best solution is to center the Sky Sphere about the camera in world space, this way when you move the camera around, the Sky follows the camera, giving the illusion that it's infinitely far away and you can't get closer.

PixelInputType ColorVertexShader(VertexInputType input)
{
PixelInputType output;

// Use local vertex position as cubemap lookup vector.
output.position = input.position;

// Transform to world space.
float4 positionWorld = mul(float4(input.position, 1.0f), worldMatrix);

// Always center sky about camera (You need to pass the camera position).
positionWorld.xyz += eyePositionWorld;

// Set z = w so that z/w = 1 (i.e., skydome always on far plane).
output.positionSV = mul(posW, viewProjectionMatrix).xyww;

return output;

}

To keep the Skybox fragments always on the far plane (z component = 1.0) you can set the z component to w. This will turn into 1 after the perspective division is applied.
With this little hack you can render the SkySphere after having rendered all your meshes, and they would all be rendered on top of it.

You may also want to do the matrix multiplication on the CPU and pass it in as another parameter for performance reasons.


Explanation of the Marching Squares saddle points resolution

Imagine that a black dot represents a value of -1 whereas a white dot represents a value of +1. You are looking for the iso-line(s) where each point upon the line is 0.

For this example you could either place the iso-lines like on the left or the right:

 or

The difference between the solutions is the value in the center. In the left case we assume 1s whereas in the right solution we assume -1s. So we check the center value and based on that value decide which solution fits best. If the center value is 1, we pick the left solution. If the center value is -1, we choose the right solution.


2D sampling with multidimensional transformations

I'm not sure I've correctly understood the question, but here goes.

You're trying to sample directions uniformly, so you've got $p(\omega)$, which is the probability of getting a particular direction. But what is a direction? You actually need your probability distribution to produce numbers in some representation, and the easiest representation to deal with is lat-long (i.e. two angles). So the thing you actually need to sample from is the probability distribution of pairs of angles. This is what $p(\theta, \phi)$ is: the joint probability of two variables.

$p(\omega)$ and $p(\theta, \phi)$ mean the same thing geometrically, but the former gives you an abstract direction you can't sample from directly, while the latter more usefully gives you two numbers that represent a direction.

The reason for your third bullet point is to do with the point you've made about how it isn't just a single direction. These aren't really functions: they're distributions. A direction is infinitesimal, so you can't have a probability of just one direction. What you actually need to do is integrate it over the directions you're interested in.
$$
\int p(\omega)d\omega = \int_0^{2\pi}\int_0^\pi p(\theta, \phi)d\theta d\phi = 1
$$

Whichever representation you use, the integral over the hemisphere has to be 1, because it's a probability distribution.

I'm not sure if I need to explain this or if you already understood, but here's the origin of the $sin(\theta)$. When you do the double-integral on the right, you're splitting the problem up into a series of rings, or slices of the unit sphere. Each ring has constant $\theta$ while $\phi$ goes from $0$ to $2\pi$. Also, the area of each individual ring decreases as $\theta$ increases: the ring at the equator is huge, while the last "ring" at the pole is tiny. The area decreases as $sin(\theta)$. Because we want each unit of area of the sphere to have the same probability, we need the smaller rings to get a smaller share of the probability.

As Florian R. explains, you can do that by including the $sin(\theta)$ factor in the integral, or you can put it inside the definition of $p(\theta, \phi)$ like the book does.


Global illumination leading to image variation

If you can make your samples deterministic (the same from run to run - don't base random sample points on time or any other non deterministic value), it will be a stable rendering that you get every time.


How can I convert signed distance field to a mesh?

with CGAL you can generate mesh by implicit function. https://doc.cgal.org/latest/Mesh_3/index.html

Search for "implicit". There is an example of generating meshes from the funciton of a sphere.


Diffuse lighting calculations in ray-tracer

Some elementary trigonometry tells you what to expect from this situation.

The angle to see the shadow terminator is marked on the diagram, and a use of SOHCAHTOA tells you it's $\cos^{-1}\tfrac{1}{2} = 60^\circ$. Yours looks higher than that so your intuition seems correct. Stepping through the lighting code will help you see where it's going wrong, and you should consider writing unit tests for it, so that it's easier to provoke bugs like this in isolation.

Something else you might try to help narrow down the problem space is replacing the diffuse calculation with 1 iff $L.N > 0$ (i.e. if the light is in front of the surface), 0 o/w. That will give you a sharp line instead of a gradient, and if that sharp line is in the wrong place, you know the input vectors are wrong. If it's in the right place, the problem is in the diffuse shader itself.


Efficiently transferring only needed parts of the vertex data to the GPU (C++/OpenGL)

This more or less a long comment than an answer.
Some other options that come to mind are the following:

A little old school, but you can create an interface with one of the texture objects. You can query different mipmap levels for your needs inside the shader. Textures are one of the better cached objects in OpenGL.

You can defer the lightening process by sending everything to a framebuffer with multiple rendering targets. The first pass would filter out the relevant parts of your data and create a geometry buffer. You can use the g-buffer for lightening pass afterwards.

You can create a flat array where your relevant and non relevant data are divided in equal strides, then use the indices of the relevant parts stored in your Element Array Buffer object in glDrawElements call. Basically you can use something like the following:

struct MyRealData {
vec3 myRelevantData
float myNotSoRelevantData
};
void to_drawable(MyRealData[20] ds, vec3[40] flat_drawable_array){
  for (int i = 0; i < 40; i+=2){
    flat_drawable_array[i] = ds[i].myRelevantData;
    flat_drawable_array[i+1] = vec3(ds[i].myNotSoRelevantData, 0, 0);
  }
}
std::vector<unsigned int> indices[] = {
  0, 2, 4, // first triangle
  2, 6, 4, // second triangle
  4, 6, 8, // third triangle
// ... etc
};
.
. // later in the code
.
glDrawElements(GL_TRIANGLES, indices.size() , GL_UNSIGNED_INT, (GLvoid *)indices.data());

```


Why is my fragment shader not showing any colors?

After checking and rechecking my code over and over again. I finally made it work.
The problem was that I was creating the buffers and assigning locations to the position and the normals buffers

// Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
// Normals
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);

However in the vertex shader I was not setting the locations

#version 410

in vec4 vposition;
in vec3 vnormal;
...

So changing the previous code to

#version 410

layout(location = 0) in vec4 vposition;
layout(location = 1) in vec3 vnormal;

fixed the application.
Now, I am not really sure why this works, but I remember reading somewhere that OpenGL assigns locations as it sees best, so maybe in my code the location for the normal was not the same as the enabled vertex attrib array. I let someone more experienced clarify this.


List of triangles to minimum amount of convex polygons

If a edge corner is concave then it needs to border 2 of the output polygons.

So one algorithm would be to find all concave corners (including the ones in the holes) and making cuts starting from them to other concave corners. This will split the polygon in two or join 2 holes into 1 or connect a hole to the outside.

The cut from a concave corner should be constrained by the angle or it will create a new concave corner that then needs to be cut again.