una resueltos que online matriz matrices inversa ejercicios adjunta 5x5 4x4 2x2 opengl glsl shader direct3d

opengl - resueltos - matriz inversa ejercicios



Calcular clipspace.w de clipspace.xyz y(inv) matriz de proyección (1)

Estoy usando un algoritmo logarítmico de profundidad que da como resultado que algunosFunc (clipspace.z) se escriban en el búfer de profundidad y no se divida la perspectiva implícita .

Estoy haciendo RTT / postprocesamiento, así que más adelante en un sombreador de fragmentos quiero recalcular eyespace.xyz, dado ndc.xy (desde las coordenadas del fragmento) y clipspace.z (desde algunosFuncInv () en el valor almacenado en el buffer de profundidad) .

Tenga en cuenta que no tengo clipspace.w, y mi valor almacenado no es clipspace.z / clipspace.w (como lo sería cuando se usa la profundidad de función fija) - así que algo en la línea de ...

float clip_z = ...; /* [-1 .. +1] */ vec2 ndc = vec2(FragCoord.xy / viewport * 2.0 - 1.0); vec4 clipspace = InvProjMatrix * vec4(ndc, clip_z, 1.0)); clipspace /= clipspace.w;

... no funciona aquí.

Entonces, ¿hay alguna manera de calcular clipspace.w fuera de clipspace.xyz, dada la matriz de proyección o es inversa?


clipspace.xy = FragCoord.xy / viewport * 2.0 - 1.0;

Esto es incorrecto en términos de nomenclatura. "Espacio de clip" es el espacio que emite el sombreador de vértices (o la última etapa de procesamiento de vértices). Entre el espacio del clip y el espacio de la ventana está el espacio normalizado de coordenadas del dispositivo (NDC). El espacio de NDC es el espacio de clip dividido por la coordenada W del espacio de clip:

vec3 ndcspace = clipspace.xyz / clipspace.w;

Entonces, el primer paso es tomar nuestras coordenadas de espacio de ventana y obtener coordenadas de espacio NDC. Lo cual es fácil:

vec3 ndcspace = vec3(FragCoord.xy / viewport * 2.0 - 1.0, depth);

Ahora, voy a suponer que su valor de depth es la profundidad de espacio NDC adecuada. Supongo que obtiene el valor de una textura de profundidad, y luego usé el rango de profundidad cerca / lejos de los valores con los que se representó para asignarlo a un rango [-1, 1]. Si no lo hiciste, deberías.

Entonces, ahora que tenemos ndcspace , ¿cómo calculamos el clipspace ? Bueno, eso es obvio:

vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);

Obvio y ... no es útil, ya que no tenemos clipspace.w . Entonces, ¿cómo lo conseguimos?

Para obtener esto, tenemos que ver cómo se calculó el clipspace la primera vez:

vec4 clipspace = Proj * cameraspace;

Esto significa que clipspace.w se calcula tomando el cameraspace y dot-producting por la cuarta fila de Proj .

Bueno, eso no es muy útil. Se vuelve más útil si realmente miramos la cuarta fila de Proj . De acuerdo, podría estar usando cualquier matriz de proyección, y si no está usando la matriz de proyección típica, este cálculo se vuelve más difícil (potencialmente imposible).

La cuarta fila de Proj , usando la típica matriz de proyección, es realmente solo esto:

[0, 0, -1, 0]

Esto significa que el clipspace.w es realmente solo -cameraspace.z . ¿Cómo nos ayuda eso?

Ayuda al recordar esto:

ndcspace.z = clipspace.z / clipspace.w; ndcspace.z = clipspace.z / -cameraspace.z;

Bueno, eso es bueno, pero solo cambia uno por desconocido; todavía tenemos una ecuación con dos incógnitas ( clipspace.z y cameraspace.z ). Sin embargo, sí sabemos algo más: clipspace.z proviene del cameraspace productivo de cameraspace con la tercera fila de nuestra matriz de proyección. La tercera fila de la matriz de proyección tradicional se ve así:

[0, 0, T1, T2]

Donde T1 y T2 son números distintos de cero. Ignoramos cuáles son estos números por el momento. Por lo tanto, clipspace.z es realmente solo T1 * cameraspace.z + T2 * cameraspace.w . Y si sabemos que cameraspace.w es 1.0 (como suele ser), entonces podemos eliminarlo:

ndcspace.z = (T1 * cameraspace.z + T2) / -cameraspace.z;

Entonces, todavía tenemos un problema. En realidad, no lo hacemos. ¿Por qué? Porque solo hay un desconocido en esta euqation. Recuerde: ya conocemos ndcspace.z . Por lo tanto, podemos usar ndcspace.z para calcular cameraspace.z :

ndcspace.z = -T1 + (-T2 / cameraspace.z); ndcspace.z + T1 = -T2 / cameraspace.z; cameraspace.z = -T2 / (ndcspace.z + T1);

T1 y T2 salen directamente de nuestra matriz de proyección (la escena original). Y ya tenemos ndcspace.z . Entonces podemos calcular cameraspace.z . Y sabemos que:

clispace.w = -cameraspace.z;

Por lo tanto, podemos hacer esto:

vec4 clipspace = vec4(ndcspace * clipspace.w, clipspace.w);

Obviamente necesitarás un flotador para clipspace.w lugar del código literal, pero entiendes mi punto. Una vez que tienes clipspace , para obtener el espacio de la cámara, multiplicas por la matriz de proyección inversa:

vec4 cameraspace = InvProj * clipspace;