You are not too far off with your second averaging approach. The problem is, that the area is the wrong weighting factor for what you want to achieve. You want each of the 3 sides of the cube to contribute equally to the vertex normal, but you need to extract the information from the adjacent triangles. The area and the number of triangles are bad weighting factors since they vary with the number of triangles per side. But one thing stays always the same at each vertex: The angle between two edges at the side. So you just need to take the angle of each triangle connected to the vertex and use it as a weighting factor for its normalized face normal. The weighting factors will always sum up to 90°/$\frac{\pi}{2}$ per side of the cube. Look for example at the bottom left vertex at the front in the image you posted.

Your first approach fails because it yields:

$$N_v = \frac{2*N_l + 2 \cdot N_f + 1 \cdot N_b}{5}$$

where $N_l$ is the left, $N_f$ the front and $N_b$ the bottom side normal. Assume them to be normalized. The factors result from the triangle count at the vertex and their sum.

Your second approach fails because it yields:

$$N_v = \frac{N_l + 0.5 \cdot N_f + 0.5 \cdot N_b}{2}$$

Here the factors result from the fact, that only the left face has all its triangles connected to the vertex. The bottom face connects only 1 of 2 and front face only 2 of 4 equally sized triangles to the vertex.

If you take the angles, you get:

$$N_v = \frac{2\cdot 45 \cdot N_l + 2 \cdot 45 \cdot N_f+ 90 \cdot N_b}{270}$$

Now each side contributes equally and independent of the number and size of triangles connected to the vertex.

EDIT:

I just realized, that the front face also contains only 2 triangles. The diagonal of the back face triangles irritated me. However, this will not affect the conclusion but the weigting factors change. For the fist approach you get:

$$N_v = \frac{2*N_l + 1 \cdot N_f + 1 \cdot N_b}{4}$$

The second remains unchanged and for the angles you get:

$$N_v = \frac{2\cdot 45 \cdot N_l + 90 \cdot N_f+ 90 \cdot N_b}{270}$$

which is still correct. What is interesting is that both your approaches give the same results for the shown cube, since a connection of the vertex to 2 triangles also means that the area weight is doubled. You can also see this if you compare both pictures.


Choosing corner values for trilinear interpolation

As a rule, SDFs do much better under interpolation than regular images do—it’s why you can mostly get away with using tiny textures for e.g. font data. You should be fine interpolating neighboring voxels.


Troubleshoot half vector sampling from a distribution (cook-torrence, trowbridge-reitz, etc)

The general idea for sampling half vector based distributions is that you generate $H$ and then compute $w_i$ by reflecting $w_o$ about $H$. This is so $H$ will be the half vector of your $w_i$ and $w_o$ pair. It is standard reflection:
$$w_i = -w_o + 2(w_o\cdot H)H $$

How you generate $H$ depends on the specific distribution. Generally, it is done in polar coordinates, with the angle from your distribution's center being picked using some specific function. Then the azimuth will be a uniform distribution, unless your distribution is anisotropic, in which case it gets more complicated.

For example, with Cook-Torrance, it goes something like:
$$\tan \theta = m \sqrt{ - \log \xi_1 }$$
$$\phi = \xi_2 2\pi$$

Then, given an orthonormal basis made of vectors $N$, $a$, $b$:

$$H = a\sin\theta\cos\phi + b\sin\theta\sin\phi + N\cos\theta$$

As for problems in your code, replacing this:

vec3 rd = normalize(vec3(screenUv, z));

// remap 0,1 to -1,1
vec3 wo = (rd * 2.) - 1.;
// wo is outward facing
wo *= -wo;

with:

vec3 wo = normalize(vec3(screenUv*2.0-1.0, -z));

Gives me a much nicer plot. Your remapping was incorrect as it was done on a vector which includes z and is no longer in 0,1 for x and y because of the normalization. This explains why the center was not in the center of the frame and the whole thing was leaning. Removing wo *= -wo; (a transformation which makes no sense) and using -z instead fixes what I think you were calling the hard transition in the 4 quadrants. That was caused by squaring the components of the vector.

The remaining glitch in the center appears to be numerical issues. Fixing that will require reworking the code to better handle some cases (likely where you have the 0.0008 constant for a sin and the 0.9999 for a cos).


Volumetric rendering fundamental concepts and terminology

When I was first reading about all of this I stumbled upon this link which helped me better understand this large subject.  Also this goes into some more detail on things mentioned here.
Light scattering is a natural phenomenon which arises when light interacts with particles distributed in a media as it travels through it.  From Wikipedia:

Light scattering can be thought of as the deflection of a ray from a straight path, for example by irregularities in the propagation medium, particles, or in the interface between two media

In computer graphics there are models that have been developed to simulate the effect of light traversing volume objects from an entry point (Point A) to an exit point (Point B).  As the light travels from A to B it is changed due to interactions with particles and these interactions are often referred to as Absorption, Out Scattering and In Scattering.  Often you will see these split into two groups; Transmittance (Absorption and Out Scattering) which I like to think of as 'light lost' and In-Scattering ('light gained').
Absorption is basically incident light energy that is transformed into some other form of energy and therefore 'lost'.
Transmittance
Transmittance describes how light reflected behind a volume will be attenuated due to Absorption as it travels through a medium from A to B.  This is usually calculated with the Beer-Lambert law which relates the attenuation of light to the properties of the material through which it is travelling.
As the light travels through the medium there is a chance that the photons can be scattered away from their incident direction and therefore not make it to the eye of the observer and this is referred to as Out-Scattering.  In most models the Transmittance equation is changed slightly to introduce the concept of Out-Scattering.
In Scattering
Above we have seen how light can be lost due to photons been scattered away from the viewing direction.  At the same time light can be scattered back into the viewing direction as it is travelling from A to B and this is called In-Scattering.
Particle In-Scattering itself is a pretty complex topic but basically you can split it into Isotropic and Anisotropic scattering.  Modelling Anisotropic scattering would take a considerable amount of time so usually in computer graphics this is simplified by using a Phase Function which describes the amount of light from the incident light direction that is scattered into the viewing direction as it travels from A to B.
One commonly used non-isotropic Phase Function is called the Henyey-Greenstein phase function which can model Backward and Forward scattering.  It usually has a single parameter, g ∈ [−1,1], that determines the relative strength of forward and backward scattering.


How is the multiplication in Gaussian Blur implemented

Each color is conceptually treated independently. If they were concatenated, multiplying a value with a color close to the maximum possible value for one channel could cause it to overflow into the lower bits of the next.
That said, if you’re asking for performance purposes, a lot of the hardware that does this kind of work can perform all of the per-channel multiplies in a single operation.


During the implementation, the way rays are scattered does not actually change and remains random.

Actually the way rays are scattered does change, specifically when you sample a light. In chapter 8 he makes a mixture pdf in order to sample either the light or the bsdf.

  What changes looks to be the contribution of each ray.

This does change, but not specifically due to the sampling of the lights but rather due to importance sampling. But that was already introduced in chapter 4.

Basically you have the following:
$$I = \int_{\Omega}f(x)\,dx = \int_{\Omega}\frac{f(x)}{p(x)}p(x)\,dx = E\left[\frac{f(X)}{p(X)}\right] = \frac{1}{N}\sum_{i=1}^{N}E\left[\frac{f(X_i)}{p(X_i)}\right] \approx \frac{1}{N}\sum_{i=1}^{N}\frac{f(x_i)}{p(x_i)}$$
Where $X$ and $X_i$ are distributed according to the probability density $p$.
As evident the main difference to the Monte Carlo formulation you are probably used to is the $p(x)$ factor, and the fact that $x_i$ are not uniformly sampled but rather sampled according to $p$. Note that for uniform sampling $p(x)=1$ and the equality still holds. Thus this is simply a generalization.


gamma transform in webGLSL: when already done or yet to be done?

This is a hard problem since the systems do not in fact tell you how it should operate. The problem is that there are several ways to address this issue:

Apply a LUT to all output
Let the system color manage
Let each application color manage

Nearly all of our color management systems are borderline braindead. There is really no sane way to ensure that you are doing the proper thing without extensively testing the system. You can not ask or specify your intent. In case of multi operating system situations. If there is reason for me to color manage something myself im at the mercy of each operating system peculiarities.

For a alternate discussion on this see this stackoverflow post. But its not really a robust enough talk to cover all cases.


Using multiply and accumulate of 4x4 matrices for ray-triangle intersection tests on GPU

Yes, it is possible.  For one however, Möller-Trumbore is not the only algorithm out there for ray triangle intersection, there exist others.

However all of these rely on linear algebra vector multiplications and matrix operations.  These can be combined into 4x4 tensor core operations (and each tensor core can do 4x4x4, but there are 8 cuda cores to every tensor core).   You can compute multiple intersections in Möller-Trumbore at a time with tensor cores.  You could say, combine multiple cross products or dot products into a single matrix operation.

The catches?  Well first, the precision of tensor cores matrix multiplication is 16bit float.  But don't fret, given decent spatial subdivision of, say, a raytraced environment, that precision should only matter per spatial block/voxel/subdivision which is necessary in ray-tracing in order to not test all triangles in the scene. 16 bit for a 10 km area might be a big deal in terms of poor position precision, but for a 2x2 meter area it isn't (mantissa alone will handle 1024 different values). Note the addition part is 32bit float.

Second, you have to move data around in such a way that tensor cores can actually access it, which, because it is unlikely that any of us on this entire site have direct access to a machine with tensorcores, has a yet unknown performance cost.

Third, I'm not entirely sure its possible to do both tensor core calculations and scalar calculations at the same time.  This could end up slowing many tasks to the point that any advantage tensor cores gave becomes negligible.  But I could be wrong and we can actually hide things like latency for tensor core memory moves with multiple floating point and tensor core instructions interleaved.


Section 6 of Microfacet Models for Refraction through Rough Surfaces has a good description of how they did it to validate their own model. That may not be everything needed to build a full database (eg. more automation) but it's an interesting read.


Whenever there's too much churn of things being created and destroyed, regardless of the specifics of the situation, a common way to dealing with this is to make free object pools.

How these work is when you are done using something, instead of actually freeing or destroying it, you put it back into a list or array of "free objects".

When you need a new object of a specific type, you check the object pool to see if there's a free one lying around.  If there isn't one there, you create a new one the "expensive" way and use it.  When you are done with it, you put it in the free pool for use in the future.

A possible issue with free object pools is that you may have a spike in objects for some reason and then you are left with a ton of unused objects sitting in a free pool that will never be needed again.  In situations like this, you can keep track of how long (in number of frames for instance) since an object was last used, and if they get over a certain unused age, free them from the object pool.

PS - make sure and profile your code to find what the ACTUAL performance bottlenecks are before attempting to solve problems.  Optimizing without profiling before (to find the problem) and after (to verify you improved things, and knowing by how much) won't get you very far (:


Both T-splines and subdivision surfaces are capable of handling an arbitrary topology input mesh, whereas NURBS can only handle meshes with regular topology.

Complex NURBS objects are therefore made out of multiple regular meshes. These meshes are trimmed and fit together to form a single complex object. However, along the trimming lines of the mesh discontinuities can occur. This is because the boundary curve of a trimmed NURBS patch is not in general a NURBS curve. This complicates the joining of several NURBS patches, potentially sacrificing water tightness.

Subdivision surfaces are able to handle meshes with arbitrary topology. This means your mesh can contain extraordinary faces (faces with more or less than four sides) and extraordinary vertices (vertices with a valency other than 4). The generated surfaces are in general curvature continuous in regular regions and tangent plane continuous at extraordinary vertices. The evaluation of a subdivision surface is an iterative process. Although regular regions can be converted to B-spline patches problems occur when rendering the irregular regions as an infinite number of B-spline patches will be generated. The OpenSubDiv library by Pixar is a good start for speedy subdivision as it calculates many things on the GPU.

Most subdivision surfaces are based on uniform subdivision and some work has been done to handle non-uniform and rational subdivision, but it is quite extensive and has some limitations.

T-splines can do everything NURBS can do as well. The most striking feature of T-splines is the ability to handle T-junctions, as well as arbitrary topology, without sacrificing in surface continuity. This allows the designer to insert more detail in some places without it effecting the mesh in other regions. In this way it is possible for a very organic design process. Take for instance this video. A downside of T-splines is that it is a patented technology.


Rounding corners of polygon given vertices of its corners

Ok, Xenapior and Reynolds together have the right idea. But the explanation is a bit lacking so here is a image to explain it all and some further musings. First let us  start by drawing an image (yes i know that is what they say in school for you to do but nobody does it).

From the image we can see that there are 2 equal right triangles $V_2, A, C$ and $V_1, B, C$. In this triangle we have one unknown that we can define namely rounding radius $r$, also we know right angle is 90°. The angle between the line $V_1-V_2 = \vec a$ and line $V_2-V_3 = \vec b$ is easy to compute with  the formulation fo angle between vectors

$$\cos(\beta) = \frac{\vec a·\vec b}{ |\vec a|·|\vec b|}$$

That in turn can be simplified if the vectors already are normal. Thus three things of the triangle is known, which means all is known. So if you know the rounding radius to use the calculating the points $A$, $B$ and $C$. So finally:

a = normalize(V2-V1);
b = normalize(V2-V3);
halfang = acos(dot(a, b))/2.;
// skip center if you iuse splines
C = V2 - r / sin(halfang) * normalize((a+b)/2);
A = V2 - r/tan(halfang)*a;
B = V2 - r/tan(halfang)*b;

You can simplify this a bit with trigonometric identities. Or if you use rational B-splines you can skip the calculation of C

Note: that this is only one possible formulation


You're tilting at windmills trying to learn "GPU assembly", and it's due to the differences between how CPUs and GPUs are made and sold.

Each CPU has what's called an instruction set architecture, for example x86 or ARMv8. The instruction set is the interface between the user of the CPU (i.e. the programmer) and the chip. The chip designer publishes the details of the instruction set so that compiler vendors can write compilers to target that instruction set. Any CPU that uses that instruction set can run the same binaries. (Extensions like SSE make that slightly untrue, but they only add new instructions: they don't change the structure of the binary.) When the vendor creates a new processor family, it could have completely different micro-architecture internally, but the same instruction set.

GPUs are not like this at all. For best efficiency, the instruction set is usually closely tied to the micro-architecture of the CPU. That means each new family of GPUs has a new instruction set. GPUs can't run binaries made for different GPUs. For this reason, the instruction set usually isn't published: instead, your interface to the GPU is the driver published by the vendor for each graphics API (OpenGL, Vulkan, DirectX, &c.). This is why the graphics APIs have functions to take the source code of a shader and run it: the compiled shader only runs on the same model or family of GPU it was compiled for.

The closest you get to GPU assembly language is SPIR-V. This is an industry-standard intermediate representation, which GPU vendors are starting to support. It's like a GPU equivalent of LLVM's intermediate representation. It allows you to do the parsing and source optimization parts of compilation up-front to get a SPIR-V file, and then the GPU driver only needs to compile that to the GPU's instruction set at load time.


Explanation of the Vatti clipping algorithm

(Promoting "comment" to an answer)

It looks to me that it's just finding monotonic runs of edges. Given a defined winding order (in this case anticlockwise), then you can identify {P6, P7, P8, P0} as a decreasing run, as is {P2, P3, P4}. Since the left most vertex, P8, is in (**the middle of) a decreasing run, the decreasing runs define left boundaries and, therefore, increasing runs are right boundaries.

**it just occurred to me that if the left most point is at the beginning/end of a monotonic run then a slightly more involved rule will need to be applied involving the edges entering/leaving that point.


How RGB images are formed when normalized between 0 and 1

Let's suggest an analogy. I have a distance of 1 centimeter and 2.54 centimeters. If I transform the latter distance to inches, then it's 1 inch. This has the same value as the first distance.

But 1 inch is still longer than 1 centimeter, no matter the fact that they both use the numeral 1. These numbers are attached to different units, so simply comparing their numerical values is meaningless.

So it doesn't matter if the 8-bit unsigned, normalized value of 255 happens to have the same value of 1. Because you cannot compare them when they are in different spaces like that. Your original values were both in 8-bit normalized, unsigned integer space. If you want to compare them in a floating-point space, you have to transform both of them.


Calculate aspect ratio from 2D shape in 3D space

The ratio is with a quick and dirty visual measurement $665:501$ which is approximately $5:4$. You can measure it by taking the ratio of the vanishing angles $\alpha/\beta$ (see picture 1) because we are so close to the center.

Image 1: Ratio of the inbound angles

We can check the situation visually by drawing a 2 point perspective grid. For this we need the center line between the vanishing points.

Image 2: Seems about right.


Should not specular reflection on a rough surface be similar to diffuse reflection?

No, because the underlying physics is not the same, nor the lobe shape - not to speak of their parameters such as color and Fresnel term.

Specular is really true surface interaction with the interface material/air, so it has Fresnel modulation and the internal medium has no influence on colors. But the surface condition strongly influence the reflectance, of course. Think of it as the reflections on ocean surface.

Diffuse is due to the subsurface scattering, light entering the medium, and thus gains the color characteristic and loose directionality. Think of it as the green color of the water turbidity. If depth of penetration is less than pixel size CG people don't call it "subsurface" but the physics is the same.

Of course diffuse input is what specular let pass, which is angle (and polarization) dependant.

Beside, there exist transparent medium with internal interfaces (e.g. thin shells), so case exists were light goes inside but still acts specularely (or even wavely) and not diffusely. Oppositely, most plastics and paints/varnishs and biological medium are intrinsically transparent, but contain pigments (often based on a metal atom) that cause the opacity (diffusion or specular on these "objects in the object"). Think of them as the fishes in clear water :-) .


The short answer: no, but if you are interested in details, please keep reading (:

About lighting units

Light “brightness” is indeed quite poor/ambiguous layman’s definition for brightness of a light source. Below is a list of different lighting properties/units commonly used in lighting calculations that define the light “brightness”. I listed both radiometric and photometric [in brackets] properties/units. Radiometric units are Human Visual System (HVS) neutral "physical" units defined based on Watts (W), while photometric units are HVS weighted units defined based on Lumens (lm).

Photometric units are commonly used in rendering because practically all consumer image input and output devices operate in these units as they are designed & optimized for image acquisition & consumption by normal tristimulus (LMS) HVS. Proper conversion between photometric & radiometric units isn’t simply a matter of multiplication by some factor (like between kilometers & miles or kilograms & pounds), but different projection from Spectral Power Distribution (SPD) of visible light spectrum (explained later). Some people use constant luminous efficacy of 683 lm/W to convert between the units, but this has very little touch with reality and results in unrealistic values.

Radiant Flux in Watts (W) [Luminous Flux in Lumen (lm)] - Total power emitted by a light (regardless
of shape or size)
Radiant Exitance in W/m^2 [Luminous Exitance in lm/m^2 or Lux] - Power emitted by a light per unit area to all directions (think different size light sources with equivalent Radiant Flux)
Radiant Intensity in W/sr (sr=steradian) [Luminous Intensity in lm/sr or Candela] - Power emitted by a light to certain direction (think of a spot vs omni light with equivalent Radiant Flux)
Radiance in W/sr/m^2 [Luminance in lm/sr/m^2 or Nits] - Power that falls on a patch of surface from some direction (e.g. pixel on screen or patch of surface from certain direction)
Irradiance in W/m^2 [Illuminance in lm/m^2 or Lux] - Power that falls on a patch of surface regardless of direction (e.g. hemispherical sky illuminating a patch of ground).

It’s important to understand the difference between these properties when performing lighting calculations, just like it is important not to confuse properties of length and speed when doing physics calculations. There are various other light properties but having good grasp of the above gets you pretty far already.

Visible light spectrum and RGB projection

Visible light spectrum contains “infinite” number of electromagnetic wavelengths from ~390nm to ~730nm.

The power spectrum emitted by light is defined with SPD (in W/m^2/nm) and you can calculate the “HVS neutral” physical light intensity, i.e. Radiant Exitance $M_e$ (in W/m^2) by integrating the spectrum over the visible light range:
$$M_e=\int_{390}^{730} S(\lambda)d\lambda$$
However, RGB color space is defined in photometric units by projecting SPD using HVS weighted color matching functions. This projection is done because storing SPD would consume immense amount of memory for little gain for image visualization purposes. The projection of SPD to RGB is defined with integrals over the visible light range as follows:
$$R=\int_{390}^{730} S(\lambda)\bar{r}(\lambda)d\lambda$$
$$G=\int_{390}^{730} S(\lambda)\bar{g}(\lambda)d\lambda$$
$$B=\int_{390}^{730} S(\lambda)\bar{b}(\lambda)d\lambda$$
CIE 1931 defines standard observer RGB color matching functions as shown below, based on measurement of 10 human observers

As you can see the functions are not discrete wavelengths for RGB, but rather weighted averages of (overlapping) wavelengths.

It’s not possible to unambiguously calculate Radiant Exitance from RGB values because many different SPD's may resulting different Radiant Exitance but project to the same RGB. This is called metamerism.


Artificially increase the region of interest of an image

It looks like your image will always have the same black area due to the mechanism used to take the picture. If that's the case then you don't need to detect the edges. Instead, you can create a static mask ahead of time. The mask can be a single channel image that's white where the eye image is and black elsewhere. You can use that 1 channel mask as the alpha mask for the RGB image you have.

If the image can move around, it looks to me that you could threshold the red channel and say any red value under 0.1, say, is outside of the eye. Another possibility is just let the user select a circular region for the big circle, and then let them select a smaller one for the bump.

To expand the ROI once you've got the mask, you can go pixel by pixel and if the mask is black, follow the vector from the current pixel towards the center of the image until you hit a non-black pixel. When you hit one, just copy that pixel to the one you started with. Do that with each pixel that's not in the eye portion of the image.

EDIT: Given that the mask is static there's an even easier way. In your other question I pointed out that the center of the larger circle was at approximately (279, 283.5) and its radius was approximately 265. So what you could do is simply iterate over all the pixels in the image and if they're farther than 265 pixels away from the center, replace them with the pixel that is 265 pixels away from the center in the same direction. Something like this untested pseudocode:

float centerX = 279;
float centerY = 283.5;
float radius = 265;
for (int row = 0; row < MAX_ROWS; row++)
{
    for (int col = 0; col < MAX_COLS; col++)
    {
        float deltaX = col - centerX;
        float deltaY = row - centerY;
        float dist = sqrt(deltaX * deltaX + deltaY * deltaY);
        if (dist > radius)
        {
            float dirX = deltaX / dist;
            float dirY = delatY / dist;
            float edgeX = centerX + radius * dirX;
            float edgeY = centerY + radius * dirY;
            SetPixel(col, row, GetPixel(edgeX, edgeY));
        }
    }
}

Note that the smaller circle presents another issue. You can test whether a given pixel is in the big circle as above, and if not, then see what the distance to the smaller circle is. If that distance is smaller than the distance to the larger circle, then get the pixel from the smaller circle rather than the larger one.


I'll point out that even if you did implement it correctly, at 1 sample per pixel with low roughness materials you'll still see heavy specular aliasing. It's not uncommon to see the firefly pattern on edges on low roughness materials.
For reference see the Infiltrator demo without TAA

http://advances.realtimerendering.com/s2014/epic/TemporalAA_Compare.mov
http://advances.realtimerendering.com/s2014/index.html#_HIGH-QUALITY_TEMPORAL_SUPERSAMPLING


Reducing artificial rings in mean curvature of mesh

This is just an educated guess, but the artifacts in your visualization of the curvature values reminded me of Moiré patterns. The images in the Wikipedia article don't show circle patterns like the ones you are observing, but I have seen similar patterns before when I tried to visualize highly oscillating functions. (Edit: The function you are visualizing, i.e. the curvature, is likely not oscillating quickly. However, the following example still illustrates that it may not only be the discretization or mesh generation algorithm that is problematic, but also the computation of the curvature.)
For example, if you try to visualize the function $f(x,y) = |\cos((x^2+y^2)^2)|$ for $x$ and $y$ ranging from $-3.3$ to $3.3$ on a grid of $256\times 256$ pixels, what you get is the following image:

The Moiré patterns appear in this image since the function $f$ is only evaluated at a single point (x,y) for every pixel, although each pixel covers not just a single point but an area. A better visualization of the function $f$ would involve integrating over the corresponding area for each pixel, which would result in a uniform gray color near the image boundaries reduces the Moiré patterns.
My guess is that there is something similar happening in your situation. As for solving your problem, this essentially means that the curvature is computed in an erroneous way if the discretization is too coarse. So you could either try to improve the algorithm that is used for the computation of the curvature or simply use a finer discretization. Unless, of course, if the rings really are a feature of your surface, in which case they will not disappear as lightxbulb pointed out.
In case you are interested, I have attached the C++ code that I used to generate the above image. Note that if you increase X and Y while keeping lX and lY constant, the discretization is refined and the Moiré patterns will disappear.
#include <fstream>
#include <vector>
#include <string>
#include <cmath>

using namespace std;

void WriteGrayscalePPM(const std::string& file, const std::vector<unsigned char>& values, const unsigned int X) {
  const unsigned int Y = values.size ( ) / X;

  std::ofstream image(file.c_str(), ios::out | ios::binary);
  image << "P6\n" << X << ' ' << Y << "\n255\n";
  for (unsigned int i=0; i<X*Y; i++) {
    unsigned char color[3] = {values[i], values[i], values[i]};
    image.write((const char*)color, 3*sizeof(char));
  }
}

int main(int argc, char **argv) {
  const int X = 256;
  const int Y = 256;
  const double lX = 3.3;
  const double lY = 3.3;

  std::vector<unsigned char> values(X*Y, 0);

  for (int y=0; y<Y; y++) for (int x=0; x<X; x++) {
    double xd = lX / (X/2) * (x - X/2);
    double yd = lY / (Y/2) * (y - Y/2);
    double d = sqrt(xd*xd + yd*yd);

    values[x + y*X] = 255*abs(cos(d*d*d*d));
  }

  WriteGrayscalePPM("moire.ppm", values, X);

  return 0;
}


Is it possible to do color conversion on decoded video without getting it from GPUmemory to CPU memory?

So it sounds like the main issue you're having is how to render something when all resources are already on the GPU. I would do it like this:

Create the destination RGB texture that's the proper width and height
Create an FBO
Set the texture created in step 1 as the output (write) texture of the FBO
Bind the NV12 texture to the texture unit you'll use in your shader
Draw a textured quad that covers the entire output
Apply a shader that samples the NV12 texture to generate the RGB value at each fragment

For step 1 you use glGenTextures() and glTexImage2D().

For steps 2 and 3 you use glGenFramebuffers() and glBindFramebuffer() passing glBindFramebuffer() the texture created in step 1 to attach it to GL_COLOR_ATTACHMENT0. (See here for more details.)

For step 4 you use glBindTexture().

For step 5 you can simply draw a quad that goes from (-1, -1) to (1, 1). You don't need any model view matrix or anything.

For step 6 you'll need to calculate where the red, green, and blue samples that correspond to the current output pixel are in the input texture and then sample them using the texture() function. You'll need to do 3 different look-ups for each output pixel. This link has C code for figuring out where each sample is from.

Once you're done you can delete the frame buffer and use the texture created in step 1 in your next step (display it, process it, save it to disk, or whatever).


Calculate BRDF and PDF when doing direct light sampling

1) When we have multiple BRDFs, adding thier components together can break energy conservation, as I think you suspect. However most renderers will handle this problem when constructing the layered BRDFs. For example you would might weight each layer or use a fresnel term to decide the weight for each layer.

Here is the spec for arnolds standard shader:

https://autodesk.github.io/standard-surface/

Each layer is multiplied by 1 - previous layer weight, which the artist is setting. This is done inside the fr function, which means that energy conservation is solved here.

2) The pdf is an average, I think, if each bxdf has an equal chance of being sampled. You therefore average the pdf even though each layer may contribute different amounts.

Note: Becareful which value you use for p(wr), this will be the pdf you used to sample your direction, so either the bxdf pdf or the light pdf. (You still need to calculate both pdfs at some point for MIS though.)


Seamlessly transitioning between nearby environment maps

It looks to me like they have a coarse polygon model of the room, and texture the model by projecting the cubemaps onto it. The model seems to include the rough shapes of the walls and furniture, but not fine details such as table legs, door handles or items on shelves. When the camera moves, the geometry gives you more-or-less-correct parallax, and the crossfade between cubemaps updates the textures.

You can also see the model clearly when the walkthrough first loads. Note that the camera starts outside of the house, letting you see the whole thing (much as you'd see a game level if you noclip the camera outside it), then it moves the camera into the living room. You can also get back to this view by selecting "Dollhouse" in their toolbar.

Their model may have been constructed by an artist, but in your case if you have depth information in the cubemaps, it's probably possible to programmatically extract some geometry from them and stitch the cubemaps together to form a coherent model. I don't know much about that subject, though.


Model Separation - Several models reside in a single .stl file

Software recommendation are not on topic. Instead I will explain how you separate the shapes. Each object is a separate volume so you can just extract all the continuous shells. You can do this simply by picking a vertex marking it as visited and then picking all connected vertices and marking them visited. You continue this visiting to new un-visited vertices until you no longer can find a connected vertex.

This is a shell, in most cases a shell is a separate object. Unless there is a empty non connected cavity inside the object. This is rare but possible in 3d printing though not most other manufacturing methods. In this case you need to check that the shells do not intersect (they shouldn't or it means your model is broken anyway, nothing to fix) and if a shell lies inside another. You can do this by picking a point on the suspected interior shell and shooting a ray in a arbitrary direction. The shells that you hit a odd number of times are surrounding your main shell.


Why do Nvidia and AMD have to update their drivers for game releases?

Games, Triple A games in particular, tend to push graphics cards to their limits, computation capabilities, bandwidth, and drivers all get stressed heavily. This tends to cause even the smallest bug, or inefficiency in the driver to become a glaring problem resulting in "glitches", slow frame rates, game crashes and rendering quality issues.
These "bugs" and inefficiencies can be very specific and often only occur when certain sequences of operations happen, which are often specific to a particular game. The range of issues that they run into tend to run the gamut from simple brain dead bugs, to show stopping monsters that everyone spends weeks agonizing over, to minor tweaks that improve visuals.
During game development vendors will provide driver updates that address these issues directly to game developers, or put the updates in a "beta" driver and release it publicly so anyone, including the developers, can install it. This allows games to be tested, developed and updated before being released.
How closely a vendor works with a game developer is going to depend heavily on the size of the project and the issues they are encountering. Sometimes this will mean going so far as having engineers from the GPU vendor actually join the game development team, and spend time on site working through the various problems that come up. Other times it can be just an updated driver dropped on the public beta website.
When the game is nearing release game developers and vendors will work together to release the updated driver with the game, this sometimes even includes shipping the updated driver with the actual game. For smaller projects vendors might no be as accommodating. It is in the best interest of both game developers and GPU vendors to work together, especially on large projects.
It would be naïve to assume that the two don't come to some sort of monetary agreement when developing a game, especially when a game gets advertised with statements like "Made for XYZ gpu vendor."


You might want to try the VK_LAYER_LUNARG_monitor layer from the LunarG Vulkan SDK.

Download the SDK from the LunarXchange site.

After SDK installation, you can activate the layer by setting this environment variable:

VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_monitor

The monitor layer displays the FPS value in the application window's title bar.


Using independent settings for each colour channel is like using settings dependent on wavelength when doing spectral rendering. So the question could be re-formulated as:

  Is a material which changes its roughness with wavelengths physically plausible?

With some kind of nano-fabrication process you could build a material surface using some microfacets reflecting certain parts of spectrum and distributing each type of microfacets in a different way. So not only it is physically plausible, but it is also physically realisable. On the other hand, you normally don't encounter such behaviour in "common" materials.


One possibility would be to create a bit array with 1 bit per half-edge. When you start iterating, initialize them all to 1, then clear the bits of each half-edge and its partner as you iterate.
The iteration can be done using __builtin_clz (GCC, clang)  or _BitScanReverse (MSVC)  [edit: or std::countl_zero in C++20!] to efficiently extract the next 1-bit without branching on every bit. Although you do then need a nested pair of loops, where you loop over the fields in your bit array, and then loop extracting bits until the current field is zero.


Difference between relativeOffset and offset in VAO with Direct Access Ext

The offset in glVertexArrayVertexBuffer is the common offset for all attributes bound to that buffer. It's where the vbo data starts.

The offset in glVertexArrayAttribFormat is added to that common offset for that attribute.

This allows you to interleave attributes using a single vbo binding point. and change the vbo binding for those attributes in a single call.

To make an example:

struct Vertex {
    vec3 pos;
    vec3 normal;
}

glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));
glVertexAttribBinding(posAttrLoc, vertexBindingPoint);
glEnableVertexAttribArray(posAttrLoc);

glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));
glVertexAttribBinding(normalAttrLoc, vertexBindingPoint);
glEnableVertexAttribArray(normalAttrLoc);

then to bind the buffer you pass the offset to where you put in where the data was uploaded to, this is 0 in the basic case.

glBindVertexBuffer(vertexBindingPoint, mesh.vbo, mesh.vboOffset, sizeof(Vertex));


One red flag is the use of new several times within the loop. Memory allocation doesn't belong in a rasterizer! :) Certainly you should not need to allocate a Point object (which is used once and then immediately discarded) and do a method call on it, just in order to fill a single pixel! The pixels are hopefully stored as a flat array of bytes, so just write directly to the appropriate address in it. Similarly, don't allocate a Vector2D every time through, just create one (ideally on the stack, if the language you're using allows for it), and re-use it.

Secondly, the algorithm you're using doesn't seem to be a true scanline rasterizer. It iterates over the pixels in each line from left to right, performing edge tests on every single pixel to determine whether it's inside or outside, and recording when that state changes in the start and end variables.

The way a scanline rasterizer is supposed to work (which is much faster) is to calculate the intersection points of each edge with the scanline (using good old school algebra line-line intersection math). Ideally you would have already categorized and sorted the three edges as left, right, or horizontal and therefore once you have the intersection points, it's easy to figure out the interval that the triangle covers on the scanline. Then you can iterate over that and shade or fill each pixel.

Finally, I'm not sure if this is a real issue or not, but there are a lot of method calls for relatively trivial things like checking whether vectors are equal, or doing an edge-vs-point test. Hopefully the compiler is inlining all those, but you might want to check the generated code to see. If it's not, you could see a fair speedup by manually inlining that stuff, and possibly manually "destructuring" the vectors (i.e. replace a Vector2D variable by two explicit x and y variables).


Texture glitch when using simple pixel shader

So I followed Alan Wolfe suggestion (in comment to my question) And turned out he was right. I was using SamplerState.LinearWrap and that was the issue. When I changed this to AnisotropicWrap it looked much better. Below are some examples of different sampling types and how they affect texture:

graphicsDevice.SamplerStates[0] = SamplerState.PointWrap;

graphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;

graphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap;


It's saying that if you're using a single GPU, the multiple processes attempting to use the GPU will be queued up and run one at a time rather than some or all being run in parallel. If you have multiple GPUs some of the processes can be run at the same time.


Z-buffering implementation with small triangles

Assuming the small triangles form continuous surfaces, although many of the small triangles "fall through the gaps" (so to speak), some should still cover the samples. If on the other hand, they are separate/independent triangles then it will alias very badly.

One possible alternative to just doing higher resolutions would be to simulate an Accumulation Buffer. In essence, do N XxY pixel renders, but for every render, offset the X&Y screen coordinates by a sub-pixel amounts.

You can then combine the N images, (perhaps initially with a simple box filter, but a Gaussian would be better) to produce your final XxY image.

  Can you explain what does "offset the X&Y screen coordinates by a sub-pixel amounts." mean ?

Perhaps it'd be a good idea to read  Haeberli and Akeley's original paper but I'll try to put in a bit of an explanation on how I would try to do the XY shifts. (I apologise in advance if I've made some fundamental flaw in the following logic...)

Let's assume we want to shift the image by $(x_{offset}, y_{offset})$ in pixels where, probably, $|x_{offset}| < 0.5$ and $|y_{offset}|<0.5$.

We want to add this offset to each vertex after it's been projected into screen coordinates. Now since we don't have much control of the pipeline post clipping and projection, we'll need to do that by adjusting the projection matrix. If we assume our default projection matrix, P, does something of the following:
$$(X_{world}, Y_{world}, Z_{world}, 1).P=(X_{clip},Y_{clip},Z_{clip}, W_{clip})$$
i.e. maps from world space to clip space, then to shift the points in image space we'll need an additional "matrix" adjustment which, off the top of my head, will be something like...
$$Adjust= \begin{bmatrix}
    1 & 0 & 0 & 0 \\
    0 & 1 & 0& 0 \\
    0 & 0 &1& 0 \\
    scaledX_{offset} & scaledY_{offset} &0& 1 \\
    \end{bmatrix}
$$
The "scaling" should take into account the resolution of the target image.

Create a new, per offset, projection matrix from $P.Adjust$ for each "offset" image you want to accumulate.


Can I get numeric data from a color map?

I don't know of any software that could do this for you. However, it should be possible to reverse engineer the colour map to create a kind of look-up table structure.

First, take a one pixel wide column (or row) of the colour map and store this as an array of colour values. Then, create a secondary array, for the data/altitude values, of the same length. Try to mark to the best of you ability the marked values of the colour map on this second array. A simple solution would be to also take a pixel wide column (or row) featuring the markings of the colour map to get the exact one-to-one pixel correspondence. Now you have a secondary array containing the marked off values and the rest of the values can be filled in by figuring out the step size of the colour map. The step size would be the difference in absolute value between subsequent markings divided by the number of pixels between these same markings.

Now when you read a colour from the mapped figure you can look up the colour in the colour array and use the index of this value to look up the altitude in the secondary array.


Quick 2-color quantization for small images

The approach I would use, and indeed have used, would be to

run principal component analysis on your image data to generate "the" main axis
Project your pixels onto that axis (i.e. compute the dot product of each colour value against the axis)
Using the dot prods, sort the the colour values from smallest to largest and
Find the "partitioning" point, i.e. that splits smaller values in one set, larger in the other, that minimises, say, the mean squared error. i.e. each partition is represented by the average of its members and you compute the total error.

This last step, i.e. finding the best partition, can be done in linear time by starting with the "least" item in partition "A", all the rest in partition "B", and progressively shifting the next smaller over from "B" to "A, one at a time. You just need to keep separate sums of the values and sums of squares of the values for each partition and then you can compute the total MSE relatively cheaply.

Note that the function should follow a quadratic curve so it (should) begin decreasing until it reaches the minimum. Once it starts increasing again you can stop the search.

A cheap way to find the principal axis is to first generate the 3x3 covariance matrix and then use the "repeated matrix vector multiplication" trick to find the principal eigenvector (i.e. the principal axis)


What's more optimal - sampling one channel at a time or all channels at once?

It should be significantly faster to sample one RGBA value from one location in a texture than four R values from different locations in the texture.


Why are these 2 buffers joint while extracting glTF information?

The accessor (model.accessors[accessor_index]) has its own byteOffset and count values that you need to account for here.
The input and output accessors are allowed to share a bufferView, and your output is showing a dump of the same entire bufferView twice.  The first five values in that dump are the input accessor with the times (in seconds, since the start of the animation) and the remainder of the bufferView is pointed at by the output accessor.  If you account for the additional settings on the accessor itself, it should allow you to pick apart this bufferView correctly.


When is it better to upload partial model matrices to the vertex shader?

Doing math with uniforms is a shader won't usually get you any performance over doing it on the CPU. A CPU isn't slower than a GPU at doing matrix math, it just isn't structured so as to do large amounts of math in parallel. But you have to actually do that large amount of math to get a win. Sending extra data to the GPU just to have the GPU multiply two matrices together will rarely net you anything.

Now, say you have a buffer of skinning matrices. It might start to matter whether you transform them all into world space on the CPU or just pass an extra model-to-world-space matrix to the GPU. But even then it depends on your ratio of vertices to bones.


What's the simplest, open, animation format?

For what it's worth, the glTF Tutorials contain a section on Skinning that shows how the raw vertex and joint weight data feed into a vertex shader to distort the mesh.
If you do design your own format to hold this, you'll need tooling to export it from 3D content creation software, as well as software to read the new format into your application.  Using an open format like glTF can grant access to existing tools, such as the Blender glTF exporter, that can write all this data into the file, in a form that's ready to load into vertex attributes and shaders.


According to the Star Swarm developers this helps them with LOD and enables greater shading scaling. Based on this I guess its simply texture space lighting.

  Because we do what we’re calling object space lighting, we calculate the projected size of each of those objects on screen, and based on that we shade it in a priority manner based on how large they are. We can scale the shading quality at a different frequency than we scale the geometry level or something else.

 A deep dive into the making of the eye-popping Star Swarm demo (interview)


GBuffer: Framebuffer with different texture format types?

You have a bit of a misunderstanding there. The paragraph you quoted doesn't actually say anything about framebuffer objects yet. It just talks about a single texture. While we usually understand a texture as a single image, it is (or can be) actually comprised of a set of images. This might be because it is an Array Texture or, even more common, it just has a set of Mip Map Levels (basically increasingly smaller filtered versions of the base image, used for advanced texture filtering). And yes, within a single texture, all those images have the same format. However one such texture usually makes for one render target.

All this has nothing to do with multiple render targets yet. And you will notice that the later parts of that article that speak about the actual framebuffer attachments, specifically the part about Framebuffer Completeness don't say anything of the sort of all attachments needing to have the same format, because there is no such restriction. They don't even need to have the same dimensions. The only thing that is required is that they all have the same number of samples (if they're multisampled at all).

It is possible that an implementation still doesn't support all kinds of image formats and combinations, but there are some that are required and a "reasonable" implementation will support a wide variety of format combinations, including ones with mixed pixel bit-depths.

There was a stricter limitation on the images in the original GL_EXT_framebuffer_object extension, namely that all attachments have the same size and internal format. However, since it has found its way into OpenGL 3.0+ core (and was from there exported back as the more advanced GL_ARB_framebuffer_object extension) they loosened these restrictions.


How to never draw "Jaggies" in the first place considering resolution and scale

Well you can render at higher resolution and sample down thhis is called FSAA and should just work without much change to render code. FSAA has the benefit of not having a conflation problem whereas smoothing does.

No, something has to emit this info.
You take the derivate (the gfx card does this for you) of the surface varying to determine how far the step would take you in your pixel. if its over the edge then you antialias.


Link between blue noise sampling and blue noise textures?

The missing link between sample locations and the greyscale noise texture is "ordered dithering".

Ordered dithering is a list of pixel locations with a "rank" (order) for each pixel. If you have a white background and want to add two black dots, you add them at the locations for the two pixels rank 0 and rank 1.

Choosing how to rank the order of the pixels to turn on can vary dramatically with different results though. For instance, a bayer matrix is a specific ordering of the points, and blue noise sample points are as well. White noise is just shuffling the points so that they have a random ordering.

How we get from this "ordered dithering" (stippling) to the greyscale color noise images is that we divide each point's rank by the number of points to get a value from 0 to 1, and use that as the points greyscale color.

That gives you the greyscale noise textures.

The greyscale blue noise texture was created with the "void and cluster" algorithm which makes it so that each new dot placed goes in the middle of the largest void.  This has the nice property that you can threshold the blue noise texture at any value, and the result will be blue noise samples of the desired density.

This paper is a great read that talks about these things more deeply:
http://cv.ulichney.com/papers/1993-void-cluster.pdf


What are the i,j,k components of a 3d mesh on plot.ly (online)?

Most mesh drawing tools use triangles to draw meshes, for technical reasons.

You could simply specify the coordinates of the three vertices of each triangle, but that is a bit wasteful in terms of memory.

What is done in many places is to specify a list of points in space, with their coordinates, and then specify a list of triangles, using indices of the points in the first list.

The exact same thing happens here. The x,y,z parameters form a list of points. The I,j,k parameters indicate triangles, using IDs in the list of points.

Have a look at the function documentation for more details:
https://plot.ly/python/reference/#mesh3d


Derivation of Wikipedia's path tracing diffuse BRDF

When you perform regular Monte Carlo integration over a hemisphere using $N$ samples, each sample represents $\frac{2\pi}{N}$ steradians. So the Monte Carlo integration for Lambertian BRDF is:

$$\frac{2\pi}{N}\sum_{i=1}^N\frac{\rho}{\pi}L_i*Cos\theta_i$$

For path tracing, you only take one sample per path segment, so because $N$=1, the above sum becomes:

$$2\pi\frac{\rho}{\pi}L*Cos\theta = 2\rho L*Cos\theta$$


How to build a 3d model from 2d pictures

This is a bit different from a conventional photogrammetry problem. You're not trying to estimate a 3D world from 2D projections. You have actual 3D information - you have the imaging slices - and you want to assemble them into a 3D model. That's a much easier problem, the kind you can solve from the comfort of your couch.

Do know the cutting planes that each image belongs to? If so, you can easily assemble them. Just plop down the images at each plane. If not, it will be hard to determine how the images stack. (Is image N on top of or below image K?)

If the images are not all taken from parallel cutting planes, then your problem is a bit easier. You can compute point correspondences between the slices and solve the alignment as an iterative registration problem. (i.e. every point in every image that "corresponds" should be at the same point in 3D space)

Now, making this into a 3D point cloud is easy - I would drop points based on the density at each point in each image, so that empty spaces are empty and dense objects have many points.

Building a mesh is way more difficult. If that's what you intend to do, and you're okay with hokey results, you might consider a triangulation approach to mesh building.

If you want good results, I would forego trying to fit a mesh to the cloud, and instead try to find density level sets in each 2D image, and see if you can build volumetric objects by following those level sets as isosurfaces in the 3D assembled scan.


Turns out I needed to be looking at the former normal as a unit vector $(\hat{r}, \hat{\theta},\hat{\varphi})$, and then use a rotation matrix as outlined here to find $(\hat{x},\hat{y},\hat{z})$.


What does "st" mean in the context of OpenGL?

The common names for the components of texture coordinates are U and V. However, because the next letter used (for 3D textures) is W, that causes a conflict with the names for the components of a position: X, Y, Z, and W.

To avoid such conflicts, OpenGL's convention is that the components of texture coordinates are named S, T, and R. Thus, you have function calls like this:

glTexParameter(..., GL_TEXTURE_WRAP_S, GL_REPEAT);

Where GL_TEXTURE_WRAP_S refers to wrapping in the S component of the texture coordinate.

Unfortunately, OpenGL picked S, T, and R long before GLSL and swizzle masks came around. R, of course, conflicts with R, G, B, and A. To avoid such conflicts, in GLSL, the texture coordinate swizzle mask uses S, T, P, and Q.

In GLSL, you can swizzle with XYZW, STPQ, or RGBA. They all mean exactly the same thing. So position.st is exactly the same as position.xy. However, you're not allowed to combine swizzle masks from different sets. So position.xt is not allowed.


GLSL does not support C++ style namespaces. You might want to do some regex magic before parsing the shader, replacing '::' with '_' or something. You might want to have a preprocessor of sorts - or just forget about it entirely.


Value range of normal distribution function

The term D is a probability density function (PDF) of microfacets' directions. Vaguely speaking, it says what "portion" of all microfacets points in the given direction.

Since it is a PDF, it doesn't have to be less or equal to 1. It can, and often is, higher than 1 for some directions.


Inverse Kinematics with more than 2 segments

What you have here is an underconstrained problem*. To solve this problem you do what you do to any other underconstrained system. This is also why you mostly only see the 2 joint version as it is not underconstrained in the planar solution, and in any case the preregistration is trivial.

Basically you have 2 options:

Add more constraints
Deal with the freedom

Adding more constraints to the system reduces the degrees of freedom. For example if you only permit one of the joints to rotate about its z axis and the another around its x axis then y then you have reduced the problem to the same 2 member problem. Another way to constrain it is to force the orientation of the last link. This also reduces it to the same case as 2 links. But there are other meaningful ways to reduce complexity that depend on your application.

Image 1: Constraining one member reduces the problem to a 2 member problem. In the planar case that means 2 solutions (other in blue).

Dealing with the freedom just means that your answer is going to be a family of answers. Then you develop a way to choose the solution from that family. Letting the user adjust the parameter is equivalent to adding one more constraint. But there are other methods such as least squares, or energy methods that yield different results. Sky is the limit here. For example I have worked with robot controllers that decided the parameter based on what was the least amount of rotation on joints. The problem was that this wasn't entirely deterministic so over time the robot ended up doing things differently...

* This is more suited to Engineering.SE but since IK is a common graphics problem lets deal with it here.


What kind of technology would be involved in the rendering of human nails?

I'm not aware of any rendering technology designed specially for fingernails. Just eyeballing it, I would suggest that a combination of subsurface scattering with a relatively smooth glossy specular surface would get you most of the way there. In other words, you could use the same shader as you do for skin, but with different textures and different specular parameters.

I wouldn't guess that a hair shader would be too useful. Nails are not in the shape of fibers, nor do they have the kind of complex occlusion and shadowing that hair does.

That being said, if the scattering properties of the nails are different enough from that of skin, it might make sense to use a different shader (for instance, doing some sort of volumetric scattering instead of a dipole approximation). I don't know of any references on skin scattering that have investigated nails specifically, though.


Program to make "Pieslice" without using library function?

You can use the sine and cosine functions to do this. Normally they start on the x axis and rotate counter-clockwise. The start point can be found by calculating:

startX = x + cos(startRadians) * radius;
startY = y + sin(startRadians) * radius;

Likewise the ending coordinates are:

endX = x + cos(endRadians) * radius;
endY = y + sin(endRadians) * radius;

Note that sin() and cos() take their parameters in radians. Given that stangle and endangle are integers, I'm guessing they're probably in degrees so you'll need to convert them by doing something like:

double startRadians = (double)stangle * M_PI / 180.0;

etc.

If you want to draw the entire pie wedge, you'll need to iterate from the start angle to the end angle and calculate every n degrees along the curve.


Different result with DSA (vertexArrayVertexBuffer, vertexArrayAttribBinding) than with glBufferData

You forgot to call glVertexArrayAttribFormat:

glCreateBuffers(1, &buffer);
glNamedBufferStorage(buffer, sizeof(vertices), vertices, 0);

glCreateVertexArrays(1, &vao);
glEnableVertexArrayAttrib(vao, 0);
glVertexArrayAttribFormat(vao, 0, 3, GL_FLOAT, GL_FALSE, 0);

glVertexArrayVertexBuffer(vao, 0, buffer, 0, sizeof(GLfloat) * 3);
glVertexArrayAttribBinding(vao, 0, 0);


Look good to me.

And yes you can use different datatypes for different attributes in a vao, that's the entire point of having the type parameter there in the first place.


Do I need a normal matrix if I calculate lighting in an objects space?

By lighting in object space, sure, you could avoid transforming the normals into world space. However, you'd have to transform the light positions/vectors into the object's space. Also, if you want any view-dependent shading such as specular, you would have to transform the camera position into object space as well, to calculate view vectors.

Now, all of this can be done straightforwardly using the inverse of the object's world matrix. The inverse world matrix will include the inverse of the object's scale (as well as correctly accounting for the inverse of its rotation and translation), so it will transform the light & camera positions to the appropriate points in the scaled coordinate system. Directional lights don't have a position, but you can transform their direction vector by the inverse world matrix to account for rotation and scale. All of this is fine so far.

However, you will then run into trouble when doing lighting calculations like N·L or N·V. For exactly the same reason that normals don't transform correctly under non-uniform scaling without using a special normal matrix, these dot products will not come out with the same result when done in a non-uniformly scaled object space as compared to world space. Namely, non-uniform scaling distorts angles. So, all your lighting calculations and BRDFs that depend on angles are going to be messed up.

While there are ways one could correct this problem by using additional matrices when calculating dot products... it's generally easier and faster to do lighting in world space (or view space). In any case, transforming the normals to world space is a pretty trivial amount of math by modern GPU standards, especially as it only needs to be done per vertex.


Deriving radiance from irradiance and intensity

Your definition for radiant intensity is wrong: it should be just $\Phi / 4\pi$. There are only $4\pi$ steradians in a sphere no matter how big it is, so $r$ doesn't come into it.
Also note that you can't calculate radiance for a point source—it would be infinite, due to the fact the point source emits a finite amount of flux compressed into zero size. It subtends zero solid angle, from the receiver's point of view, so the $d\omega$ factor in the denominator of radiance would be zero. The usable quantities are radiant intensity in a certain direction from the point source (which could vary with direction, for a non-omnidirectional light), and irradiance in a certain direction and distance. As you've seen, irradiance is obtained from radiant intensity by dividing by $r^2$—you could think of this as "area per steradian", as it's the conversion factor from $4\pi$ steradians to $4\pi r^2$ area of a sphere; then the units work out.
Where radiance would actually show up is when dealing with an area light rather than a point light. Then you would have the flux being distributed over a finite solid angle from the receiver's point of view, and you'd get the incident irradiance by integrating the light's radiance over that solid angle. The emitted radiance would be $\Phi/(2\pi A_\text{light})$, assuming it's emitted uniformly over the surface of the light and into all directions from each point. This is only $2\pi$ since it's only emitting into the outward-facing hemisphere. Also note that you don't do any division by $r^2$ for radiance—with area lights, the distance attenuation comes naturally as a result of the light subtending less solid angle from the receiver's point of view, when the receiver is farther away.


Where do computer graphic engineers look for job ads?

There are several major Computer Graphics publications that have a jobs section. Try Siggraph for example. I'm pretty sure I saw a similar thing for Eurographics, but I can't find it right now.
Furthermore, you can look for applicants at the conferences themselves, if you have the resources to do so.

If you accept students that just finish university, you should put up an ad there (or tell the computer graphics professor to spread the word - my professor was kind enough to distribute offers to us every now and then).
Apart from that, you'll probably find most graphics programmers in computer games related fields. Gamasutra has a jobs section, although I'm not sure they let non-games related companies advertise there.

Moreover, Stackoverflow has a job offers section. I never really used it myself, but it's probably worth looking into. I got quite a few computer graphics related offers, so my guess is that you can advertise specifically to people with tags like OpenGL and Rendering as their favourite tags.


Ray tracing where illumination itself affects the geometry

You might look into Mitsuba, which is a physically based path tracing renderer that's designed to be easy to extend with plugins. It might be useful as a base for you to build on, implementing your own algorithms as plugins or by modifying its code.
It already contains facilities for measuring the amount of light falling on some geometry, in the form of the "irradiance meter" object. I'm not sure how much it can help you with geometry modification as it's not really designed for that (it just imports geometry from a file and renders it), but maybe you can find some other libraries to help with that part, depending on what kind of geometry operations you need to do.


How does Smith multiple scattering interact with diffuse subsurface scattering?

The goal of Heitz et al.'s model is pretty much the opposite of subsurface scattering: They only consider surface scattering, i.e. the ray can never enter the material.

Because microfacets are statistical in nature, they can recast their problem in such a way that it can be solved by microflakes, which allows them to compute properties such as the mean free path to derive a heightfield sampling procedure. However, even though they use microflake theory, they still solve the same problem of multiple scattering on microfacets, and their result is still a BSDF, not a subsurface scattering model.

Because it is a BSDF, the path exits at the same location as it hit the surface. This is also mentioned in the introduction:

  Note that our volume-scattering process models the interaction with a surface, but its application in rendering is virtual in that no displacements occur, i.e. the incident and exitant location are the same and the resulting plane-parallel radiometry produces a BSDF.


There is no such function. Given the context of the text, it is almost certainly referring to glTextureSubImage*.


How to generate the stereographic projection of a 3D model

If instead of stereographic projection you can use other conformal projection. I would recommend you the "Least Squares Conformal Maps" algorithm. There are several implementations out there, including the prominent CGAL (https://doc.cgal.org/latest/Surface_mesh_parameterization/index.html).


exact down sampling and re-triangulation of mesh data(non-convex)

1. Method: Vertex Clustering

This is more or less a low-quality method, but depending on your mesh it could work well.
The basic idea is to partition the space into a regular grid, and then choose one representative for each cell that holds at least one vertex.
Then calculate the connectivity based on the connectivity of the original vertices.

In the image you see a basic 2D clustering. The unreduced mesh on the left, and the reduced on the right with the chosen representatives.
As you can see, just choosing an existing vertex as representative (by closest to mean, or closest to center, or any other idea you can think of) you get a subset of vertices.

But you also see the problem, thin parts will degenerate and parts that are close to forming a loop will probably get connected. But as already said, it depends on your mesh if this works.

2. Method: Incremental Mesh Decimation with with Half-edge Collapse

One vertex gets collapsed into its neighbour. Thereby you get again a subsampling.
This is a progressive method. You evaluate which collapse will decrease the quality (for example total distance to the original surface, but many more possible) and collapse it. Then you check if your quality has dropped too much for another collapse, and if so you stop. Otherwise you do it again. Until either the quality drops too much or the target size is reached.

Method 3: Progressive Mesh Decimation with Vertex Decimation.

The same progressive idea as in method 2, but this time instead of a collapse you just delete a vertex and calculate a new triangulation for the hole that this created.


How to use shadow mapping and deferred rendering to create a large amount of lights?

Deferred rendering does not have an asymptic complexity of O(lights+fragments). It has a complexity of O(fragments+visibleFragments*lights).

What you are doing in deferred rendering is preventing having to calculate lighting for many fragments that cover the same screen pixel. Once you have found which ones are visible, all of those still have to calculate lighting from every light source.

This is faster than forward rendering on the premise that lighting calculations are heavier than geometry calculations and that most fragments are ocluded by other fragments.


What if the camera rotate around its gaze direction? The v rotates while the t stays the same.

The camera's orientation is defined by two directions: g and t. If the camera "rotates around its gaze direction", g will not be changing; that is what it means to "rotate around its gaze direction". If g isn't changing, and the camera's orientation is defined by two directions, then you can only get a different orientation if t is changing.

Therefore, your second statement is a contradiction of the first. Changing t is precisely how you cause the camera to "rotate around its gaze direction".

To put it a different way, there are changes to t which will not affect the values of u, v, or w. However, none of those changes will cause the camera to "rotate around its gaze direction".


Polygon offsetting is certainly possible to do yourself. It is not nearly as involved as Bezier or B-spline offsetting is. First you want to decide how to deal with:

Areas with no info, in essence how to deal with the joins. Do you just extend the line to the common intersection (miter join) or do you just connect the endpoints (bevel). You could also use round, parabolic or other join styles if you wish. Options here are unlimited.

For the purposes of this discussion I will assume you will want a miter or bevel join.
How do you want to deal with sidedness. Is an open curve's offset closed or just on the other side. Other than that the convention is usually in 2D that outside is on the clockwise side of the path

So lets look at what happens when 2 straight lines join and they are offset.

Image 1: Situation in 2D.

For a beveled corner join vector, from any point to its offset is magnitude of $a$. Take the direction of the segment rotated counterclockwise 90 degrees then multiply that with the length of offset. Or in the case of the picture in mathematical notation

$$
 A' = A + a\bigg(\big|B-A\big|   \begin{bmatrix}
    0 & 1\\
    -1 & 0
  \end{bmatrix}\bigg)
$$

Where $a$ is the amount of offset. This assumes lines go from $A$ to $B$ to $C$. Connecting segments must be processed on both sides separately. The same formula can be used for all the points. Then just connect $B'^1$ to $B'^2$ with a line. In case you are matrix illiterate, the matrix says swap x and y coordinate and invert the x value.

For a miter join the following applies:

Image 2: Situation of miter.

$$
 B^{B-B'^{1}} = a\bigg(\big|B-A\big| \begin{bmatrix}
    0 & 1\\
    -1 & 0
  \end{bmatrix}\bigg)
$$
$$
B' = B+\dfrac{ B^{B-B'^{1}}}{B^{B-B'^{1}}  \cdot (|B-A|-|C-B|)}
$$

The above can be heavily simplified but I'll leave that to the reader.

Now the reason to use a library is that when the curves start to self intersect it gets a bit tedious to manage this. So just find a library that does this for you and you'll save a lot of time.


Changing the projection reference point in Open GL

Eye position, projection reference point PRP, camera center, or projection center are all just different words for the same thing.

gluLookAt() applied to the GL_MODELVIEW matrix works for both, parallel and perspective projection.

You can choose between parallel and perspective projection by setting up the GL_PROJECTION matrix. For perspective projection this can be done using the gluPerspective() function.

Creating a perspective projection matrix in OpenGL

Edit: (after revised question)

If the PRP is not at the eye position, you can not use gluPerspective(). Instead you have to create your own GL_PROJECTION matrix. Following the formula that you have now provided, this results in the 4 x 4 matrix:

$$\mathtt{A} =\begin{bmatrix} z_c-z_{pp} & 0 & -x_c &  x_c \cdot z_{pp}\\ 0  & z_c-z_{pp}  & -y_c & y_c \cdot z_{pp} \\ 0 & 0 & \frac{\mathrm{far}+\mathrm{near}}{\mathrm{near}-\mathrm{far}} & \frac{2 \cdot \mathrm{far} \cdot \mathrm{near}}{\mathrm{near}-\mathrm{far}} \\ 0 & 0 & -1 & z_c \end{bmatrix}
$$

I have done a quick OpenGL/WebGL rendering test with the GSN Composer. Follow the link and move the mouse over the render output to change $x_c$ and $y_c$ of the projection reference point $(x_c, y_c, z_c)$:

Example: ProjectionReferencePoint | GSN Composer


Understanding camera() settings in Processing

As the documentation describes it, it looks like each group of three parameters is a vector in 3D space. The first three are the position of the “eye”, the next three are the position it’s looking at, and the last three are the “up vector”, i.e. the direction of an arrow pointing out of the top (…sort of—more detail below) of the eye. The positions aren’t related to the size of your display window—the view of your 3D geometry from the camera at that point will fill the display.

In other words, if you have a box centered at (0, 0, 0) that’s 1×1×1 units in size, then your camera should be positioned a few units away—say (2, 3, 4)—and looking roughly at the center of the box, i.e. (0, 0, 0). If the box is 100×100×100 instead, then the eye position should be on the same order of magnitude in distance, e.g. (200, 300, 400). The behavior of the up vector is a little more complicated to explain, but leaving it at (0,1,0) is fine for most purposes—it’s mostly there to help you avoid gimbal lock.


Have you considered using SDL 2?
My use-case is basically identical to yours, and I've found this approach to work really well. They have a really nice C (and C++) API for drawing framebuffers to a window. It's also platform-agnostic, so you can share your implementation fairly easily between macOS, Linux and Windows.
If you want to see an example, you can go check out this module here on GitHub. I do warn you though, while this implementation works, and I can easily run it at 60-120FPS, it likely does use more CPU than a fully optimised implementation.
Specifically observe the initDisplay() and drawWindow() functions.


Estimating the area of a triangle-circle intersection

Working Towards an Exact solution

Just some quick thought before I must run!

Ok, let us turn the problem on its head. What if one does not calculate the area of the triangle cut by the circle. Instead let's calculate the inverse of this. The area of three segments cut out of the circle. The beauty of this approach is that we can make a single piece of code that we can repeat three times. Of course some of the time the answer will be 0 but that is OK.

Image 1: Let's calculate this problem instead.

Now it turns out we know how to calculate the inverse, it is the segment of a circle.  So we can just say that $A_{int}=A_{circle}-A_1-A_2-A_3$.

Image 2: We know this solution.

The formula for the area of a segment is simply $A_{sector}-A_{triangle}$ and that has a well known solution in literature.

So now all you need to do is find the intersections between the edges and the circle in a space centered on the circle, calculate the angle between those and then calculate each segment. And the only special case is if no intersection exists. I dont know if this is fast but at least code should be somewhat easy to implement.


I think it would be a good idea to get back to the basics. It's a large post, so there's a recap at the end.
Colour can be represented in a couple of ways. We can have Red, Green and Blue (RGB). We could have CMYK (used in printing). There's also YCbCr/YUV (one for luminance and two for colour) and similar flavours of that. We have HSV/HSL/HSB (hue, saturation, value/luminance/brightness). And even more. These are called colour models (or color models, depending on where you live). RGB is the most popular model in terms of computer graphics. It's how colour film stock, digital sensors, monitors and roughly our eyes work. So, from now I'll be using the RGB colour model. The things in the rest of this post will have equivalents for the other models, but for simplicity it's just RGB for now.
We have three values, R G and B, but that raises the question. If we have 100% red, 0% green and 0% blue, what kind of red is it? The answer is, we don't know. So, we have to define what kind of red red is, what kind of green green is, what kind of blue blue is and what kind of white white is. White is also important to define. This definition is called the colour gamut. The colour gamut defines the chromaticities for red, green, blue and white. Chromaticity is colour but without the luminance (basically just the hue and saturation). By defining the colour gamut, we will know exactly what colour we have for any given RGB value.
But there's another thing. If we want to send an image to our monitor or save it to a file on our drive, we don't want to have to send over or save a lot of data. We basically want to use the least amount of bits we can. We found out that having 8 bits for the red, green and blue values is enough. However! Our eyes are more sensitive to changes in brightness in dark areas and less sensitive in bright areas of an image. So, while 8 bits is enough for the bright areas, in the darker areas we can really see that we only have 256 possible values for red, green and blue. We fix this by moving around the values in order to use more of those 256 values for the darker areas and less on the brighter areas. Right now I am using 8 bits as an example, but this is the same for any amount of bits (10 and 12 bits is also popular but has the same problem). We do this using a transfer function. In short, a transfer function redistributes the values in order to more efficiently use a limited amount of bits.
Gamma correction (or just gamma) is a form of a transfer function. As you can see in your graph (the blue line) it nudges the values upwards which means that the range [0,0.5] becomes [0,0.73]. This means that we have almost 50% more bits for the darker areas of our image! That's what we want. Gamma isn't the only kind of transfer function. Another popular one is log, which is an umbrella term for transfer functions (or colour spaces using transfer functions) that make use of logarithms. With logarithms, each stop of light gets roughly the same amount of bits, which is really useful for images that have a very high dynamic range (like what comes out of a cinema camera). Perceptual quantizer (SMPTE ST 2084) is another transfer function that is used a lot in HDR video (like HDR10 and Dolby Vision) and it's made to take advantage of how our eyes perceive brightness (which falls somewhere between a logarithmic curve and cube-root curve). Values that haven't been transformed by a transfer function are called linear.
When you combine a colour model, colour gamut and transfer function, you get a colour space. A colour space specifies how the colours are represented (what colour is what). There is one very important thing however, you do not need a transfer function for a colour space. sRGB is a very popular colour space which is used by practically every computer monitor. It uses the RGB colour model with the sRGB colour gamut (Rec.709 uses the same gamut) and the transfer function is generally a gamma of 2.2 (although it actually isn't, but most use the gamma for simplicity, go look at its Wikipedia page). But you also have linear-sRGB which is also a colour space that just like sRGB, uses the RGB model and sRGB gamut, but doesn't have a transfer function. The values are in linear (often referred to as "scene linear").
To try and make things a bit more clear, here's an example showing how a transfer function works when displaying an image that is either CGI or a video game being rendered. The first thing that is important is that both the computer/program and the display need to agree on the colour space to use. In this example, we use sRGB. Basically, the program sends the sRGB image to the display and the display takes that sRGB image and converts it to the actual electronic signals to send to the pixels.

And now we finally get to tone mapping. A tone mapper is a function that takes in a large, generally infinite, range of values and compresses it to a smaller, often limited, range of values. Tone mapping is generally used to apply a "look". A very popular tone mapping is the filmic s-curve, which is called a "film characteristic curve" or "Hurter–Driffield curve". It adds some contrast in the shadows and instead of the highlights clipping once they reach 100% brightness, it adds a nice roll-off that gradually brings it to 100%. This tone mapper is used in a lot of places. It's how film stock behaves, it's what digital cinema cameras often do, in video games they use this curve. Basically, because it looks good and with it we can see values above 100% (because the tone mapper maps it to something below 100%). If you want to tone map your image, it should be done before the transfer function/colour space conversion (for example converting from linear-sRGB to sRGB), because tone mapping isn't part of a colour space and is basically a look (just like applying a filter over an image).
However, you don't need a tone mapper. If you take a cheap camcorder, DSLR, your phone (depending on the settings) or a broadcast camera they use to film the news and such (especially before the 2010s), then all of them don't do any kind of tone mapping. They just apply the sRGB or Rec.709 colour space (and thus also the transfer function) and that's it. What you often do see is that parts of the image go to 100% white very quickly and then clips Here's a picture that I took with my phone. It's just normal average sRGB and no tone mapping.
You can see that the cloud is completely white and the trees are quite dark. Using a tone mapper, I could bring those values closer together and not have the clouds be 100% white without any detail, while still being able to see detail in the trees.
To recap

Gamma correction is a type of transfer function, which is part of a colour space.
A colour space tells us how to represent and store colours.
When we want to send images to our display, we need to apply the transfer function.
The display will undo that transfer function (and will do it no matter what, so you have to apply the transfer function on your end to get the correct values when displayed).
A tone mapper is both to apply a look and to compress the range of RGB values to a smaller range so that we can see a high dynamic range image on a standard dynamic range monitor.
While you need to apply a transfer function when sending the image to the display, you don't need to apply a tone mapper. Only if you want to.


Section "17.3.8 Blending" of the OpenGL spec states:

  If the color buffer is fixed-point, the components of the source and destination values and blend factors are each clamped to [0, 1] or [-1, 1] respectively for an unsigned normalized or signed normalized color buffer prior to evaluating the blend equation. If the color buffer is floating-point, no clamping occurs. The resulting four values are sent to the next operation.

So we know that no clamping occurs there. The next section is "17.3.8.1 Blend Equation" and states:

  Signed or unsigned normalized fixed-point destination (framebuffer) components are represented as described in section 2.3.4. Constant color components, floating-point destination components, and source (fragment) components are taken to be floating-point values. If source components are represented internally by the GL as fixed-point values, they are also interpreted according to section 2.3.4.

Finally, section "17.3.8.2 Blend Functions" refers to table 17.2 which explains that for GL_SRC_ALPHA_SATURATE:

RGB Blend Factors = (f, f, f)
Alpha Blend Factor = 1

where

$$ f = min(A_{s0}, 1 - A_d) $$

So it seems that the reference documentation is misleading for this particular case. However the specification is clear: there is no clamping or conversion for floating-point color buffers.

What if Ad is negative floating value?

My reading of the spec is that nothing special happens if Ad is negative. The min() operation will still produce results, but I don't see how they would be useful.

I've never used GL_SRC_ALPHA_SATURATE myself, but the way I understand it, with GL_FUNC_ADD, it is meant to accumulate color values in the color buffer until the accumulated alpha value equals 1. When the alpha value of the color buffer is 1, no further color contribution from new pixels is allowed. This assumes that you use alpha values between 0 and 1 and use an initial alpha value of 0. Otherwise everything falls apart.

In fact, I think majority of the blending factor mechanisms were designed with alpha values between 0 and 1 in mind and make little sense outside of that range.


Assuming that the normal was created by differentiating some height field f(u,v):

N = normalize(df_du, df_dv, 1)

What you probably want to achieve is to "strengthen" your normals as-if by scaling that height field by a factor C:

g(u,v) = C*f(u,v)

Then your new normal would be:

M = normalize(dg_du, dg_dv, 1) = normalize(C*N0, C*N1, N2)

Translating that to GLSL in your shader:

vec3 GetNormal(){
    vec3 n = texture(normalMap,uv).xyz;
    n = n * 2.0 - 1.0;
    n.xy *= C;
    n = normalize(n);
    return  normalize (v_TBN * n);
}

By constructing a normal map texture that stores only the height-field gradient (df_du, df_dv) without normalization, using the internal format GL_RG8_SNORM for the texture, and making sure that v_TBN is orthonormal, you can simplify it further to:

vec3 GetNormal() {
    vec3 n = normalize(vec3(texture(normalMap,uv).xy, C));
    return v_TBN*n;
}


Looking for a compact file format for outputting 3D geometry with color support

The PLY file format is a simple format similar to OBJ that allows arbitrary attributes (like colours) and has a binary mode.


Variance of estimator (Monte Carlo Integration)

Quoting from "Advanced global illumination" book:

The Monte Carlo estimator is defined as:

And its variance according to the above definition(continuous random variable) would be:

Edit:

An example for how the variance of an estimator G is calculated:

(note how the summation is written as N times the integrand and is cancelled out later.)


shaderc compile through api with #include

It is your responsibility to support includes by instantiating an IncluderInterface instance and calling SetIncluder(...) on the options instance.

The interface includer API consists of the following methods:

// Handles shaderc_include_resolver_fn callbacks.
virtual shaderc_include_result* GetInclude(const char* requested_source,
                                           shaderc_include_type type,
                                           const char* requesting_source,
                                           size_t include_depth) = 0;

// Handles shaderc_include_result_release_fn callbacks.
virtual void ReleaseInclude(shaderc_include_result* data) = 0;

It will therefore also be your responsibility to implement these functions and interpret the #include directives from the GLSL into shaderc_include_result instances that will be used by shaderc to complete the preprocessing of the GLSL.


Most efficient way to render many OO meshes in OpenGL

Don't copy around huge chunks of data if you don't have to.

I would delay collecting and building the final forest mesh for as long as possible.

However when you have multiple of the same mesh that just needs to be translated and rotated a bit you can use instancing. Which lets you draw thousands of copies of a tree with a single draw call.

The most efficient way of getting data to the gpu is to map the buffer and fill that. In java that means using a Buffer.


Two-dimensional bounded area defined parametrically

One solution is bilinear mapping, which works for every convex quadrilateral.

Let $A, B, C, D$ be the vertices of a quadrilateral $Q$ in the plane, in this order.

Then $f(u,v)=(1-u)(1-v)A + u(1-v)B + uvC + (1-u)vD$ maps the square $[0,1] \times [0,1]$ to $Q$.


Illumination model used in the "Raytracer in a weekend" series

It’s a “naive” Monte Carlo sampler so it’s too dumb to send rays toward lights— it shotguns.   But the light is just a hemisphere (like a cloudy day) so you don’t get punished with too much noise.   Cloudy days look pretty good in real life.   But if you try to add a small light it will work but get very very noisy.   The third book in that series uses one method to address this (basically sending more rate where lights are rather than shadow rays per se)


Avoiding CPU race condition/cache invalidation of RNG on multi thread path tracing

You need to implement your own RNG class and not use the clib RNG implementation that shares the state across threads. What I'm using is a simple & efficient multiply-with-carry RNG by George Marsaglia, that I initialize with a seed based on pixel coordinates (e.g. simple x+y*width) that I'm calculating (state per pixel instead of global state)


Does atomic functions on same memory location cause an performance issue?

Will having all invocations incrementing the same atomic counter be slower than not doing that? Sure. How much slower? That depends on many factors, but it's hardly going to be a crippling performance issue.
The whole point of atomic memory operations is that there is some hardware mechanism that allows them to work reasonably efficiently. Not as efficiently as bumping a local variable of course, but they shouldn't be assumed to cause a massive performance penalty.
On some hardware, atomic counter operations aren't even memory operations. AMD implements them as specialized hardware within their shader system, such that atomic counter operations don't touch actual memory storage until after the rendering process that uses them is complete.
Obviously, the best thing you can do is profile on your hardware-of-choice, but failing that, I would see no reason not to use this mechanism as you see fit.


Experimental real-time shadowing techniques?

There’s an interesting technique that’s been used in demoscene and Shadertoy projects for a while, and an analogue of which recently made it into Unreal Engine 4: using signed-distance fields and raymarching to produce high-quality soft shadows with accurate penumbras.

There’s a good writeup of the idea, with some visual examples, by Íñigo Quílez here—I’m not sure whether he invented the technique or was just one of the first to write about it:

  The trick is to think what happens when a shadow ray doesn't hit any object, but was just pretty close to do so. Then, perhaps, you want to put that point you are shading under penumbra. Probably, the closest your point was to hit an object, the darker you want to make it. Also, the closest this happened from the point you are shading, the darker too. Well, it happens that as we raymarched our shadow ray, both these distances were available to us! … So, we can simply compute a penumbra factor for every step point in our marching process and take the darkest of all penumbras.

The documentation on the corresponding Unreal feature is here; their description of the technique is a little vaguer, but still helpful.

  To calculate shadowing, a ray is traced from the point being shaded through the scene's Signed Distance Fields (SDF) toward each light. The closest distance to an occluding object is used to approximate a cone trace for about the same cost as the ray trace. It allows for high-quality area shadowing from spherical light source shapes.

The main advantage of this approach is its high visual quality—most other techniques don’t handle varying penumbras well, and it doesn’t suffer as much from the aliasing problems of shadow maps. The main disadvantage is needing a distance-field representation of your scene geometry to trace rays through; unless you built it that way in the first place (there’s a fascinating talk about how the team behind “Dreams” did exactly that), you’ll need a way to construct the SDFs out of your mesh geometry, which is an expensive and sometimes error-prone operation.

UE4 handles the SDF generation by building them offline beforehand and then stamping them into a volume around the camera at runtime (more information on that here), but it’s not a cheap process so UE’s approach is only viable on high-end hardware for now. That said, if you do already have your scene geometry in SDF form, it’s quite easy to implement—see this Shadertoy for an example.


Your first version was correct, except that alpha and 1-alpha should be swapped (the result should be a when alpha == 0 and b when alpha == 1).

For Phong shading, you do want to keep the normalize on the end; that's the key thing that makes Phong different from Gouraud shading. But also, normalize isn't part of the usual definition of "lerp" (linear interpolation), so I would keep it out of the lerp function, and move the normalize to the Phong shading function where you call lerp.


Is "generative art" the best term for describing graphical techniques like ASCII art or photo mosaics?

Generative art (Wikipedia) doesn't necessarily start with an image as the input, and ASCII art can be drawn/typed by hand (in a text editor) especially for ASCII line art (which I've often used for diagrams) or "oldskool" ASCII art.

While there may be overlap, generative art is neither a synonym nor a hypernym for ASCII art.  Note that your pen-plotter example is different again in that the computer-controlled physical output (e.g. choice of pen or even brush on similar devices) is a crucial part of the process but a human is likely to do a fair bit of image manipulation first.  ASCII art and photo-mosaics are essentially the same on screen or printed.

Sticking with Wikipedia, algorithmic art seems closer, if you exclude hand-typed ASCII art, but this still doesn't fit the robotic drawing of your second example (not robotic art, which is art consisting of robots rather than made by robots).

What you're looking for is actually quite broad, and computer art may be as close as you're going to get, though computer art includes things like this:

 (example borrowed from a previous answer of mine)


There's nothing like frame capture for OpenGL on macOS, unfortunately. But there are 2 other tools that are useful for GL debugging: OpenGL Profiler and OpenGL Driver Monitor. You can read about them here. (Warning the images in the article are really old. They look like normal apps today without all the brushed metal, etc.) To download them, you need to log in to your developer account on developer.apple.com, click on "Downloads" on the left side. On the downloads page in the upper right is a tiny "more" link. If you click on that, you'll get the search tool. Enter "OpenGL Profiler" for your search and you'll be presented with a number of packages for different versions of Xcode. Choose the one that matches whichever version of Xcode you have. It's in the "Graphics Tools" section of the download.

OpenGL Profiler can show you the resources currently in use by a program. You can set breakpoints on any OpenGL call and when it breaks you can see all textures, shaders, FBOs, etc. and see what their contents are as well as all OpenGL state.

OpenGL Driver Monitor will graph over time how many textures are in use, or how much texture memory, etc. It can tell you the frequency of page-ons and page-offs for the GPU and other useful statistics.