The following GLSL code:
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = fragCoord / iResolution.xy;
vec2 windowSize = iResolution.xy;
float border = 50.0;
vec2 pixelPos = uv * windowSize;
vec2 v = windowSize - pixelPos;
vec2 n = normalize(vec2(1.0, -1.0));
float col = 1.0;
if (dot(v, n) < 0.0) {
col = clamp(windowSize.x - pixelPos.x, 0.0, border) / border;
} else {
col = clamp(windowSize.y - pixelPos.y, 0.0, border) / border;
}
fragColor = vec4(vec3(col), 1.0);
}
Produces the following image:
There is a noticeable lighter line at the corner - where the right and top gradients meet. I don't really understand why this happens. When a point is right at the diagonal the values are supposed to be identical to the values near the diagonal. To illustrate my point, consider the following python code:
import numpy as np
from numpy.linalg import norm
def clamp(x, min_val, max_val):
return np.minimum(np.maximum(x, min_val), max_val)
def normalize(x):
return x / norm(x)
def vec2(x, y):
return np.array([x, y])
windowSize = vec2(200, 100)
border = 50.0
def calculate(pixelPos):
v = windowSize - pixelPos
n = normalize(vec2(1.0, -1.0))
col = 1.0
if np.dot(v, n) < 0.0:
col = clamp(windowSize[0] - pixelPos[0], 0.0, border) / border
else:
col = clamp(windowSize[1] - pixelPos[1], 0.0, border) / border
return col
print(10 / border) # expected value
pixelPos = np.array([190, 90]) # right on the diagonal
print(pixelPos, calculate(pixelPos))
pixelPos = np.array([189, 90]) # slightly above
print(pixelPos, calculate(pixelPos))
pixelPos = np.array([190, 89]) # slightly below
print(pixelPos, calculate(pixelPos))
It outputs:
0.2
[190 90] 0.2
[189 90] 0.2
[190 89] 0.2
As the above code shows, the values at the diagonal are identical to the values to the left and down of it. So if the values are identical, why does OpenGL show this light line at the corner?
As has been pointed out to me, turns out this is a well known optical illusion, and similar questions have been asked here on Stack Overflow:
Here is a small python script that visualizes it more clearly:
import numpy as np
from numpy.linalg import norm
import matplotlib.pyplot as plt
def clamp(x, min_val, max_val):
return np.minimum(np.maximum(x, min_val), max_val)
def normalize(x):
return x / norm(x)
def vec2(x, y):
return np.array([x, y])
windowSize = vec2(200, 100)
border = 50.0
def calculate(pixelPos):
v = windowSize - pixelPos
n = normalize(vec2(1.0, -1.0))
col = 1.0
if np.dot(v, n) < 0.0:
col = clamp(windowSize[0] - pixelPos[0], 0.0, border) / border
else:
col = clamp(windowSize[1] - pixelPos[1], 0.0, border) / border
return col
pixels = [[0.0 for _ in range(windowSize[0])] for _ in range(windowSize[1])]
for i in range(windowSize[1]):
for j in range(windowSize[0]):
x = j
y = windowSize[1] - i
pixels[i][j] = calculate(vec2(x, y))
plt.imshow(pixels)
plt.show()