GLSL - Merge two textures I would like to display arbitrary 3d meshes with black edges (black outline, black ridges, etc.). Thereby I have created two different textures: One color texture and one anti-aliased edge texture.

Here is an example of the color texture:

And the the corresponding edge texture:

Now I'd like to merge both textures. The edge texture has a white background with black/grey edges. I used fxaa, therefore some pixels are grey.

My question: How can I combine (blend) both textures correctly? And do I have to apply fxaa for the color texture, too?

EDIT: For completeness, here's the fxaa-shader code:

    #version 330 core

in vec2 texPos;
out vec4 color;
uniform sampler2D colorTexture;
uniform float rt_w;
uniform float rt_h;

vec4 PostFX(sampler2D tex);
vec3 FxaaPixelShader(sampler2D tex, vec2 rcpFrame);

void main()
{
    color = PostFX(colorTexture);
    //color = texelFetch(colorTexture, ivec2(gl_FragCoord), 0 );
}

vec4 PostFX(sampler2D tex)
{
  vec4 c = vec4(0.0);
  vec2 rcpFrame = vec2(1.0/rt_w, 1.0/rt_h);
  c.rgb = FxaaPixelShader(tex, rcpFrame);
  c.a = 1.0;
  return c;
}

vec3 FxaaPixelShader(
  sampler2D tex, // Input texture.
  vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}.
{
/*---------------------------------------------------------*/
    #define FXAA_REDUCE_MIN   (1.0/128.0)
    #define FXAA_REDUCE_MUL   (1.0/8.0)
    #define FXAA_SPAN_MAX     8.0
/*---------------------------------------------------------*/
    vec3 rgbNW = texture(tex, vec2(texPos) + (vec2(-1,-1) * rcpFrame.xy)).xyz;
    vec3 rgbNE = texture(tex, vec2(texPos) + (vec2(1,-1) * rcpFrame.xy)).xyz;
    vec3 rgbSW = texture(tex, vec2(texPos)+ (vec2(-1,1) * rcpFrame.xy)).xyz;
    vec3 rgbSE = texture(tex, vec2(texPos) + (vec2(1,1) * rcpFrame.xy)).xyz;
    vec3 rgbM  = texture(tex, vec2(texPos)).xyz;
/*---------------------------------------------------------*/
    vec3 luma = vec3(0.299, 0.587, 0.114);
    float lumaNW = dot(rgbNW, luma);
    float lumaNE = dot(rgbNE, luma);
    float lumaSW = dot(rgbSW, luma);
    float lumaSE = dot(rgbSE, luma);
    float lumaM  = dot(rgbM,  luma);
/*---------------------------------------------------------*/
    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
/*---------------------------------------------------------*/
    vec2 dir;
    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
/*---------------------------------------------------------*/
    float dirReduce = max(
        (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),
        FXAA_REDUCE_MIN);
    float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
    dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),
          max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
          dir * rcpDirMin)) * rcpFrame.xy;
/*--------------------------------------------------------*/
    vec3 rgbA = (1.0/2.0) * (
        texture(tex, texPos.xy + dir * (1.0/3.0 - 0.5)).xyz +
        texture(tex, texPos.xy + dir * (2.0/3.0 - 0.5)).xyz);
    vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (
        texture(tex, texPos.xy + dir * (0.0/3.0 - 0.5)).xyz +
        texture(tex, texPos.xy + dir * (3.0/3.0 - 0.5)).xyz);
    float lumaB = dot(rgbB, luma);
    if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA;
    return rgbB;
}

The simplest solution would be just a multiplication, which would give black edges:

combinedColor = sceneColor * edgeRGB.r;

For more control I would suggest something very similar to what @PaulHK proposed in the comments:

float opacity = maxEdgeOpacity * (1. - edgeRGB.r);
combinedColor = mix(sceneColor, edgeColor, opacity);

edgeColor is the desired edge color and maxEdgeOpacity is meant to be a parameter between 0 (no edges at all) and 1 (opaque edges), that you both choose to your liking.


Is my perspective math correct? I've got a homework in which I have to calculate and plot some points using a pespective transformation, but I'm not sure my results are correct, since the 3d plot using Camera coordinates looks very different from the 2d plot using the image coordinates. Can you help me understand what's wrong?

This is what is given:
The camera is at the point $_WT^C = [−1, 1, 5]^T$, specified in world coordinates (in meters). The camera coordinate system is rotated around the Y axis of the world reference by $\theta = 160^o$, so it's rotation matrix is $^wR_c = \begin{bmatrix}cos(\theta) & 0 & sin(\theta)\\ 0 & 1 & 0 \\ -sin(\theta) & 0 & cos(\theta)\end{bmatrix}$

Camera parameter are: $f = 16mm$, $s_x = s_y = 0.01 mm/px$, $o_x = 320 px$, $o_y = 240px$

Sample points (in world coordinates):

$^WP_1 = [1, 1, 0.5]^T$

$^WP_2 = [1, 1.5, 0.5]^T$

$^WP_3 = [1.5, 1.5, 0.5]^T$

$^WP_4 = [1.5, 1, 0.5]^T$

I have to calculate and plot the points in camera coordinates and in image coordinates, so I wrote the following code in Octave:

%camera intrinsic parameters
f = 16
Sx = 0.01
Sy = 0.01
Ox = 320
Oy = 240

%given points, in world coordinate
wP1 = transpose([1, 1, 0.5])
wP2 = transpose([1, 1.5, 0.5])
wP3 = transpose([1.5, 1.5, 0.5])
wP4 = transpose([1.5, 1, 0.5])

% camera translation matrix
wTc = transpose([-1, 1, 5])

% rotation angle converted to rad
theta = 160 / 180 * pi

%camera rotation matrix
wRc = transpose([cos(theta), 0, sin(theta); 0, 1, 0; -sin(theta), 0, cos(theta)])

%transform the points to homogeneous coordinates
wP1h = [wP1; 1]
wP2h = [wP2; 1]
wP3h = [wP3; 1]
wP4h = [wP4; 1]

%separate each line of the rotation matrix
R1 = transpose(wRc(1 , :))
R2 = transpose(wRc(2 , :))
R3 = transpose(wRc(3 , :))

%generate the extrinsic parameters matrix
Mext = [wRc, [-transpose(R1) * wTc; -transpose(R2) * wTc; -transpose(R3) * wTc]]

%intrinsic parameters matrix
Mint = [-f/Sx, 0, Ox; 0, -f/Sy, Oy; 0, 0, 1]

% calculate coordinates in camera coordinates
cP1 = wRc * (wP1 - wTc)
cP2 = wRc * (wP2 - wTc)
cP3 = wRc * (wP3 - wTc)
cP4 = wRc * (wP4 - wTc)

% put coordinates in a list for plotting

x = [cP1(1), cP2(1), cP3(1), cP4(1), cP1(1)]
y = [cP1(2), cP2(2), cP3(2), cP4(2), cP1(2)]
z = [cP1(3), cP2(3), cP3(3), cP4(3), cP1(3)]

%plot the points in 3D using camera coordinates
plot3(x, y, z, "o-r")

pause()

% calculate the points in image coordinates
iP1 = Mint * (Mext * wP1h)
iP2 = Mint * (Mext * wP2h)
iP3 = Mint * (Mext * wP3h)
iP4 = Mint * (Mext * wP4h)

%generate a list of points for plotting
x = [iP1(1) / iP1(3), iP2(1) / iP2(3), iP3(1) / iP3(3), iP4(1) / iP4(3), iP1(1) / iP1(3)]
y = [iP1(2) / iP1(3), iP2(2) / iP2(3), iP3(2) / iP3(3), iP4(2) / iP4(3), iP1(2) / iP1(3)]

plot(x, y, "o-r")

pause()

And these are the plots I've got from the script:
I was expecting they were somewhat similar, but they don't look so.

Plot in camera coordinates

Plot in image coordinates

Identifying your axes in both figures and adding the camera position to your first figure would help you understand what's going on.

You could also have a single variables for all your points, generating a 2D matrix with the rows as each point and columns as the components $x$, $y$ and $z$. That way, you could handle the projection using a simple matrix multiplication instead of handling each row separately.

In the problem statement, would be interesting to know the direction of your rotation, and more importantly, the original camera direction and its up vector. I guess you camera is rotated by 160° counter-clockwise, the original camera direction is $[0, 0, 1]$ and its up vector is $[0, 1, 0]$. If any of those assumptions is wrong, the rest of the answer will be wrong.

There is no sign of mm to m conversion in your code. Either your focal should be $0.016$ and $S_x = S_y = 0.0001$ or your point coordinates should be multiplied by $0.00001$.

Let's reason about where should the points end up in your image. For example, your camera center, without rotation, is pointing at the $[-1,1,x]$ line. Since the points are all on the $z=0.5$ plane, we can do the following analysis: if we focus on the $x$-axis, we can see that $tan(160°) \cdot (5 - 0.5) = 1.64...$, so the camera center will end up slightly to the left of the points (as the camera is at $x=-1$), so the center will end up at $\approx 0.64$, meaning that the points will appear on the right section of the image. Furthermore, the camera has the same $y$ coordinates as two point, and since the $y$ coordinates are not changed by the rotation, they should still end up on the same coordinates after the transform, meaning on the central row of the image.

A good way to check your answer is by using an existing 3D modeler like Blender:

Be cautious with Blender' coordinates system, for example the default camera vector is [0, 0, -1].
Here's the render:

Focal was set to another value to make the sphere more visible. So we see that the bottom two points are on the middle row of the image and the points are slightly to the right of the image.

I implemented your homework in Python:

import numpy as np

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d, Axes3D

# Parameters
f_mm = 0.016
f_px = f_mm / 0.00001
t_cam = np.array([[-1., 1., 5.]]).T
t_cam_homogeneous = np.vstack((t_cam, np.array([[0]])))
theta = 160. * np.pi / 180.
ox = 320
oy = 240
# Rotation and points are in homogeneous coordinates
rot_cam = np.array([[np.cos(theta), 0, np.sin(theta)],
                    [0, 1, 0],
                    [-np.sin(theta), 0, np.cos(theta)]])
points = np.array([[1, 1, 0.5, 1],
                   [1, 1.5, 0.5, 1],
                   [1.5, 1.5, 0.5, 1],
                   [1.5, 1, 0.5, 1]]).T

# Compute projection matrix using intrinsics and extrinsics
intrinsics = np.array([[f_px, 0, ox],
                       [0, f_px, oy],
                       [0, 0, 1]])
extrinsics = np.hstack((rot_cam, rot_cam.dot(-t_cam)))

rot_cam2 = np.identity(4); rot_cam2[:3,:3] = rot_cam
camera_coordinates = rot_cam2.dot(points - t_cam_homogeneous)
camera_coordinates = camera_coordinates[:3,:] / camera_coordinates[3,:]

# Perform the projection
projected_points = intrinsics.dot(camera_coordinates)
projected_points = projected_points[:2,:] / projected_points[2,:]
projected_points[0,:] = -projected_points[0,:] # Inverted x-axis because camera is pointing toward [0, 0, 1]

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(points[0,:], points[1,:], points[2,:], label="Points")
ax.scatter(t_cam[0], t_cam[1], t_cam[2], c="red", label="Camera")
ax.set_xlabel("X axis"); ax.set_ylabel("Y axis"); ax.set_zlabel("Z axis")
plt.title("World coordinates")
plt.legend()
plt.savefig('world_coordinates.png', dpi=300, bbox_inches="tight")

fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(camera_coordinates[0,:], camera_coordinates[1,:], camera_coordinates[2,:], label="Points")
ax.scatter(0, 0, 0, c="red", label="Camera")
ax.set_xlabel("X axis"); ax.set_ylabel("Y axis"); ax.set_zlabel("Z axis")
plt.title("Camera coordinates")
plt.legend()
plt.savefig('camera_coordinates.png', dpi=300, bbox_inches="tight")

plt.figure()
plt.scatter(projected_points[0,:], projected_points[1,:])
plt.xlabel("X axis"); plt.ylabel("Y axis")
plt.title("Image coordinates")
plt.savefig('image_coordinates.png', dpi=300, bbox_inches="tight")

plt.show()

This yield me those figures:

Respectively: World coordinates, Camera coordinates, Camera coordinates rotated to fit slightly the camera orientation (note that here the camera vector goes toward the figure viewpoint, it does not "enter" the figure) and image coordinates.

So we see that the vertical coordinates for the bottom points are correctly on the middle row (240) and the points are on the right side of the image (horizontal value > 320).

I believe one bug you had is that you found negative X values, so you negated the focals (-f/Sxy) in the intrinsics matrix to compensate. The issue here is that we've assumed that the camera initially was pointing toward $[0, 0, 1]$ (otherwise the 160° rotation would not point toward the points). If you look at it that way, the $x$-axis increases when going toward the left, the inverse of this axis should be taken.

Both our results seems similar to me, just that you supposed a $[0, -1, 0]$ up vector for the camera (in fact both axes were mirrored because you negated both focals), and did the computation in mm instead of meters.


Trouble using Open Image Denoise I'm trying to use open image denoise. Here's the code:

int main() {
    int width, height, nrChannels;
    unsigned char* image = stbi_load("img_cornell_box.png", &width, &height, &nrChannels, 0);
    unsigned char* resultImage = new unsigned char[width*height*nrChannels];
    oidn::DeviceRef device = oidn::newDevice();
    device.commit();
    std::cout << nrChannels << std::endl;
    oidn::FilterRef filter = device.newFilter("RT");
    filter.setImage("color", image, oidn::Format::Float4, width, height);
    filter.setImage("output", resultImage, oidn::Format::Float4, width, height);
    filter.set("hdr", false);
    filter.set("srgb", true);
    filter.commit();
    filter.execute();

    const char* errorMessage;
    if (device.getError(errorMessage) != oidn::Error::None) {
        std::cout << "Error: " << errorMessage << std::endl;
    }
    else {
        stbi_write_png("img.png", width, height, nrChannels, resultImage, width * nrChannels);
    }
}

I'm getting an error saying that the image format is unsupported.

If I use jpg, and change Format::Float4 to Format::Float3 I get this error:

Exception thrown at 0x00007FFC5588E1F5 (OpenImageDenoise.dll) in oidntest.exe: 0xC0000005: Access violation reading location 0x0000021D9C42FA70.

Am I doing something wrong?
This is the image I'm using: https://drive.google.com/open?id=1uSjsyWCRisXNFUJG6R8iL5AdVbM7_18u

As far as I remember, you need to input data in float array. Right now your input is unsigned char array. To quick check this, try loading any HDR image in float array & pass it on to the setImage functions, this seems to work.

In your case, you would need to read individual image channel data & cast it to float. If your image color is stored in [0-255] range, you would then need to bring it to [0-1] range (Not completely sure about this stage!) & then pass the data in float array to denoiser functions.

Hope this helps.


Multiplication of SH coefficient sets representing occlusion and color Currently I got interested in implementation of Precomputed Radiance Transfer.

I decided that occlusion representation (which is not trivial to compute) would be precomputed as CPU raytracing and stored as vertex buffer in addition to usual vertices. This representation would be stored as SH coefficients because I need to have information about occluded and unoccluded directions (probably 4 so additional vec4 buffer). So these would store only unoccluded directions. I don't know yet how that would behave but using this foreach vertex should make it quite accurate despite being low frequency.

And as for color representation, computing it is quite trivial (transforming image representing skymap scattering and normals into SH set) and I want it to be dynamic so it would be done every frame. These would be 9 coefficients because why not.

So in reconstruction step I would have two sets of coefficients: precomputed occlusion (4 coefficients) and real time color (9 coefficients for RGB so in sum 27 coefficients).

Can I (and how) multiply them (as in the picture below from this paper) so in the result I would get representation with occluded color filtered out?

I was overthinking it. The usual reconstruction for given direction and then multiplication will work fine probably.


is a scene graph actually a tree? All "scene graphs" I've seen in practice are actually trees, but I have some vague memories about somebody saying a while ago that sometimes they can actually be graphs (technically, trees are already graphs, but you get the point).

If they can actually be graphs, what are some practical examples?

If they're always just trees, is there some history behind why it was originally called "scene graph"?

Yes, scene graphs can be non-tree graphs. Your question is a little vague, but assuming you're talking about something like the scene graph in rendering a frame of video, for say a feature film, then yes, there are often references between objects. For example, in a compositing application, you might have a piece of footage with an effect applied. The effect may have as one of its inputs another piece of footage which is also in the scene. (It might use the other image for blending, as a reflection map, as a diffuse or specular lighting map, a bump map etc.) So you could have a scene that looks like this:

scene contains:
    footage A contains:
        filter "Multiply Blend" which takes input:
            footage B
    footage B
    footage C

In something like a game, you might objects that refer to other objects that they can collide with:

scene contains:
    ground which can collide with:
        player
        ball
        goal
    player which can collide with:
        ground
        ball
        goal
    ball which can collide with:
        player
        ground
        goal

etc.


How to invert an affine matrix with small values? I'm using an affine transformation matrix to transform 2D coordinates from screen (magnitude 10e3) to small parts of fractal sets (magnitude as little as 10e-15).

I also need to map the other way round, so I simply invert the matrix. It works when the magnitudes are not too far apart, but it fails when the determinant gets too close to zero to be represented with standard double numbers.

The matrices I use are of the form:

a c e
b d f
0 0 1

And the inversion algorithm I have is:

var dt = a * d - b * c;
return new Matrix(d/dt, -b/dt, -c/dt, a/dt, (c * f - d * e) / dt, -(a * f - b * e) / dt);

Is there an alternate way of inverting the matrix? I'm not very good at mathematics, so I would need a simple solution, and one I could find the code, or an algorithm, for.

An example of such a matrix:

 3.26091378894248e-9   -1.882689453850103e-9   -0.7172216437740687
-1.882689453814925e-9  -3.2609137888815494e-9  -0.23371832131832268
 0                      0                       1

I found a solution to my specific problem. Instead of computing the determinant and hitting the precision wall, I use the Gauss-Jordan method step by step.

In my specific case of affine transformation matrices and the range of values I use, I don't hit any precision problem this way.


Factor of 2 converting radiance to irradiance For a Lambertian surface, the radiance at a point is

$$L = \frac{\alpha}{\pi}\cos\theta_i E_0$$

If we have an infinite flat surface, albedo = 1, illuminated directly normal, then we get

$$L = \frac{E_0}{\pi}$$

But now suppose we are sitting very close to the surface. The surface occupies $2\pi$ sr of our view, so the irradiance we measure is

$$E_r = 2\pi L = 2E_0$$

Is this correct? I was expecting to get $E_0$ back again. $2E_0$ makes it feel like we're violating the conservation of energy or something.

I don't really understand what are you doing. I think your first equation shouldn't have a cos factor in it.

We have the relation,

$BRDF = dL_r / dE_i$

That is the brdf is the ratio of reflected radiance to incoming "irradiance". Re-arranging this gives us,

$ dL_r =  BRDF * dE_i$

For diffuse surfaces we know,

$BRDF = \alpha/\pi$

Substituting in above equation we have,

$dL_r = \alpha/\pi * dE_i$

Irrespective of what angle we view, the radiance is the same. Now for a diffuse surface with albedo = 1 we have what you said,

$dL_r = dE_i/\pi$

Now in order to measure Irradiance, we can use the relation,

$E = \int_{2\pi} L \cos(\theta) d\omega$

$E = \displaystyle\int_{\phi = 0}^{2\pi} \displaystyle\int_{\theta = 0}^{\pi/2} L \cos(\theta) \sin(\theta) d\theta d\phi$

$E = E/\pi * \pi$

$E = E$

So you got back the same irradiance.


Matching a virtual camera to a physical camera Say I've got a photograph of a scene, and measurements for part of it (eg. a room where I know the dimensions of the walls).  Assuming a rectilinear lens, how would I go about setting up a virtual camera so that 3D objects are rendered as if they were in the physical scene?

This is the Camera re-sectioning problem.

We need to have a few points, like the end points of the walls, to take the roles of xw, yw and zw in the following equation:

Here A is defined as:

These are the values of the camera itself.

R and T are defined as the Rotation and Translation matrices for the camera, and are the values we need to solve for. The position, C, of the camera expressed in world coordinates is C = -R-1T = -RT T .

The linked Wikipedia article mentions a few algorithms to solve these equations.

An example of a practical application of these is also found on Math Stack Exchange.

Another example, with some code samples that you may want to use, is found Stack Overflow.


Is there an algorithm to bold an outline font? One of my friend got a pretty pretty Chinese hand-writing font. However, the font has no bold version, since it is handwritten. And I would like to help generate a bold one automatically by code.

I searched the Internet but didn't find any materials about it. My friend told me that his Kindle could "bold" that font automatically by setting "contrast". So I tried to firstly convert the outline font to bitmap, then change the contrast of the glyphs one by one, and finally output a bitmap "bolded" font. Everything went well except the processed font is aliased, i.e. looks blocky, since that the bitmaps is binary images, i.e. there are no gray pixels. But I can't find a popular font type that supports bitmap plus gray pixels.

So, is there an algorithm to bold an outline font? What is it?

The best way to do proper outlines, is unfortunately, also the hardest. It involves calculating an offset curve, usually from the medial axis or straight skeletons, which are non-trivial to calculate. Once you have those, you can calculate the distance of any point from the input object and decide whether to draw the outline or bolding, or not.

A simpler way to do it, which doesn't look quite as nice, is to use a MinMax filter. This is a sliding 2D box filter that calculates either the minimum or maximum value within the box at each input pixel. If you have black text on a white background, you can use the min filter to generate an outline. Use the max if it's white text on a black background. Other shapes, such as a circular area will produce different results that may be better for some fonts. In most cases, you'll end up either rounding off or squaring off corners as the size of the filter increases.


Hiding Boundaries with the Eye close to a set of adjacent textured quads I'm rendering clouds by applying a texture map on the inside of an ellipsoid. From a distance (at the center of the cloud ellipsoid) the texture looks quite nice and reasonably realistic. See image below:

The problem is that as I fly close to the boundary of the ellipsoid (into the cloud) I see the boundaries of each of the quads that make up the ellipsoid. See image below:

Any suggestions on how to get around this artifact would be appreciated. I'm using 50 grid segments in both the azimuthal and polar directions of the ellipsoid which is actually truncated 10 degrees below the poles. The texture map uses GL_MODULATE with GL_LINEAR and GL_LINEAR_MIPMAP_LINEAR for the Min and Mag filters. The ellipsoid base colour is white, so that there are no shading issues involved. I have also verified that the texture coordinates are correctly applied and the normals are oriented correctly.

Thanks in advance.

I could cheat and use a lot of fog which would mimic actually flying into a cloud, but I'd really like to implement an elegant robust solution.

I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.

What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.

As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!

Problem solved.

In case anyone else finds this useful, here's the code (I wrote it in VBA) to calculate averaged vertex normals given a set of vertices on a surface that is topologically rectangular.

Sub Calculate_Averaged_Vertex_Normals(Vertx#(), M%, N%, VnormX#())
' INPUT:
'L,M: Array Dimensions
' Vertx - 3D array of vertex coordinates
' OUTPUT: VnormX: 3D array of Averaged Vertex Normals

 Dim i%, j%, k%, p%, q%, w%, NormX#(3), Ncount%(), Vx#(), Fn#(3),Gn#(3),Hn#(3),A#
 ReDim Ncount%(0 To L, NF + 1), Vx(0 To L, NF + 1, 4, 3)
 For k = 0 To M - 1
  For i = 0 To N - 1
   Call Quad_Normal_Vector_Parametrisation(Vertx,k, i,Fn,Gn,Hn) ' Local Normals at each Vertex

     p = k: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w
  Next i
 Next k

 For k = 0 To M
  For i = 0 To N
   For w = 1 To 3
    A = 0#
    For j = 1 To Ncount(k, i)
     A = A + Vx(k, i, j, w)
    Next j
    VnormX(k, i, w) = A / Ncount(k, i)          ' Averaged Vertex Normal
   Next w
  Next i
 Next k
End Sub

Sub Quad_Normal_Vector_Parametrisation(Vertx#(),k%, i%,Fn#(),Gn#(),Hn#())
 Dim j%, Bv#(3), CV#(3), Dv#(3)
 For j = 1 To 3
  Bv(j) = Vertx(k, i + 1, j) - Vertx(k, i, j)           ' Tangent Vectors from Bilinear Parametrisation
  CV(j) = Vertx(k + 1, i, j) - Vertx(k, i, j)
  Dv(j) = Vertx(k + 1, i + 1, j) - Vertx(k, i + 1, j) - Vertx(k + 1, i, j) + Vertx(k, i, j)
 Next j
 Call CrossProd(Bv, CV, Fn)             ' Normal Vector from Cross Product of Tangent Vectors.
 Call CrossProd(Bv, Dv, Gn)
 Call CrossProd(Dv, CV, Hn)
End Sub

Sub Quad_Vertex_Normal(x#, y#, NormX#(),Fn#(),Gn#(),Hn#())
 Dim j%, Norm#
 Norm = 0#
 For j = 1 To 3
  NormX(j) = Fn(j) + Gn(j) * x + Hn(j) * y
  Norm = Norm + NormX(j) * NormX(j)
 Next j
 Norm = Sqr(Norm)
 For j = 1 To 3
  NormX(j) = NormX(j) / Norm
 Next j
End Sub

Sub CrossProd(x#(), y#(), Z#())
 Z(1) = x(2) * y(3) - y(2) * x(3)
 Z(2) = y(1) * x(3) - x(1) * y(3)
 Z(3) = x(1) * y(2) - y(1) * x(2)
End Sub


How to paint onto 3d models I have searched this topic for very long time and have found basically no information on it.
If we have a 3d model with a uv layout. What is the basic technique for 3d painting on said model with a brush? A brush stroke consists of the brush pixel data/image laid out in succession. So do we project each individual brush image onto the surface of the object? (Although in actuality to do this we would be projecting the object onto the image space instead). I have managed to project textures onto objects before. And projecting each individual brush image definitely seems feasible, but I'm not sure if it's practical from performance standpoint and whether there're better techniques.

As long as no pixel on the texture is used twice, you can render the geometry and display the uv-coordinates (texture coordinates). Usually they are a combination of red and green (2d).
When using a brush, you only need to read out the uv-coordinates you've hit and color the texture at position (uv) in the desired color.
Hint:
paint onto a second texture, so you'll not destroy the original texture color.
Drawbacks:
Sometimes the texture resolution of different triangles within a geometry vary. So at some faces it will look nice, and on others it will be pixelated.
As said before, if the mesh (geometry) uses the same part of a texture twice (two faces aiming at the same texture coordinates), and you draw on one of them, the other will be painted as well.


Can i compile my shaders to SPIR-V without using glslangValidator? I'm making a cross-platform application, and i need my shaders to be compiled to SPIR-V for both Opengl and Vulkan. It seems that the only way to do so is to call a separate program, called "glslangValidator.exe/.deb/.dmg". This sort of makes it cross-platform, but it requires me to change the command that calls the program on each platform (and that's not ideal to me). Can i embed some code or use something else to compile shaders directly from my application?

Typically compiling GLSL to SPIRV would be something you do as part of the build process, so that you end up distributing SPIRV instead of GLSL.  Then you don't need to compile it at runtime.  Assuming you're using the Vulkan SDK, the binary for glslangValidator (or a shell script to build it) should be part of the installed SDK.

That said, if you want to compile GLSL to SPIRV at runtime, you can link against the glslang library and do that.  Take a look at the Programatic Interface section in the readme.


Rendering equation - why unsolvable directly? Why is the rendering equation, introduced by Kajiya in 1986, not solvable directly/analytically?

I'm sadly not able to add a comment to the answer above (not enough reputation), so I will do it like this.

I'd like to point out that what Dragonseel describes is simply an integral equation (specifically a Fredholm equation of the second kind). There are many such equations which do have an analytic solution; even some forms of the rendering equation have one (e.g. the solution of a white furnace can be given using a simple convergent geometric series, even though the rendering equation is infinitely recursive).

It is also not necessary to bias the estimated solution by bounding the number of recursions. Russian Roulette provides an useful tool for giving us an unbiased solution for an infinitely recursive rendering equation.

The main difficulty lies in the fact that the functions for reflectance (BRDF), emitted radiance and visibility are highly complex and often contain many discontinuities. In these cases there often is no analytic solution, or it is simply unfeasible to find such a solution. This is also true in the one dimensional case; most integrals lack analytic solutions.

Finally I'd like to note that even though most cases of the rendering equation do not have analytic solutions, there is a lot of research in forms of the rendering equation which do have an analytic solution. Using such solutions (as approximations) when possible can significantly reduce noise and can speed up rendering times.


Transform a point into another point I have the following problem:

Give a matrix that will transform the point $(x,y,z)$ into the point $(\frac{2}{x+y}, \frac{5y + z}{2x + 2y}, 3)$.

I have been reading my book to find a way to solve it without success. I will very much appreciate your feedback about how to solve it.

The hint with the perspective division was already mentioned by ratchet freak, but I'd like to add some explanation of how to come up with the solution.

First of all, remember that homogenous coordinates add a fourth value $w$ to your 3D vector. For points in the 3D space, $w \neq 0$ holds and $[x, y, z, w] = [n*x, n*y, n*z, n*w]$ also holds for every $n$.

Now the goal is to find a transformation matrix $T$, which solves

$$
    \begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}
= T \cdot
\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
=
\begin{bmatrix} t_{11} & t_{21} & t_{31} & t_{41}  \\ t_{12} & t_{22} & t_{32} & t_{42} \\ t_{13} & t_{23} & t_{33} & t_{43} \\ t_{14} & t_{24} & t_{34} & t_{44} \end{bmatrix}
\cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
$$

These are basically four equations, but having a look at the first row, being

$$\frac{2}{x + y} = t_{11}\cdot x + t_{21}\cdot y + t_{31} \cdot z + t_{41}$$

and trying to find values for the $t$s, you'll see that this is not possible without further restructuring. The main problems are the $x$ and $y$ in the denominator. But as we can make use of the fourth value in the vector, we can expand the $w$.

$$
\begin{bmatrix} \frac{2}{x + y} \\ \frac{5y + z}{2x + 2y} \\ 3 \\ 1 \end{bmatrix}
=
\begin{bmatrix} \frac{2}{x + y} \\ \frac{2.5y + 0.5z}{x + y} \\ 3 \\ 1 \end{bmatrix}
=
\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}
$$

In the first step, I removed the factor of $2$ from the second values denominator, leading to every values denominator either being $1$ or $(x + y)$. In the second step, I made use of the above mentioned rule ($[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$), setting $n = (x + y)$, thus eliminating the denominator of the first two values.

Now we've got

$$
\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}
=
\begin{bmatrix} t_{11} & t_{21} & t_{31} & t_{41}  \\ t_{12} & t_{22} & t_{32} & t_{42} \\ t_{13} & t_{23} & t_{33} & t_{43} \\ t_{14} & t_{24} & t_{34} & t_{44} \end{bmatrix}
\cdot
\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
$$

which is not that hard anymore.

$$
\begin{bmatrix} 2 \\ 2.5y + 0.5z \\ 3(x + y) \\ x + y \end{bmatrix}
=
\begin{bmatrix} 0  &  0 &   0  &  2   \\ 0 &  2.5 & 0.5 &  0 \\ 3 &   3  &  0 &   0 \\ 1  &  1  &  0  &  0 \end{bmatrix}
\cdot
\begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
$$

TL;DR

Remember the advantage of homogenous coordinates $w$.
$[x, y, z, w] = [n\cdot x, n\cdot y, n\cdot z, n\cdot w]$ is the key.
Push everything that's in the denominator to the $w$ coordinate.


How many 3D textures does OpenGL support I'm making a voxel engine in OpenGL and wondering how many 3D textures I can have at once. They are fairly large (256x256x256 in GL_R32UI format). I want it to be able to run on any graphics card supporting OpenGL 3.3, if possible. I'm accessing them all from the same fragment shader, by the way. So how many can I have? Will 8 work? Thanks!

As gllampert pointed out in the comments the value is hardware dependent. You can retrieve it with glGet, using GL_MAX_COMBINED_TEXTURE_IMAGE_UNIT. You can find how different hardware performs here.

However, in OpenGL 3 there is a lower bound of at least 48 simultaneously used textures, no matter which type. [source]


Strategy for connecting 2 points without intersecting previously drawn segments of curves I have to connect point pairs without intersection.
Let's say I have two given points that I connect with a segment of a curve. Then again two new endpoints are selected and these new points have to be connected as well however without intersecting previously drawn curves and so on for any number of given point pairs.

What is the easiest way of finding and drawing these segments of curves?

The general problem is called graph drawing and is not an easy problem.
The graphs that can be drawn on the plane without crossings are called planar, but not all graphs are planar: the typical graphs that are not planar are the complete graph on $5$ vertices $K_5$ and the complete bipartite graph on 6 vertices $K_{3,3}$, famous because of the three utilities problem.
You may want to try Graphviz - Graph Visualization Software to produce nice drawings.
See also

Szirmay-Kalos, László, Dynamic layout algorithm to display general graphs, in Graphics Gems IV, 1994. code
Rosati, Claudio, A simple connection algorithm for 2-d drawing, Graphics Gems III, 1992, code.


Bresenham's Algorithm not drawing horizontal lines I'm getting started with graphics and I'm having trouble implementing the Bresenham's algorithm. Now, I know that my implementation is incomplente, but I can't see why it doesn't make horizontal lines(same height(y) values, different width(x values). I get a floating point exception. Here's the algo:

int draw_line(void *mlx_ptr, void*win_ptr, t_2dpoint *initial_p, t_2dpoint *final_p)
{
 53     int delta_x;

 53     int delta_x;
 54     int y;
 55     int delta_y;
 56
 57     delta_x = final_p->x - initial_p->x;
 58     delta_y = final_p->y - initial_p->y;
 59
 60     x = initial_p->x;
 61     y = initial_p->y;
 62     e = (float)(delta_x / delta_y) - 1.0;
 63
 64     while(x < final_p->x - 1)
 65     {
 66         mlx_pixel_put(mlx_ptr, win_ptr, x, y, 0XFF00FF);
 67         if ( e >= 0)
 68         {
 69             y += 1;
 70             e -= 1.0;
 71         }
 72         x += 1;
 73         e += (float)delta_x / delta_y;
 74     }
 75     mlx_pixel_put(mlx_ptr, win_ptr, x, y, 0XFF00FF);
 76 }

e = (float)(delta_x / delta_y) - 1.0;

e += (float)delta_x / delta_y;

Either of these lines will cause a divide-by-zero error when delta_y is zero, which is when the line is horizontal (or zero-length). You need to check for this condition and have some special-case code.

As an aside, I don't know why people still teach Bresenham's algorithm to new CG students. It's a good example of an algorithm but it's not very useful knowledge in itself: you're unlikely to need to know it unless it's for a job interview.


Get normalized device coordinate of an image pixel I have an image rendered to the screen, and based on the normalized device coordinates of the cursor I would like to pick the pixel of the image under the cursor.
Say the image has four channels, I then define a pixel struct:
struct Pixel {
  unsigned char r, g, b, a;
};

I can then get the closest index of the pixel under cursor like this:
int getPixel(float normalX, float normalY, float imageWidth, float imageHeight) {
  return (int)(normalY*imHeight)*imageWidth + normalX*imageWidth;
}

Now how would I do it the other way around, basically given the pixel index get its normalized device coordinates?

You can modulus by row length to retrieve the x coordinate (think about the x coordinate "wrapping around" after each line), and division by row length to get the y coordinate (inverting the multiply you have by imageWidth). We subtract one from the width and height to ensure the last pixel in the row/column maps to 1.0. Note that this isn't "Normalized Device Coordinates", since that implies a 3D quantity which also stores depth, and that all coordinates lie in [-1,1].
struct Point2D { float x; float y; };

Point2D GetNormalizedPixelCoords(int pixelIdx, int imageWidth, int imageHeight) {
    Point2D point;
    point.x = (pixelIdx % imageWidth) / (float)(imageWidth-1);
    point.y = (pixelIdx / imageWidth) / (float)(imageHeight-1);
    return point;
}


glDrawArrays is failing with GL_INVALID_ENUM I'm on OpenGL ES 3.0 using Mesa 17.0.3. When calling
glDrawArrays(GL_TRIANGLE_FAN, 0, 4),
glGetError() returns GL_INVALID_ENUM.

I have no idea what's causing it and https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glDrawArrays.xhtml is claiming that GL_TRIANGLE_FAN is an accepted value for mode.

I'm checking for GL errors immediately before the call, and everything's fine then.

I used MESA_DEBUG=1 (Debugging Tips | mesa3d.org, Environment Variables | mesa3d.org) and found out that glEnable(TEXTURE_2D) was causing the error.

I don't know why it only got triggered on the glDrawArrays (maybe weird bindings) but when I removed that call it no longer failed with GL_INVALID_ENUM.


Heat Method (Crane et Al) How do we pick u? The heat method is a very interesting paper for distance computation:
https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf
The idea behind the paper is that, heat travels along the surface of an object essentially in a geodesic like fashion. And so the time it takes for heat to travel from a hot spot to any point on a surface is irreconcilably correlated with the geodesic distance.
The paper first considers the general, analytic case and then suggests discretization approaches. What I am very confused about is the mention of the heat flow function $u$ across the paper. Consider this equation for example:

That is the discrete laplacian operator applied to $u$ or $\Delta u$. There are multiple other sections in the paper that mention $u$. From my reading, $u$ seems to be a suitable function that approximates heat flow on the surface of a manifold?
I don't really see an equation of the form $u = \text{expression}$ nor do I see descriptions of its properties nor suggestions for a good $u$ function. What is $u$? Where did $u$ come from? Where did $u$ go? Where did $u$ come from? cotan, i, o?

From my reading, u seems to be a suitable function that approximates heat flow on the surface of a manifold?

$u$ is the function that describes how your quantity behaves/evolves in a certain field. In the paper, the quantity is the temperature or heat flux, I guess. However, most of the time there is no analytical solution/formula for $u$. This is where methods like Finite Elements (FEM) come into play. By discretizing your field, you can piecewise approximate your function $u$.
In your case, you would use your mesh, which is already a discretization of your surface. Your elements are the triangles and you need to define how the nodal quantities are interpolated inside each triangle. --- Here, linear interpolation is probably the way to go. Otherwise, you need to remesh your geometry or introduce additional nodes for higher-order approximations.
Then you have to assign to each Node/Vertex an initial value $u_0$ as written in the answer of gilgamec. Afterwards, you build and solve your finite element system and get the nodal distribution of $u$ that actually solves your equation or system of equations. The finer your mesh gets, the better the solution. Higher-order interpolations will also help with accuracy.
So $u$ or its nodal values are what you are actually looking for as lightxbulb said in his comment. It's your unknown quantity.
If this doesn't help, you might want to read some literature about the finite element method. Can't tell how helpful the following links are, but a short glimpse looked promising. You will see, that they use $u$ all over the place. So I hope one of them will help you:

A gentle introduction to the Finite Element Method
PE281 Finite Element Method Course Notes
Introduction to the finite element method
finite element analysis by hand

I also had a link to a good online tutorial similar to the last link I provided that helped me a lot in understanding the fundamentals. If I find the link, I ll add it to my answer.

Found the link I was referring to. Unfortunately, it is in german:

FEM Handrechnung


Ray tracing - partial derivatives for texture lookup I'm doing some ray tracing on GPU using a fragment shader...

How can I calculate texture coordinates partial derivatives with respect to screen coordinates so I could perform filtered texture lookup with textureGrad GLSL function?

Do I need to use ray differentials?

If yes, then how?

Example explaining derivatives calculation for ray-plane intersection (ray described using origin and direction normal vector, plane using one point laying on a plane and normal vector) would be nice, although pointers for general case would also be appreciated...

Yes, ray differentials are the way to go. The Paper by Igehy introduces them for the use case of filtered texture lookups. When generating the primary rays, you initialise the differentials to reflect the pixel footprint. As the ray progresses through the scene, you update the differentials at every bounce. When it comes to a texture lookup, you need to project the differentials to your s,t texture space (aka UV), typically by going to surface parameter space as an intermediate.

The case that you mention, the calculation of derivatives for a ray surface intersection, is implemented in pbrt:
Here the surface is described by a point p, normal n and two tangent vectors dPdu and dPdv. The resulting dudx, dudy, dvdx and dvdy are the differentials of the u, v parameters of the surface with respect to screen space x and y. Conversion from surface parameters to texture space happens here.


Why do Vertex Buffer Objects improve performance? From my basic understanding, a Vertex Buffer Object works something like this (pseudo code):

Normally, if one wanted to say, draw a square, one could issue line drawing commands.

line (0, 0) -> (1, 0)
line (1, 0) -> (1, 1)
line (1, 1) -> (0, 1)
line (0, 1) -> (0, 0)

Using a VBO, if I understand correctly, would load the vertices into a VBO.

define VBO
load (0,0) -> VBO
load (1,0) -> VBO
load (1,1) -> VBO
load (0,1) -> VBO
load (0,0) -> VBO

Then you can issue one drawing command.

draw VBO vertices

While I understand how VBOs work, I don't know why they improve performance.

How do they improve performance?

In general, when you render an object in an immediate mode—issuing line drawing commands for instance—you build up a series of commands that you submit to the graphics card to draw. If you're drawing a lot of data, or drawing very frequently, you can waste a lot of time sending this data over and over again.

A vertex buffer allows you to produce a single object that you submit to the graphics card once. If you don't need to change your geometry, you can leave it on the graphics card and simply send the graphics card a request to draw that object. Since it avoids the copy every time you draw, there's much less overhead for each draw.

Note that using a vertex buffer object doesn't always provide a very significant speedup. If you're only drawing the object once per frame, and you're replacing the geometry in between each frame, then you don't get the benefits of avoiding the copy each frame.

Most of my experience comes from writing programs using graphics APIs like OpenGL, so someone who's messed with the backend of a graphics driver can probably provide a more detailed answer, but I hope this makes things a bit clearer.


How to build a 3d model from 2d pictures I have a series of MRI images. I want to build a 3D model out of it, which not only presents the surface, but also contains the inside structures. What kind of photogrammetry based method can realize that?

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.


Perlin Noise with Smooth function vs Lerp I tried implementing Perlin Noise using the Wikipedia as my main resource. From what I can tell my implementation of the algorithm is spot on but for some reason I'm getting a lot of values equating to 1 or to 0.

This is my Perlin function:

GLfloat perlin(GLfloat x, GLfloat y)
{
    // Turn param into vector
    glm::vec2 xy = glm::vec2(x, y);

    // Grid Cell Coordinates
    glm::vec2 bottomLeft = glm::vec2(std::floor(x), std::floor(y));
    glm::vec2 topRight = glm::vec2(bottomLeft.x + 1, bottomLeft.y + 1);

    GLfloat sx = x - bottomLeft.x;
    GLfloat sy = y - bottomLeft.y;

    GLfloat bottomLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)bottomLeft.y], xy - bottomLeft);
    GLfloat bottomRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)bottomLeft.y], xy - glm::vec2(topRight.x, bottomLeft.y));

    GLfloat smooth1 = glm::smoothstep(bottomLeftDot, bottomRightDot, sx);

    GLfloat topLeftDot = glm::dot(gradients[(GLint)bottomLeft.x][(GLint)topRight.y], xy - glm::vec2(bottomLeft.x, topRight.y));
    GLfloat topRightDot = glm::dot(gradients[(GLint)topRight.x][(GLint)topRight.y], xy - topRight);

    GLfloat smooth2 = glm::smoothstep(topLeftDot, topRightDot, sx);

    GLfloat value = glm::smoothstep(smooth1, smooth2, sy);
    return value;
}

As you can see, I am using the generated values as a height map. In the image above you can see that there's a straight wall and I'm wondering if maybe I'm not interpolating correctly. Can someone point out my mistake?

I'm generating a 100 by 100 grid and my input values are from 0.00 to 0.99 on each axis.

Another question I have is Wikipedia says to use a smoothstep function but I'm not sure for what values?

Update:
I changed the smoothstep and function to the lerp function and now everything seems to be working well but can someone please explain why the outcome is so drastically different.

New outcome below:

It looks like the way you're using smoothstep isn't quite right.

With lerp, the first two parameters are the endpoints of the output range, and the third is a 0–1 value specifying how far to interpolate. It looks like you're trying to use smoothstep the same way, but it doesn't work like that: the first two parameters to smoothstep are endpoints of the input range, and the third is a value in the input range; the output of smoothstep is always in 0–1. It's almost the inverse of lerp in that regard. (See also the GLM docs for smoothstep).

To use smoothstep here, you'd want to do something like this:

glm::lerp(bottomLeftDot, bottomRightDot, glm::smoothstep(0, 1, sx));

This applies smoothstep to the sx value (which is between 0 and 1). The result, which is another 0–1 value, is then used to lerp between the two "dot" values.


Dealing with GL reflection I'm planning the port of our DX based renderer to OpenGL. The target will be Desktop OpenGL 4.x. For DX we use shader reflection but as far as I know OpenGL just has glGetProgramInterfaceiv , glGetUniform and frieds. Theres also SPIR-V (I have never worked with it).

My main concerns right now are:

Using gl*: it will be done at runtime, so this will be potentially slow as there are a lot of shaders to load (+ the interface is ugly as fuck). EDIT: I guess this could be done on a prebuild step too (?).
Use SPIR-V: means that we need to add another build step and I don't see much doc around.

I would like to hear advice from people with experience with this.
Thanks a lot!

opengl has several methods that together let you reflect the shader IO.

However it is much simpler if the shader IO is uniform across all your shaders. IOW have a set of default bindings/locations for everything. Then you only need some meta data for each shader where you deviate from those defaults for some reason.

You then only need to query that the binding exists to see whether you need to provide the data. This has the added bonus that if an input gets optimized out you'll not waste time giving data it doesn't need.


Uniform line thickness in plot I have written a very minimal plotting code which take a function $f$ and a domain $[a,b]$ and plots its graph. (It's here, if relevant.)

Now, I query $f$ at the sides of each pixel, and then every vertical pixel in the line gets marked. But this makes an incredibly thin graph unless the pixel density is low. So I want to support variable line thickness.

When the function is constant, this is easy: Just add the requisite number of pixels above and below the correct pixel. However, as $f'(x) \to \infty$, that gets weird. You still mark above and below the correct pixel, but then the graph appears thin. Here's an example, which I've made comically thick for emphasis:

The function $\sin(x)$ is pretty much uniformly thick, but $1/x$ gets really thin as $x\to 0$, and so does $\sin(1/x)$.

What can I do to get these graphs uniformly thick?

If I assume I can use automatic differentiation on $f$, does the problem have a more interesting solution?

Note: I tried setting the line thickness at point $x$ to
$$
t(x) = t_{\mathrm{user}}\max(1, |f'(x)|)
$$
where $ t_{\mathrm{user}}$ is the user requested thickness.
But of course $|f'|$ can diverge, so this did horrible things to the graph. So I did:
$$
t(x) = t_{\mathrm{user}}\min(\max(1, |f'(x)|), 8)
$$
which also looked terrible, though admittedly less terrible than before. But it's just too arbitrary, so asking the hive-mind it is.

Edit: I'm now thinking that the width should be marked along the normal to the tangent, i.e. the line
$$
y - f(x_i) = -\frac{1}{f'(x_i)} (x-x_i),
$$
not along a vertical. So automatic differentiation is required?

Edit 2: You can get the derivative in pixel space via finite differences; that's just fine, and I image cheaper. Then it's Bresenham's line algorithm + some alpha decay with distance from the curve?

You should separate your line drawing logic from your calculation logic.
In general you should try to have a generic line drawing function that would accept any number of points and draw a line from one point to the next.
The simplest implementation for this would be to have dense points and draw a circle at each point.

If you however absolutely have to calculate the color of a pixel as a function of the X coordinate you'll have to calculate the value multiple times.
Lets say you want thickness of 3 pixels, you will have to calculate this for [X-1, X, X+1] and then check if the current pixel is close to any of the values.
A big downside to this is that you have many duplicate calculations.


What is a common approach to smooth structures in textures? I have a screen-aligned texture resulting from multiple rendering passes. It looks  about this:

I want the edges to appear smoother than they do now (but still keep their characteristic shape). When zooming in, the blocky appearance becomes very obvious. Is there a common approach in computer graphics (or in OpenGL in particular) to resolve this? Since the texture results from the application of the jump flooding algorithm the what-ever approach has to be performed in a post-processing step. I'm so far just interested in the approach(es) itself, not in the implementation.

I don't have enough rep to add a comment so...

You could use a post process based anti-aliasing technique like FXAA or SMAA. Also, if performance is not a priority, you could go for SSAA. Another option could be to write to a multi sampled texture (I'm not 100% sure if that is possible in your case).


rotate objects like a trackball I know how to rotate objects around the center and there are rotation matrices for that as well, but, how do we rotate the object like a trackball, below is the example:

firstly I rotate around the y axis, and then the x axis, then I rotate it like a trackball, how is the third rotation achieved?

I don't know the specifics of what looks to be blender. But I would grab the view matrix of the camera. The rows of which should be orthonormal and give you forward, up, and right. Or columns depending on row or col major (technically its the inverse of the view, but that's just the transpose). Then just do some axes angle rotations around that. Something like this:
Vec3 dx = scale * (currPosX - prevPosX)
Vec3 dy = scale * (currPosY - prevPosY)
Matrix4x4 m1 = axesAngleRot(dx, camera up)
Matrix4x4 m2 = axesAngleRot(dy, camera right)

Matrix4x4 deltaRot = m1 * m2

Where scale is defined by you, and dx and dy give the delta coords of the mouse.
Then apply that to the object. You may have to tack on an extra transform to move back to origin (however you have that transform defined) before doing rotations. The cube you showed is at origin though.
Matrix4x4 finalTransform = inverseFinalTransform * deltaRot * finalTransform


ScratchAPixel : Understanding how to use Perlin's permutations hash table Consider this course : https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/procedural-patterns-noise-part-1/creating-simple-2D-noise . In sub-part Introducing the Concept of Permutation (use CTRL||CMD + F), the author explains Ken Perlin uses the array containing noise values to be interpolated (denoted A) in conjunction with another array, which is the "permutation hash table" (denoted B).

The idea is : from any input (a point), we get its unique noise value in A, using B. A has always 256 cases (whatever the input point's dimension is) : it allows to gain in RAM consumption. B has 512 cases : the 255 first randomly contain numbers from {0...255}, idem for the last half part of B.

How to use the permutation table, according to ScratchAPixel ?

There are 2 things I didn't understand.

First, (1/2) I didn't understand how the hash table is actually used. The workflow I think I understood is the following :

For an input (coordinate), we find the both nearest pre-defined coordinates (i.e. : those present as indices in A). It's a multiple of 255.
The lower one is used to lookup in B
We get a number between [0;255] that we use to lookup in A
We get a number between [0;1] : the noise.

But where is the interpolation between the both pre-defined coordinates' noise values ?

In which way my understanding is wrong ? I believe you should really read this sub-part (Introducing the Concept of Permutation (use CTRL||CMD + F), https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/procedural-patterns-noise-part-1/creating-simple-2D-noise), it's very short and maybe your answer would fit my question more than if you were giving me explanations that possibly would be out of the range of those provided by ScratchAPixel. Thus, I would understand your answer better.

By the way, (2/2) I didn't understand this paragraph neither :

  You may wonder why the permutation array is twice the size of the function period (512 in size instead of 256). If we deal with a 2D noise, we will first do a lookup in the permutation table using the integer value for the x coordinate of our input point (as described). This will return an integer value in the range [0:255]. We will add the result of this lookup to the integer value for the input point y coordinate and use the sum of these two numbers as an index of the permutation table again. Since the result of the first permutation lookup is in the range [0:255] and that the integer value for the point's y coordinate is also in the range [0:255], it means that the range of possible index value for the permutation table is [0:511]. Hence the size of the permutation array (512).

I'm getting confused by all the different but likely terms ("integer value", "coordinate", ...).

First, (1/2) I didn't understand how the hash table is actually used. The workflow I think I understood is the following :

  For an input (coordinate), we find the both nearest pre-defined coordinates (i.e. : those present as indices in A). It's a multiple of
  255.
  The lower one is used to lookup in B
  We get a number between [0;255] that we use to lookup in A
  We get a number between [0;1] : the noise.

  But where is the interpolation between the both pre-defined
  coordinates' noise values ?

There are 4 of most of what you wrote here, then the interpolation. For example, if your 2D input is (2.7, 6.4):

You would truncate that to (2,6).
Then perform the permutation and noise lookup steps for (2,6), (3,6), (2,7), (3,7).
And finally perform a 2D interpolation (lerp) of the 4 lookups with the remainder of your input: (0.7, 0.4).

As for the second part of your question, the table is just a creative way to get a "(int, int) -> int" hashing function to go from input coordinates to an index to pick a value in the random data table. You could use any generic hash function instead. In fact, the method used is fairly obsolete for CPUs as it does not lend itself to SIMD implementation and has horrible memory dependencies. It might still have value for GPUs as they have different behavior. But it will have a visible period of 256 which can cause problems in images. So it is really a poor hash function but for the CPUs back then, it was fast and used little memory which is likely why it was picked.


What is a good color similarity metric? I have some colors in RGB in [0,1] and want to find a way to rate their similarity, as perceived by a human.

I have two ideas in mind, but I am sure there are other options as well, but am unsure which is best, or if perhaps there is no best, but only trade offs.

My first idea is to treat the RGB colors as XYZ points and calculate their distance.

Another idea I have is to treat the RGB values as a histogram and use dot product to get a similarity value between them, where a larger value is better.

I know however, that not all of the color channels have the same perceived brightness so maybe I ought to weight the color channels differently for both cases?

I'm also thinking I perhaps would need to do sRGB correction on the color values (such as, sqrt each color channel).

I also know other color spaces exist, so maybe one of those would be better at giving a similarity value.

Another challenge to this may be that different displays will display the same color values differently.  Not sure if that's relevant in this case.

Anyone able to provide some help/direction?

If complex metric is acceptable I would suggest to look at perceptual based approach described here. The metric is designed to pick perceptual difference of two images. There are two main tests for that : luminance based and color based. First one allows to answer the question how important luminance change is by estimating a non uniform threshold factor based on sensitivity to contrast changes depending on spatial frequencies of the image. The second one is based on euclidean distance in CIE LAB color space, but slightly modified to make color difference less important when luminance is in mesopic and scotopic ranges. A list of papers related to that metric can be found here.


What is a vertex normal used for? I'm new to the graphics area, and when it comes to the light part, the concept of vertex normals confuses me a lot.

First, I cannot imagine how a vertex could have a normal, and second, when calculating the reflection lights, shouldn't I use the normal of a face?

So, can someone help me understand what a vertex normal is, what it is used for, and how it compares to a face normal?

First, I cannot imagine how could a vertex have a normal,...

Welcome to the exciting field of computer graphics. The first thing that might lead to your confusion is to think about a vertex too much as a point in space in a geometrical way. ---> A 3d point can't have normal since it does not have a face.
But the way you should think about it is more like a checkpoint that contains all information of an arbitrary 3d curve at a certain position.

  ... and second, when calculate the reflection lights, shouldn't I use the normal of a face?

What happens if you want to render a perfect sphere that can only be represented by a limited set of triangles? It will look like the one in the middle in this question. The flat surfaces are clearly visible, but that is not what you want. You can improve this by drastically increasing the triangle count, but that comes with a huge performance impact and memory footprint.

The solution here is using vertex normals. To understand, why this is a solution, you need to know a little bit about how the render pipeline works. The most important parts for your understanding are vertex processing, rasterization, and the pixel/fragment shader.

Vertex processing is the first programable (in modern APIs) step in the pipeline and is mostly used to reposition your vertices so that your 3d world is displayed correctly on a 2d display. Therefore you apply some mathematical corrections (perspective for example) to your vertex positions. You can do a lot more, but that is not important here. What is important is, that the vertex processor does not know to which triangle a vertex belongs. He sees it in total isolation. Therefore, he can not calculate any face normals, so you have to provide it in some way, for example by adding it as vertex attribute.

After some optional pipeline steps, you get to the rasterizer. Its job is to turn your triangles into actual pixels on your screen. The information he gets are three vertices that form a triangle. Now here is, where the magic happens. For each pixel, he interpolates the properties of the three vertices and passes them to the final step, the pixel shader (also programable in modern APIs). So if your vertices had normals, you will have an interpolated normal for each pixel of your triangle. This enables you to render perfectly smooth surfaces (or at least fake them) since you can perform the lighting calculation for each pixel with individual normals in the pixel shader.

This is why you need vertex normals. The vertices are checkpoints that hold information about your surfaces at specific points. You connect these points to triangles. The information in between is interpolated by the rasterizer. So you essentially describe a whole triangle-shaped field of normals with its three edge values.

However, even if you want to render flat surfaces, you might still need vertex normals. As I said before, the vertex processor does not know anything about triangles, so you can not calculate any surface normals there. So you have to pass them in somehow. There are other ways, but attaching the normals to the vertices is usually the best and easiest solution.

Additional note: You do not necessarily need to perform the lighting calculation in the pixel shader. You can also do this in the vertex stage. So you need vertex normals again ;). This is called Gouraud Shading and gives you a performance boost since you do not need to perform the light calculations per pixel. However, the visual quality of curved surfaces suffers from that. For flat surfaces, you should not see any differences.


How to change sampler/pipeline states at runtime in Vulkan? I have problems implementing a Vulkan renderer alongside my OpenGL one.

In OpenGL one can change sampler parameters easily at runtime (like anisotropy settings through glTexParameter) or blend/depth states.

I wonder if this is also possible in Vulkan.

I usually create lets say a sampler object with all information needed and throw the creation info away after construction.

I did not find any information on this on the net.

So, is there any way to change those settings at runtime or do I have to create a complete new sampler object down the road?

The same question applies to depth/blend states in pipeline objects.

I think the second case would not actually be particularly fast performance wise.

You're sort of asking two different questions here but that's okay.

Changing Sampler states is pretty straightforward. When you create a descriptor set, you write your VkSampler object that you've created into a descriptor set. If you want to update a sampler in a descriptor set, create a VkSampler with the sampler settings you want and then call vkUpdateDescriptorSets with the new VkSampler writes that you want to perform. When you bind that descriptor set again it should contain your new sampler. This is a bit roundabout but you have to architect for it. You probably don't want to update samplers every frame so only do this when you need to. This is not an extremely expensive operation if you do it right. Vulkan expects descriptor set data to change; so long as that data lines up with the descriptor set layout it's going to go pretty fast.

Changing Pipelines is EXTREMELY expensive. Vulkan doesn't like to perform context switches like this so you can't just update an existing pipeline that's in use. You do have to completely rebuild your rendering path to use the new PSO. If you want to change between a few different Pipelines it's best to build them all upfront, build all the different command buffers that use the different pipelines and then execute the command buffer that has the pipeline you want to run. If you want to change your pipeline, execute the other command buffer that uses the pipeline you want.

Vulkan wants you to create, cache and reuse data as much as possible. That's how you get a lot of savings. You don't need to update descriptor sets, command buffers etc. unless they actually change.


Unwinding an image on a spiral to make it long and flat Here's an odd intellectual puzzle.  Something I was daydreaming about on a train - but the maths are somewhat beyond me.  How would someone go about un-winding a spiral to produce a long flat image?  Like a rope on a spool, I'd want to uncoil the rope so that it lay long and flat.  The function would have to take in the image data (imageData) and the imageHeight (the height of the output strip - and hence also the thickness of the 'rope' on the spool).  Assumptions that could be made are that the input image is square, containing a circle whose top and bottom touch the top and bottom of the square - and left and right similarly.  The hub of circle would be in the absolute centre of the image.

(char*) unwindImage (char* imageData, int imageHeight)

Has anyone else puzzled over this?  And, if so, what solution did your come up with?

A quickly formulated method, read first one that popped in my brain (not best), could be. Find the closest points on a parametric spiral for each sample (read A Pixel Is Not A Little Square3). Then place the samples on a line by placing the pints in one axis by how far they are from your spiral line and the other by what the closest point is.

You can then use something like poisson disk sampling to reconstruct the image (maybe the didsk should be longer ovals the further away they are form the center line and less long as you progress further into the spiral).

Now that I think of the problem a bit more. A simpler approach could be to map the image on mesh, using UV mapping, then unwrap the mesh. A triangular mesh might exhibit some artifacts so using a B-spline interpolation could be better. Several image mesh algorithms exist and you even have these in Photoshop.

Image 2: A proof of concept of unwound spiral with the mesh method. Note i scaled the unwound spirals length to make it fit the site requirements better.

From initial test in my 3D app of choice seems that a dense enough triangular mesh works fine.


How does Texture Cache work in Tile Based Rendering GPU How does cache work with tile based rendering?

Are there any tips on how to improve cache hit ratio for it? (for instance, if tiles are processed horizontally and I have vertical segments of triangles with the same texture, does it work worse for cache than if I had triangles layout out horizontally?)

Whether it's a tile based GPU or not doesn't really affect the texture cache architecture. The memory layout of texture will look like some flavor of Morton order or Hilbert curve in all GPUs.

As a result, it's more efficient to render triangles that are close to equilateral triangles because GPU memory system fetches cache lines of texels.

So obviously on tile borders, it may happen that you have to fetch texels twice. This has a small cost as tile borders are only "few" pixels.

Arguably desktop GPUs behave identically to tile based GPUs as experiments such as the following demonstrate:
http://www.g-truc.net/post-0597.html

The size of the tiles differ but both architecture actually process fragments into a hierarchy of tiles of different sizes.

When coding for tile based GPUs my recommendation is to always have in mind:

Don't switch framebuffer objects unless you really need to.
When binding a new framebuffer object, if you don't need to save the content of the current framebuffer, discard it. If don't want to load content of the new framebuffer, then you should clear the framebuffer.


Is Russian Roulette really the answer? I have seen that in some implementations of Path Tracing, an approach called Russian Roulette is used to cull some of the paths and share their contribution among the other paths.

I understand that rather than following a path until it drops below a certain threshold value of contribution, and then abandoning it, a different threshold is used and paths whose contribution is below that threshold are only terminated with some small probability. The other paths have their contribution increased by an amount corresponding to sharing the lost energy from the terminated path. It isn't clear to me whether this is to correct a bias introduced by the technique, or whether the whole technique is itself necessary to avoid bias.

Does Russian Roulette give an unbiased result?
Is Russian Roulette necessary for an unbiased result?

That is, would using a tiny threshold and just terminating a path the moment it drops below that threshold give a more biased or less biased result?

Given an arbitrarily large number of samples, would both approaches converge on an unbiased resulting image?

I'm looking to understand the underlying reason for using the Russian Roulette approach. Is there a significant difference in speed or quality?

I understand that the energy is redistributed among other rays in order to preserve total energy. However, could this redistribution not still be done if the ray were terminated on dropping below a fixed threshold, rather than having a randomly determined life span after reaching that threshold?

Conversely, if the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?

In order to understand Russian Roulette, let's look at a very basic backward path tracer:

void RenderPixel(uint x, uint y, UniformSampler *sampler) {
    Ray ray = m_scene->Camera.CalculateRayFromPixel(x, y, sampler);

    float3 color(0.0f);
    float3 throughput(1.0f);

    // Bounce the ray around the scene
    for (uint bounces = 0; bounces < 10; ++bounces) {
        m_scene->Intersect(ray);

        // The ray missed. Return the background color
        if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
            color += throughput * float3(0.846f, 0.933f, 0.949f);
            break;
        }

        // We hit an object

        // Fetch the material
        Material *material = m_scene->GetMaterial(ray.geomID);
        // The object might be emissive. If so, it will have a corresponding light
        // Otherwise, GetLight will return nullptr
        Light *light = m_scene->GetLight(ray.geomID);

        // If we hit a light, add the emmisive light
        if (light != nullptr) {
            color += throughput * light->Le();
        }

        float3 normal = normalize(ray.Ng);
        float3 wo = normalize(-ray.dir);
        float3 surfacePos = ray.org + ray.dir * ray.tfar;

        // Get the new ray direction
        // Choose the direction based on the material
        float3 wi = material->Sample(wo, normal, sampler);
        float pdf = material->Pdf(wi, normal);

        // Accumulate the brdf attenuation
        throughput = throughput * material->Eval(wi, wo, normal) / pdf;

        // Shoot a new ray

        // Set the origin at the intersection point
        ray.org = surfacePos;

        // Reset the other ray properties
        ray.dir = wi;
        ray.tnear = 0.001f;
        ray.tfar = embree::inf;
        ray.geomID = RTC_INVALID_GEOMETRY_ID;
        ray.primID = RTC_INVALID_GEOMETRY_ID;
        ray.instID = RTC_INVALID_GEOMETRY_ID;
        ray.mask = 0xFFFFFFFF;
        ray.time = 0.0f;
    }

    m_scene->Camera.FrameBuffer.SplatPixel(x, y, color);
}

IE. we bounce around the scene, accumulating color and light attenuation as we go. In order to be completely mathematically unbiased, bounces should go to infinity. But this is unrealistic, and as you noted, not visually necessary; for most scenes, after a certain number of bounces, say 10, the amount of contribution to the final color is very very minimal.

So in order to save computing resources, many path tracers have a hard limit to the number of bounces. This adds bias.

That said, it's hard to choose what that hard limit should be. Some scenes look great after 2 bounces; others (say with transmission or SSS) may take up to 10 or 20.

If we choose too low, the image will be visibly biased. But if we choose too high, we're wasting computation energy and time.

One way to solve this, as you noted, is to terminate the path after we reach some threshold of attenuation. This also adds bias.

Clamping after a threshold, will work, but again, how do we choose the threshold? If we choose too large, the image will be visibly biased, too small, and we're wasting resources.

Russian Roulette attempts to solve these problems in an unbiased way. First, here is the code:

void RenderPixel(uint x, uint y, UniformSampler *sampler) {
    Ray ray = m_scene->Camera.CalculateRayFromPixel(x, y, sampler);

    float3 color(0.0f);
    float3 throughput(1.0f);

    // Bounce the ray around the scene
    for (uint bounces = 0; bounces < 10; ++bounces) {
        m_scene->Intersect(ray);

        // The ray missed. Return the background color
        if (ray.geomID == RTC_INVALID_GEOMETRY_ID) {
            color += throughput * float3(0.846f, 0.933f, 0.949f);
            break;
        }

        // We hit an object

        // Fetch the material
        Material *material = m_scene->GetMaterial(ray.geomID);
        // The object might be emissive. If so, it will have a corresponding light
        // Otherwise, GetLight will return nullptr
        Light *light = m_scene->GetLight(ray.geomID);

        // If we hit a light, add the emmisive light
        if (light != nullptr) {
            color += throughput * light->Le();
        }

        float3 normal = normalize(ray.Ng);
        float3 wo = normalize(-ray.dir);
        float3 surfacePos = ray.org + ray.dir * ray.tfar;

        // Get the new ray direction
        // Choose the direction based on the material
        float3 wi = material->Sample(wo, normal, sampler);
        float pdf = material->Pdf(wi, normal);

        // Accumulate the brdf attenuation
        throughput = throughput * material->Eval(wi, wo, normal) / pdf;

        // Russian Roulette
        // Randomly terminate a path with a probability inversely equal to the throughput
        float p = std::max(throughput.x, std::max(throughput.y, throughput.z));
        if (sampler->NextFloat() > p) {
            break;
        }

        // Add the energy we 'lose' by randomly terminating paths
        throughput *= 1 / p;

        // Shoot a new ray

        // Set the origin at the intersection point
        ray.org = surfacePos;

        // Reset the other ray properties
        ray.dir = wi;
        ray.tnear = 0.001f;
        ray.tfar = embree::inf;
        ray.geomID = RTC_INVALID_GEOMETRY_ID;
        ray.primID = RTC_INVALID_GEOMETRY_ID;
        ray.instID = RTC_INVALID_GEOMETRY_ID;
        ray.mask = 0xFFFFFFFF;
        ray.time = 0.0f;
    }

    m_scene->Camera.FrameBuffer.SplatPixel(x, y, color);
}

Russian Roulette randomly terminates a path with a probability inversely equal to the throughput. So paths with low throughput that won't contribute much to the scene are more likely to be terminated.

If we stop there, we're still biased. We 'lose' the energy of the path we randomly terminate. To make it unbiased, we boost the energy of the non-terminated paths by their probability to be terminated. This, along with being random, makes Russian Roulette unbiased.

To answer your last questions:

Does Russian Roulette give an unbiased result?

Yes

Is Russian Roulette necessary for an unbiased result?

Depends on what you mean by unbiased. If you mean mathematically, then yes. However, if you mean visually, then no. You just have to choose you max path depth and cutoff threshold very very carefully. This can be very tedious since it can change from scene to scene.

Can you use a fixed probability (cut-off), and then redistribute the 'lost' energy. Is this unbiased?

If you use a fixed probability, you are adding bias. By redistributing the 'lost' energy, you reduce the bias, but it is still mathematically biased. To be completely unbiased, it must be random.

If the energy that would be lost by terminating a ray without redistributing its energy is eventually lost anyway (as the rays to which it is redistributed are also eventually terminated), how does this improve the situation?

Russian Roulette only stops the bouncing. It doesn't remove the sample completely. Also, the 'lost' energy is accounted for in the bounces up to the termination. So the only way for the the energy to be 'eventually lost anyway' would be to have a completely black room.

In the end, Russian Roulette is a very simple algorithm that uses a very small amount of extra computational resources. In exchange, it can save a large amount of computational resources. Therefore, I can't really see a reason not to use it.


How to use GetViewProjMatrix().TransformVector(LineDirection) in UE4? I try to project a 3D vector (a direction, not a position) in screen space, but it does not return satisfying results:

 FVector LineDirectionOnScreen =
   EdMode->ViewMatrices.GetViewProjMatrix().TransformVector(LineDirection);
 FVector2D LineDirectionOnScreen2D(
   LineDirectionOnScreen.X * 0.5f * (float)EdMode->ViewRect.Width(),
   LineDirectionOnScreen.Y * 0.5f * (float)EdMode->ViewRect.Height());

When LineDirection is (0,0,1) it always returns a something like (0,Y) (Y can be anything), no matter how the camera is rotated.

What is wrong with my code?

I don't think you can simply use TransformVector when the matrix you're transforming by involves a projection matrix. To fully project to screen space, you have to divide by W, which TransformVector doesn't do (it simply multiplies by the matrix without translation).

Also, because of the divide by W, transforming vectors (as opposed to points) by a projection matrix is probably not what you actually want. If what you want is the screen-space vector between two points, you should transform and divide-by-W each point, then subtract them to get a screen-space vector. Otherwise the vector will likely be inaccurate.


Render fragments with uvs outside (0,1) range as transparent I'm rendering an image onto a mesh. And I need to render fragments with uv coordinates that fall outside (0,1) range with full transparency. In the code below I'm specifying a border color with zero alpha. However I'm getting fully opaque border. That is when texture itself does not have alpha channel. Is it possible to use a texture without alpha channel but still render fragments outside of the range as transparent?
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float border[] = {1, 1, 1, 0};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);

Here is the fragment shader code:
out vec4 color;
in vec2 uv;
uniform sampler2D tex;

void main() {
    color = texture(tex, uv);
}

I enabled alpha blending like this:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Assuming that alpha works properly in the rest of the code it can be solved on shader level:
out vec4 color;
in vec2 uv;
uniform sampler2D tex;

void main() {
    color = texture(tex, uv);
    color.a = 0.0;
    if (all(greaterThan(uv, vec2(0.0))) && all(lessThan(uv, vec2(1.0)))) {
        color.a = 1.0;
    }
}


What is the name of these software on 2 screen? Look at the photo, modelling for new products.

Regards

Judging by the interface that would be blender:

https://www.blender.org/

Please note that here is a bender-specific stackexchange site as well:

https://blender.stackexchange.com/


How to open and render in a second window with OpenGL / JOGL with NEWT I have a working renderer implemented with Java in JOGL with NEWT. Now I want to implement a Material Editor which should run in a second window. However I can't get a second window up and render in it.

My main window is implemented as follows:
I have a class Backend which implements the GLEventListener. The two important methods are:

public static void initOpenGl()
{
    GLProfile.initSingleton();
}

which is called before anything else happens on start up and, to create the window itself

public void createWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle
        , Program program)
{
    GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));
    caps.setBackgroundOpaque(false);
    glWindow = GLWindow.create(caps);

    glWindow.setTitle(windowTitle);
    glWindow.setSize(windowWidth, windowHeight);
    glWindow.setUndecorated(false);
    glWindow.setPointerVisible(true);
    glWindow.setVisible(true);

    m_program = program;
    glWindow.addGLEventListener(this);
    glWindow.addKeyListener(m_program);
    glWindow.addMouseListener(m_program);
    m_program.setBackend(this);

    Animator animator = new Animator();
    animator.add(glWindow);
    animator.start();
}

TRY 1

In my first attempt, I created a subwindow thus:

public void createSubWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle
        , Program program)
{

    Display display = NewtFactory.createDisplay("mystring");
    display.addReference();

    Screen screen = NewtFactory.createScreen(display, 0);
    screen.addReference();

    GLProfile profile = GLProfile.get(GLProfile.GL3);
    GLCapabilities caps = new GLCapabilities(profile);
    GLWindow window = GLWindow.create(screen, caps);
    //the following line does not work, context is null
    GLContext context = window.createContext(GLContext.getCurrent());

    window.setSize(windowWidth, windowHeight);
    window.setVisible(true);
    window.setTitle(windowTitle);

    System.out.println(windowTitle + " window is open!");
}

Since the context is null however, an exception is thrown:

  No OpenGL context current on this thread

TRY2

In my second try I created a SubWindow class much like the Backend class, which implements GLEventListener and has the same createWindow method. This throws a different exception:

  com.jogamp.opengl.GLException: Caught ThreadDeath: null on thread main-Display-.windows_nil-1-EDT-1-AWTAnimator#01

Perhaps the question would be better stated as "how to create a second GL Context", I am not exactly sure.

So after letting this lie for quite a while, I just came back to it. Turns out, the error was in my code with a faulty false return value which would lead to a System.exit. I have no idea how I didn't catch this the last time round, but it now works with Try 2. That is:

public class SubWindow implements GLEventListener
{
    GLWindow glWindow;
    Program m_program;

    public void createSubWindow(int windowWidth, int windowHeight, boolean isFullscreen, String windowTitle
            , Program program)
    {
        GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL3));
        caps.setBackgroundOpaque(false);
        glWindow = GLWindow.create(caps);

        glWindow.setTitle(windowTitle);
        glWindow.setSize(windowWidth, windowHeight);
        glWindow.setUndecorated(false);
        glWindow.setPointerVisible(true);
        glWindow.setVisible(true);

        m_program = program;
        glWindow.addGLEventListener(this);
        glWindow.addKeyListener(m_program);
        glWindow.addMouseListener(m_program);

        Animator animator = new Animator();
        animator.add(glWindow);
        animator.start();
    }

Where the Program is one of my own classes handling the logic and the SubWindow class additionally implements the required init, display, etc. methods.


Rotate a Bitmap with Shearing I am rotating a bitmap using the three shear algorithm documented in these articles [1][2].
From about 0-90°, the quality is acceptable, but beyond that it gets progressively more distorted until it's unintelligible.

Can anyone help me locate what is going wrong? Thank you!
This is my shear function:
def shear(angle,x,y):
    '''
    |1  -tan(/2) |  |1        0|  |1  -tan(/2) |
    |0      1     |  |sin()   1|  |0      1     |

    '''
    # shear 1
    tangent=math.tan(angle/2)
    new_x=round(x-y*tangent)
    new_y=y

    #shear 2
    new_y=round(new_x*math.sin(angle)+new_y)      #since there is no change in new_x according to the shear matrix

    #shear 3
    new_x=round(new_x-new_y*tangent)              #since there is no change in new_y according to the shear matrix

    return new_x,new_y

This is the code in the draw function:
cos = math.cos(self.rotation)
sin = math.sin(self.rotation)

# Define the width and height of the destination image
newWidth = round(abs(w*cos)+abs(h*sin))+1
newHeight = round(abs(h*cos)+abs(w*sin))+1

# Find the center of the source image for rotation
origCenterWidth  = round(((w+1)/2)-1)    #with respect to the source image
origCenterHeight = round(((h+1)/2)-1)    #with respect to the source image

# Find the center of the destination image
newCenterWidth  = round(((newWidth+1)/2)-1)  #with respect to the destination image
newCenterHeight = round(((newHeight)/2)-1)  #with respect to the destination image

for i in range(h):
    for j in range(w):
        #co-ordinates of pixel with respect to the center of source image
        x = w-1-j-origCenterWidth
        y = h-1-i-origCenterHeight

        #Applying the Shear Transformation
        new_x,new_y = shear(self.rotation,x,y)

        #with rotation, the center will change so new_x and new_y will be the new center
        new_y = newCenterHeight-new_y
        new_x = newCenterWidth-new_x

        alphaValue = sourceBmp.GetAlphaPixel(alphaChannel, j, i) #gets the source image pixel's alpha
        col = sourceBmp.GetPixelDirect(j, i) #gets the source image pixel's color as a Color Vector
        destBmp.SetAlphaPixel(nBmpAlpha, int(new_x), int(new_y), alphaValue) #sets the destination image pixel's alpha
        destBmp.SetPixel(int(new_x), int(new_y), int(col.x), int(col.y), int(col.z)) #sets the destination image pixel's color

as paulHK said:

One fundamental issue here is you're rotating in destination space rather than source space (e.g. apply the shear on source coordinates and output a rectangle). This way you can guarantee every pixel in the output is drawn once and only once and there are no gaps in between.

and the line that's causing the 180 problem is this line:
tangent=math.tan(angle/2)
If the angle is 180, the tan of 90 will be basically infinity.
This is a graph of 1 / (cos(rotation) ^ 2), one of the shearing calculations the narrator at datagenetics.com uses:

That means his method stalls at certain angles.
In all the code i wrote, I never needed to call tan(x).
Use cos(x) and sin(x) instead, also use as few divisions as possible that could create infinity. Most rendering engines tackle this problem by limiting the angle of the camera to 89 degrees.
To get unaliased rotated images, i suggest a better drawing method, which computer graphics use today:
Use a 3x3 rotation matrix and a translation matrix , and loop over the pixels image that you want to draw on:
cos(angle) -sin(angle) + offset x
sin(angle) cos(angle)  + offset y
0          0           1
to get this matrix, multiply first:
1 0 -[rotation centre x]
0 1 -[rotation centre y]
0 0 1
then:
cos(angle) -sin(angle) 0
sin(angle) cos(angle)  0
0          0           1
and then:
1 0 [rotation centre x]
0 1 [rotation centre y]
0 0 1
and then(if needed to translate):
1 0 [translation x]
0 1 [translation y]
0 0 1
Multiply the position on the target image by the INVERSE of the combined matrix to get the position on the source image.
If the position is in the bounds of the source image,
fill the target pixel with the source pixel at that location.