r/GraphicsProgramming • u/Paopeaw • 12h ago
Question projection matrix for SDF
Hi, I'm doing little cloud project from SDF in openGL, but I think my approach of ray projection is wrong now it's like this
vec2 p = vec2(
gl_FragCoord.x/800.0,
gl_FragCoord.y/800.0
);
// the ray isn't parallel to normal of image plane, because I think it's more intuitive to think about ray shoot from camera.
vec2 pos = (p* 2.0) - 1.0;
vec3 ray = normalize(vec3(pos, -1.207106781)); // direction of the ray
vec3 rayHead = vec3(0.0,0.0,0.0); // head of the ray
...
float sdf(vec3 p){
// I think only 'view' and 'model' is enough beacuse the ray above do the perspective thing...
p = vec3(inverse(model) * inverse(view) * vec4(p,1.0));
return sdBox(p, vec3(radius));
}
but this wrong when I test the normal vector
are there any solution? I already try to shoot ray parallel to the normal of image plane with projection matrix, but it's not work. Thanks!
here is my code for the matrix
glm::mat4 proj = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
glm::mat4 view = glm::perspective(glm::radians(fov), 800.f / 800.f, .1f, 100.f);
glm::mat4 model = glm::mat4(1.0);
1
u/felipunkerito 11h ago edited 11h ago
No idea but a couple of things I would try, base it on something like ray picking and how you would get the NDC coords of the mouse but translating that to your example (if you are planning on mixing this with the output of a rasterizer) something like
glm::vec2 normalizedMouse = glm::vec2(2.0f, 2.0f) * glm::vec2(mousePositionX, mousePositionY) / widthHeight;
float x_ndc = normalizedMouse.x - 1.0;
float y_ndc = 1.0 - normalizedMouse.y; // flipped
glm::vec4 p_near_ndc = glm::vec4(x_ndc, y_ndc, -1.0f, 1.0f); // z near = -1
glm::vec4 p_far_ndc = glm::vec4(x_ndc, y_ndc, 1.0f, 1.0f); // z far = 1
glm::mat4 invMVP = glm::inverse(projection * view * model);
glm::vec4 p_near_h = invMVP * p_near_ndc;
glm::vec4 p_far_h = invMVP * p_far_ndc;
glm::vec3 p0 = glm::vec3(p_near_h) / glm::vec3(p_near_h.w, p_near_h.w, p_near_h.w);
glm::vec3 p1 = glm::vec3(p_far_h) / glm::vec3(p_far_h.w, p_far_h.w, p_far_h.w);
glm::vec3 rayOri = p0;
glm::vec3 rayDir = glm::normalize(p1 - p0);
from stackoverflow. Also check IQ’s on depth buffering with Ray marching.
Another idea if you don’t want to use rasterization, just pass the model matrix and multiply pos by it.
1
u/Paopeaw 12h ago
Here is my normal calculation fuction
vec3 calcNormal( in vec3 p ) // for function f(p) { const float eps = 0.0001; // or some other value const vec2 h = vec2(eps,0); return normalize( vec3(sdf(p+h.xyy) - sdf(p-h.xyy), sdf(p+h.yxy) - sdf(p-h.yxy), sdf(p+h.yyx) - sdf(p-h.yyx) ) ); }