Я только что закончил первую версию своего приложения для iOS, Corebox , и сейчас работаю над некоторыми новыми функциями.
Одна из новых функций - это «небольшая» настройка рендеринга OpenGL, чтобы заставить некоторые объекты никогда не рисоваться меньше минимального размера. Все объекты, нуждающиеся в этой обработке, представляют собой простые 2-точечные линии, нарисованные с помощью GL_LINES.
Этот аннотированный скриншот объясняет, что мне нужно. Не обращайте внимания на серые линии, единственные объекты, которые меня интересуют, это более широкие желтые линии.
Я очень много гуглил, и мне кажется, что мне нужно изменить геометрию линий, используя вершинный шейдер. Я довольно новичок в GLSL, и большинство примеров шейдеров, которые я могу найти, касаются применения освещения и других эффектов, например: GLSL Heroku Editor и KicksJS редактор шейдеров .
Мой текущий вершинный шейдер чрезвычайно прост:
// GL_LINES vertex shader
uniform mat4 Projection;
uniform mat4 Modelview;
attribute vec4 Position;
attribute vec4 SourceColor;
varying vec4 DestinationColor;
void main(void) {
DestinationColor = SourceColor;
gl_Position = Projection * Modelview * Position;
}
Как и мой фрагментный шейдер:
// GL_LINES fragment shader
varying lowp vec4 DestinationColor;
void main(void) {
gl_FragColor = DestinationColor;
}
Мое предположение относительно того, что требуется:
- Определить расстояние между зрителем (положение камеры) и объектом
- Определите, насколько велик объект на экране, исходя из его размера и расстояния до камеры
- Если объект будет слишком маленьким, отрегулируйте его вершины так, чтобы он стал достаточно большим, чтобы его можно было легко увидеть на экране.
Предостережения и другие примечания:
- Но если вы уменьшите масштаб, не приведет ли это к тому, что модель будет просто оранжевым шариком на экране? Да, это именно тот эффект, который мне нужен.
Редактировать: вот окончательная рабочая версия реализации предложений от mifortin
uniform mat4 Projection;
uniform mat4 Modelview;
uniform float MinimumHeight;
attribute vec4 Position;
attribute vec4 ObjectCenter;
attribute vec4 SourceColor;
varying vec4 DestinationColor;
void main(void) {
// screen-space position of this vertex
vec4 screenPosition = Projection * Modelview * Position;
// screen-space mid-point of the object this vertex belongs to
vec4 screenObjectCenter = Projection * Modelview * ObjectCenter;
// Z should be 0 by this time and the projective transform in w.
// scale so w = 1 (these two should be in screen-space)
vec2 newScreenPosition = screenPosition.xy / screenPosition.w;
vec2 newObjectCenter = screenObjectCenter.xy / screenObjectCenter.w;
float d = distance(newScreenPosition, newObjectCenter);
if (d < MinimumHeight && d > 0.0) {
// Direction of this object, this really only makes sense in the context
// of a line (eg: GL_LINES)
vec2 towards = normalize(newScreenPosition - newObjectCenter);
// Shift the center point then adjust the vertex position accordingly
// Basically this converts: *--x--* into *--------x--------*
newObjectCenter = newObjectCenter + towards * MinimumHeight;
screenPosition.xy = newObjectCenter.xy * screenPosition.w;
}
gl_Position = screenPosition;
DestinationColor = SourceColor;
}