I would like to create perfect mathematical objects in postprocessing so that curved geometries are really continuously curved. here is an example with a very simple curved geometry, a sphere. the relative position is easy but the orientation worries me. I don’t have any vertices, just mathematically described points from the camera’s point of view where the boundary surface of the sphere is. I have to transform these points into the reference system of the world so that I can correctly simulate gloss effects and light shadows. can anyone tell me which matrix i need for this?
export const perfectGeometryVS =`
out vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4( (uv - 0.5)*2.0, 0.0, 1.0 );
}
`;
export const perfectGeometryFS = `
in vec2 vUv;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
uniform vec3 cameraPos;
uniform vec3 spherePos;
uniform float sphereRadius;
uniform vec3 lightPos;
uniform mat4 viewWorldInverse;
uniform mat4 uProjectionInverse;
uniform mat4 uMatrixWorld;
vec3 computeWorldPosition(){
// Convert screen coordinates to normalized device coordinates (NDC)
float normalizedDepth = unpackRGBAToDepth( texture2D( tDepth, vUv) );
vec4 ndc = vec4(
(vUv.x - 0.5) * 2.0,
(vUv.y - 0.5) * 2.0,
(normalizedDepth - 0.5) * 2.0,
1.0);
vec4 clip = uProjectionInverse * ndc;
vec4 view = uMatrixWorld* (clip / clip.w);
vec3 result = view.xyz;
return result;
}
bool RayIntersectsSphere(vec3 rayStart, vec3 rayDir, vec3 sphereCenter, float sphereRadius, out float t0, out float t1) {
vec3 oc = rayStart - sphereCenter;
float a = dot(rayDir, rayDir);
float b = 2.0 * dot(oc, rayDir);
float c = dot(oc, oc) - sphereRadius * sphereRadius;
float d = b * b - 4.0 * a * c;
// Also skip single point of contact
if (d <= 0.0) {
return false;
}
float r0 = (-b - sqrt(d)) / (2.0 * a);
float r1 = (-b + sqrt(d)) / (2.0 * a);
t0 = min(r0, r1);
t1 = max(r0, r1);
return (t1 >= 0.0);
}
vec4 perfectSphere(vec3 rayDir, vec3 rayOrigin, vec3 spherePos, vec3 diffuse, float rSphere) {
float t0, t1;
// Early out if ray doesn't intersect ocean.
if (! RayIntersectsSphere(rayOrigin, rayDir, spherePos, rSphere, t0, t1)) {
return vec4(diffuse, 1.);
}
//here i need a matrixoperation because the spherical geometry is always created from the perspective of the camera
vec3 vPosition = rayOrigin - spherePos + t0 * rayDir; //virtual vertex
vec3 vNormal = normalize(vPosition); //virtual normal
vec4 LightPosition = viewWorldInverse * vec4(lightPos - spherePos, 0.);
float intensity = 1.0;
float shininess = 100.0;
vec3 n = vNormal;
vec3 s = normalize(LightPosition.xyz - vPosition);
vec3 v = normalize(-vPosition);
vec3 r = reflect(s, n);
vec3 color = vec3(250./255., 5./255., 20./255.);
vec3 diff = color * max(dot(s, n), 0.0);
vec3 spec = vec3(1.0) * pow(max(dot(r, v), 0.0), shininess);
return vec4(diff + spec, 1.);
}
void main() {
vec3 diffuse = texture2D(tDiffuse, vUv).rgb;
vec3 posWS = computeWorldPosition();
vec3 cameraDirection = normalize(posWS - cameraPos);
vec3 color = perfectSphere(cameraDirection, cameraPos, spherePos, diffuse, sphereRadius).xyz;
gl_FragColor = vec4(color, 1.);
}
`;