Мир состоит из сфер.Поскольку рисование сферы в OpenGL занимает много треугольников, я подумал, что было бы быстрее использовать точку и радиус для представления сферы, а затем использовать Billboarding в OpenGL для ее рисования.При текущем подходе, который я выбрал, смежные сферы не соприкасаются при повороте вида.
Вот пример:
Есть две сферы:
Сфера 1 Позиция (0, 0, -3) Радиус (0.5)
Сфера 2 Позиция (-1, 0, -3) Радиус (0,5)
Матрица проекции определяется с помощью:
glm::perspective(glm::radians(120.0f), 1.0f, 1.0f, 100.0f);
Изображение 1 : если вращение отсутствует, оно выглядит так, как ожидалось.
![No rotation](https://i.stack.imgur.com/fFiSm.png)
Изображение 2 : при наличии вращение, рекламный щит реагирует на камеру, как и ожидалось, , но сферы больше не касаются.И если бы они были на самом деле сферами, которые были рядом друг с другом, вы могли бы ожидать их прикосновения.
![Rotation](https://i.stack.imgur.com/g4XBz.png)
Что я пробовал:
- Я пытался
GL_POINTS
, они не работали так хорошо, потому что мне показалось, что тест глубины для меня не совсем корректный. - Я пробовал геометрический шейдер, который создает квадрат до и после применения матрицы проекции.
Вот код, который я сейчас создал для создания изображений:
Вершинный шейдер
#version 460
layout(location = 0) in vec3 position;
layout(location = 1) in float radius;
out float radius_vs;
void main()
{
gl_Position = vec4(position, 1.0);
radius_vs = radius;
}
Геометрический шейдер
#version 460
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
layout(location = 2) uniform mat4 view_mat;
layout(location = 3) uniform mat4 projection_mat;
in float radius_vs[];
out vec2 bounds;
void main()
{
vec3 x_dir = vec3(view_mat[0][0], view_mat[1][0], view_mat[2][0]) * radius_vs[0];
vec3 y_dir = vec3(view_mat[0][1], view_mat[1][1], view_mat[2][1]) * radius_vs[0];
mat4 fmat = projection_mat * view_mat;
gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz - x_dir - y_dir, 1.0f);
bounds = vec2(-1.0f, -1.0f);
EmitVertex();
gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz - x_dir + y_dir, 1.0f);
bounds = vec2(-1.0f, 1.0f);
EmitVertex();
gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz + x_dir - y_dir, 1.0f);
bounds = vec2(1.0f, -1.0f);
EmitVertex();
gl_Position = fmat * vec4(gl_in[0].gl_Position.xyz + x_dir + y_dir, 1.0f);
bounds = vec2(1.0f, 1.0f);
EmitVertex();
EndPrimitive();
}
Фрагмент шейдера
#version 460
out vec4 colorOut;
in vec2 bounds;
void main()
{
vec2 circCoord = bounds;
if (dot(circCoord, circCoord) > 1.0)
{
discard;
}
colorOut = vec4(1.0f, 1.0f, 0.0f, 1.0);
}