Próbowałem zaimplementować zamknięcie przestrzeni ekranu zgodnie z instrukcją this samouczek. Zajmuję się problemami z moją implementacją, ponieważ natknąłem się na nie, ale ten problem mnie teraz zaskoczył.OpenGL: Wyświetlanie współrzędnych przestrzeni widoku z NDC, pozornie poza zakresem [-1,1]
Moje zrozumienie metody jest następujące. Czynnik okluzji otoczenia określa się za pomocą próbek pobranych z półkuli wyrównanej do normalnej dla danego fragmentu. Aby określić, czy próbka przyczynia się do współczynnika okluzji otoczenia, muszę sprawdzić głębokość próbki w polu widoku w stosunku do tekstury głębokości przestrzeni widoku (zawartej w lewym dolnym rogu obrazów tego wpisu). Tak więc wiem, które współrzędne, aby pobrać z tekstury głębi, muszę przekształcić współrzędne linii próbki z przestrzeni widoku do znormalizowanych współrzędnych urządzenia (w zakresie [-1,1]), a następnie do zakresu [0 1], więc tekstura głębi skutecznie "odwzorowuje" do okna roboczego.
Poniższy obraz przedstawia moją ambientową okluzję nałożoną na moją scenę. Zdaję sobie sprawę, że mam dość oczywisty problem z samą okluzją otoczenia (zakładam, że półkule są źle zorientowane), z którymi poradzę sobie w porę, ale to, co wzbudza moją ciekawość, to pojawienie się okluzji ", sugerując, że moja operacja przejścia od współrzędnych próbki przestrzeni widoku do współrzędnych tekstury jest nieprawidłowa.
Jak mam brakuje stabilnego Shader Debugger, debugowanie mogę zrobić, jest ograniczona do tego, co można uczynić na ekranie. Następny obraz jest tworzony za pomocą następującego kodu z strategii zwalczania narkotyków jest znormalizowana urządzeniach współrzędnych dla danej próbki .:
if (ndcs.x > 1.0f || ndcs.y > 1.0f || ndcs.x < -1.0f || ndcs.y < -1.0f)
{
gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
else
{
gl_FragColor = vec4(vec3(1.0f), 1.0f);
}
ja oczekiwać, że obraz jest całkowicie biały (a raczej bity, w których używam tego shadera), jednak wydaje się sugerować, że tworzone przeze mnie centra danych są poza zakresem [-1,1], co moim zdaniem musi być nieprawidłowe. To nie jest zgodne obszaru ekranu albo, jak widać na poniższym obrazie, w którym aparat jest bardzo blisko powierzchni:
nigdy nie używałem tej procedury, aby uzyskać NDCS wcześniej, więc jestem pewien, że moja logika musi gdzieś być nie tak. Pobrałem kod demonstracyjny dostarczony wraz z samouczkiem i nie widzę, gdzie mój kod się różni. Szukałem również w Internecie (w tym na tej stronie) i wydaje mi się, że nie mogę znaleźć nikogo z takimi samymi objawami jak ja.
Oto odpowiedni kod z moich shaderów:
Vert Shader:
v_eye_space_position = u_mvpMatrix * a_position;
v_world_space_normal = normalize(u_rotationMatrix * a_normal);
v_eye_space_normal = normalize(u_mvpMatrix * a_normal);
gl_Position = v_eye_space_position;
Frag Shader:
// --- SSAO Testing ---
// Convert from the noise texture back to [-1,1] range
// We want the noise texture to tile across the screen.
vec3 kernel_rotation = (texture2D(s_noise, gl_FragCoord.xy * u_noise_scale) * 2.0f - 1.0f).xyz;
vec3 eye_space_tangent = normalize(kernel_rotation - v_eye_space_normal.xyz * dot(kernel_rotation, v_eye_space_normal.xyz));
vec3 eye_space_bitangent = cross(v_eye_space_normal.xyz, eye_space_tangent);
mat3 tbn = mat3(eye_space_tangent, eye_space_bitangent, v_eye_space_normal);
float ambient_occlusion = 0.0f;
const float hemisphere_radius = 0.05f;
for (int i=0; i<16; i++)
{
vec3 kernel_sample = tbn * u_ssao_kernel[i];
kernel_sample = kernel_sample * hemisphere_radius + v_eye_space_position.xyz;
// Project the sample position into screen space.
vec4 offset = vec4(kernel_sample, 1.0f);
offset = u_projection_matrix * offset;
offset.xy /= offset.w;
vec4 ndcs = offset;
offset.xy = 1.0f - (offset.xy * 0.5f + 0.5f);
// Find the depth at this sample point.
float sample_depth = texture2D(s_camera_depth, offset.xy).z;
// Check if the sample point is occluded.
float range_check = 0.0f;
float linear_eye_space_position = (v_eye_space_position.z - u_near_plane)/(u_far_plane - u_near_plane);
// Range check.
if (abs(linear_eye_space_position - sample_depth) < hemisphere_radius)
{
range_check = 1.0f;
}
float linear_kernel_sample_depth = (kernel_sample.z - u_near_plane)/(u_far_plane - u_near_plane);
if (sample_depth <= linear_kernel_sample_depth)
{
ambient_occlusion += 1.0f * range_check;
}
}
// Average and invert the ambient occlusion.
ambient_occlusion = 1.0f - (ambient_occlusion/16.0f);
Szukałem w każdym elemencie w izolacji i nie mogę zobacz problem z nimi.
- Mam podstawiony za własną pozycję w przestrzeni widok fragmentu jest do projekcji (zamiast pozycji widok przestrzeni w próbce) i dostaję takie same wyniki.
- Macierz projekcji jest macierzą perspektywa używam do przekształcania wierzchołki modelki (mam skonstruowana macierz MVP w moim vertex shader w celu zapewnienia macierzy projekcji jest osiągnięciem programu cieniującego w takcie i jest).
- Sama operacja projekcji - nie jest to coś, co robiłem wcześniej, ale przeczytałem artykuły online i pytania od osób z problemami z projekcją i nie widzę, co robię źle.
Mogę tylko stwierdzić, że musi istnieć coś fundamentalnego w moim zrozumieniu projekcji perspektywicznej, która jest wadliwa, ale ja po prostu nie wiem, co. Jeśli ktokolwiek z was mógłby rzucić trochę światła na problem lub dalsze możliwości, które mógłbym sprawdzić, byłbym bardzo wdzięczny. Jeśli są jakieś przydatne informacje, które pominąłem lub cokolwiek, co mogę wyjaśnić, proszę daj mi znać.
Dziękuję bardzo za pomoc w tej sprawie. Po wykonaniu sugestii wyniki są tym, czego oczekiwałem. To zabawne, jak zaślepiłem się na tak prosty błąd. Lekcja: zawsze sprawdzaj "proste" rzeczy (szczególnie współrzędne przestrzeni). Jeszcze raz bardzo dziękuję - uwolniłeś mnie od ogromnego stresu. Miłego dnia! :) –