2011-02-04 2 views
20

Я хочу настроить цвета в зависимости от того, какое положение xyz они находятся в мире.GLSL: Как получить положение пикселя x, y, z?

Я попробовал это в моем пиксельном шейдере:

varying vec4 verpos; 

void main(){ 
    vec4 c; 
    c.x = verpos.x; 
    c.y = verpos.y; 
    c.z = verpos.z; 
    c.w = 1.0; 

    gl_FragColor = c; 
} 

но мне кажется, что цвета изменяются в зависимости от моего угла наклона камеры/положения, как я сделать Coords независимо от моей позиции камеры/угла?

Heres моя вершинный шейдер:

varying vec4 verpos; 

void main(){ 
    gl_Position = ftransform(); 
    verpos = gl_ModelViewMatrix*gl_Vertex; 
} 

Edit2: изменил название, поэтому я хочу мира COORDS, а не экран Coords!

Edit3: добавил мой полный код

+2

Не умножать по вашей gl_ModelViewMatrix. – Hannesh

ответ

27

В вершинном шейдере у вас есть gl_Vertex (или что-то еще, если вы не используете фиксированный трубопровод), который является положением вершины в модели координат. Умножьте модельную матрицу на gl_Vertex, и вы получите положение вершин в мировых координатах. Назначьте это переменной переменной, а затем прочитайте ее значение в шейдере фрагмента, и вы получите положение фрагмента в мировых координатах.

Теперь проблема заключается в том, что у вас не обязательно есть матрица моделей, если вы используете матрицу просмотра по умолчанию OpenGL, которая представляет собой комбинацию как матрицы модели, так и вида. Я обычно решают эту проблему, имея две отдельные матрицы, а не просто один видовой матрицы:

  1. модель матрицы (карты координаты модели в мировой системе координат), и
  2. вид матрицы (карты мира в координаты камеры).

Так что просто передайте две разные матрицы в ваш вершинный шейдер отдельно. Вы можете сделать это, определив

uniform mat4 view_matrix; 
uniform mat4 model_matrix; 

В начале шейдера вершин. И тогда вместо ftransform(), говорят:

gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex; 

В основной программе необходимо записать значения в обоих этих новых матриц. Во-первых, чтобы получить матрицу вида, сделайте преобразования камеры с помощью glLoadIdentity(), glTranslate(), glRotate() или gluLookAt() или того, что вы предпочитаете, как обычно, а затем вызовите массив glGetFloatv (GL_MODELVIEW_MATRIX, &); чтобы получить матричные данные в массив. А во-вторых, аналогичным образом, чтобы получить матрицу модели, также вызовите glLoadIdentity(); и выполните преобразования объектов с glTranslate(), glRotate(), glScale() и т. д. и, наконец, вызовите glGetFloatv (массив GL_MODELVIEW_MATRIX, &); чтобы получить данные матрицы из OpenGL, чтобы вы могли отправить их в свой шейдер вершин. Особенно обратите внимание, что вам нужно вызвать glLoadIdentity(), прежде чем начать преобразовывать объект. Обычно вы сначала должны преобразовывать камеру, а затем преобразовывать объект, который приведет к одной матрице, которая выполняет как функцию представления, так и модели. Но поскольку вы используете отдельные матрицы, вам необходимо сбросить матрицу после преобразования камеры с помощью glLoadIdentity().

gl_FragCoord - координаты пикселя, а не координаты мира.

+1

@ltjax спасибо, отредактировал мой ответ. – kynnysmatto

+0

Я не могу заставить его работать, он меняет цвета, когда меняю положение/поворот камеры. см. мой текущий код в правлении. – Rookie

+0

@Rookie, извините, я пару раз редактировал свой ответ. вы прочитали и поняли эту последнюю версию? – kynnysmatto

-2

Самый простой способ - передать мировое положение вниз от вершинного шейдера с помощью переменной переменной.

Однако, если вы действительно должны восстановить его с gl_FragCoord, единственный способ сделать это - инвертировать все шаги, которые привели к координатам gl_FragCoord. Обратитесь к спецификациям OpenGL, если вам действительно нужно это сделать, потому что потребуется глубокое понимание преобразований.

10

Или вы могли бы просто разделить координату z по координате w, которая по существу не делает перспективную проекцию; давая вам свои оригинальные мировые координаты.

ie.

depth = gl_FragCoord.z/gl_FragCoord.w; 

Конечно, это будет работать только для не вырезанных координат ..

Но кто заботится о обрезаны из них так или иначе?

+1

Это по существу даст мне расстояние от камеры до фрагмента? Сладкий ... это именно то, что я хотел. – mpen

0

Вам необходимо пройти матрицу World/Модель в мундире до вершинного шейдера, а затем умножить его на положение вершин и отправить его в качестве изменения в пиксельный шейдер:

/*Vertex Shader*/ 

layout (location = 0) in vec3 Position 

uniform mat4 World; 
uniform mat4 WVP; 

//World FragPos 
out vec4 FragPos; 

void main() 
{ 
FragPos = World * vec4(Position, 1.0); 
gl_Position = WVP * vec4(Position, 1.0); 
} 

/*Fragment Shader*/ 

layout (location = 0) out vec4 Color; 

... 

in vec4 FragPos 

void main() 
{ 
Color = FragPos; 
} 
Смежные вопросы