Как изменить положение вершины с помощью gsl

Я пытаюсь переместить объект в зависимости от положения камеры. Вот мой вершинный шейдер

uniform mat4 osg_ViewMatrixInverse;

void main(){
vec4 position  = gl_ProjectionMatrix * gl_ModelViewMatrix *gl_Vertex;   
vec3 camPos=osg_ViewMatrixInverse[3].xyz;

if( camPos.z >1000.0 )
  position.z = position.z+1.0;
    if( camPos.z >5000.0 )
  position.z = position.z+10.0;
if (camPos.z< 300.0 )
  position.z = position.z+300.0;
gl_Position =  position;
}

Но при вертикальном положении камеры меньше 300 или больше 1000 модель просто исчезает, хотя во втором случае ее надо сдвинуть всего на единицу. Я читал о том, что координаты шейдера отличаются от мировых координат, поэтому я умножаю на матрицы Projection и ModelView, чтобы получить мировые координаты. Может быть, я ошибаюсь в этом вопросе? Простите, если вопрос простой, но ответа не нашел.

ОБНОВЛЕНИЕ: camPos переводится в мировые координаты, а position — нет. Может быть, это связано с тем, что я использую osg_ViewMatrixInverse (переданный OpenSceneGraph) для получения положения камеры и внутренних gl_ProjectionMatrix и gl_ModelViewMatrix для получения координат вершин? Как перевести положение в мировые координаты?


person Stranger1399    schedule 14.03.2014    source источник


Ответы (3)


Проблема заключается в том, что вы преобразуете положение в координаты клипа (путем умножения gl_Vertex на матрицы проекции и представления модели), а затем выполняете операцию мировых координат над этими координатами клипа, что не дает желаемых результатов.

Просто выполните свои преобразования, прежде чем умножать на матрицы представления модели и проекции.

uniform mat4 osg_ViewMatrixInverse;

void main() {
    vec4 position = gl_Vertex;   
    vec3 camPos=osg_ViewMatrixInverse[3].xyz;

    if( camPos.z >1000.0 )
        position.z = position.z+1.0;
    if( camPos.z >5000.0 )
        position.z = position.z+10.0;
    if (camPos.z< 300.0 )
        position.z = position.z+300.0;
    gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * position;
}
person Colonel Thirty Two    schedule 14.03.2014
comment
позиция находится в пространстве объектов, а камера находится в мировом пространстве. Идея есть, но работать не будет - person Raxvan; 14.03.2014
comment
Затем вам нужно будет разделить матрицу модели и представления, умножить позицию на матрицу модели, выполнить свою операцию, а затем умножить ее на матрицы представления и проекции. - person Colonel Thirty Two; 14.03.2014
comment
@Colonel Thirty Two Я сделал, как вы предложили, теперь модель исчезает в точке ниже 300, а в точке выше 1000 происходит что-то странное (я изменил это на position.z = position.z+200.0, чтобы было легче обнаружить разница). Большая часть модели поднята более чем на 1000 единиц, а некоторые части просто висят в воздухе отдельно. Идея есть.... Как разделить модель и матрицы просмотра? gl не предоставляет их отдельно. - person Stranger1399; 14.03.2014
comment
Вам придется выполнять матричные операции самостоятельно (я рекомендую GLM), затем загрузить их через униформу. Матричные функции GL в любом случае являются устаревшими функциями и удалены в OpenGL 3.1+. - person Colonel Thirty Two; 14.03.2014
comment
@Colonel Тридцать два Спасибо, я попробую. - person Stranger1399; 14.03.2014

gl_Position находится в пространстве отсечения, значения, которые вы выводите для любой координаты, должны быть >= -gl_Position.W или ‹= gl_Position.W, иначе они будут обрезаны. Если все ваши координаты для примитива находятся за пределами этого диапазона, то ничего не будет нарисовано. Причина этого в том, что после завершения вершинного шейдера OpenGL делит координаты пространства отсечения на W, чтобы получить координаты в диапазоне [-1,1] (NDC). Все, что находится за пределами этого объема, не будет отображаться на экране.

На самом деле вам следует добавить эти координаты к вашей позиции в пространстве объектов, а затем выполнить преобразование из пространства объектов в пространство отсечения. Ответ полковника Тридцать два уже очень хорошо показывает, как это сделать; Я просто хотел объяснить, почему вы не должны применять это смещение к координатам пространства отсечения.

person Andon M. Coleman    schedule 14.03.2014

Догадаться:

uniform mat4 osg_ViewMatrixInverse;
uniform mat4 osg_ViewMatrix;

void main(){
    vec3 camPos=osg_ViewMatrixInverse[3].xyz;

    vec4 position_in_view_space = gl_ModelViewMatrix * gl_Vertex;
    vec4 position_in_world_space  = osg_ViewMatrixInverse * position_in_view_space;

    if( camPos.z >1000.0 )
      position_in_world_space.z = position_in_world_space.z+700.0;
    if( camPos.z >5000.0 )
      position_in_world_space.z = position_in_world_space.z+1000.0;
    if (camPos.z< 300.0 )
      position_in_world_space.z = position_in_world_space.z+200;
    position_in_view_space = osg_ViewMatrix * position_in_world_space;
    vec4 position_in_object_space = gl_ModelViewMatrixInverse * position_in_view_space;
    gl_Position = gl_ModelViewProjectionMatrix * position_in_object_space;
}

Нужно преобразовать gl_Vertex (который находится в координатах пространства объекта) в координаты мира через координаты пространства просмотра (может быть, есть прямое преобразование, которое я не вижу), чем он может изменить их и преобразовать обратно в координаты пространства объекта.

person Stranger1399    schedule 14.03.2014