2017-01-30 12 views
0

Я беру курс в WebGL в NTNU. В настоящее время я изучаю, что делают шейдеры и как я могу их использовать.Возможно ли запустить код один раз за призыв на призыв в WebGL?

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

Это означает, что я должен поместить код где-то в другом месте, кроме функции main() в вершинном шейдере, поскольку этот вызов вызывается много раз за призыв на призыв.

Vertex шейдеров:

uniform vec3 camRotation; 
attribute vec3 position; 
void main() { 

    // I want this code to run only once per draw call 
    float rX = camRotation[0]; 
    float rY = camRotation[1]; 
    float rZ = camRotation[2]; 
    mat4 camMatrix = mat4(
     cos(rY) * cos(rZ), cos(rZ) * sin(rX) * sin(rY) - cos(rX) * sin(rZ), sin(rX) * sin(rZ) + cos(rX) * cos(rZ) * sin(rY), 0, // 
     cos(rY) * sin(rZ), cos(rX) * cos(rZ) + sin(rX) * sin(rY) * sin(rZ), cos(rX) * sin(rY) * sin(rZ) - cos(rZ) * sin(rX), 0, // 
     -sin(rY), cos(rY) * sin(rX), cos(rX) * cos(rY), 0, // 
     0, 0, 0, 1 
    ); 
    // End of code in question 

    gl_Position = camMatrix * vec4(position, 1); 
    gl_PointSize = 5.0; 
} 

Возможно ли это? Неужели я дурак для попытки?

+0

Вы можете найти [эти статьи полезны] (http://webglfundamentals.org) – gman

ответ

3

AFAIK, нет никакого способа сделать это. Вы должны вычислить camMatrix в коде JS и передать его в шейдер через униформе:

uniform mat4 camMatrix; 
attribute vec3 position; 
void main() { 
    gl_Position = camMatrix * vec4(position, 1); 
    gl_PointSize = 5.0; 
} 

Теперь вы должны вычислить матрицу в JS:

// assuming that program is your compiled shader program and 
// gl is your WebGL context. 
const cos = Math.cos; 
const sin = Math.sin; 
gl.uniformMatrix4fv(gl.getUniformLocation(program, 'camMatrix'), [ 
    cos(rY) * cos(rZ), cos(rZ) * sin(rX) * sin(rY) - cos(rX) * sin(rZ), sin(rX) * sin(rZ) + cos(rX) * cos(rZ) * sin(rY), 0, 
    cos(rY) * sin(rZ), cos(rX) * cos(rZ) + sin(rX) * sin(rY) * sin(rZ), cos(rX) * sin(rY) * sin(rZ) - cos(rZ) * sin(rX), 0, 
    -sin(rY), cos(rY) * sin(rX), cos(rX) * cos(rY), 0, 
    0, 0, 0, 1 
]); 
+0

Спасибо за ответ. Я знаю о методе, который вы предоставляете, я любопытно посмотреть, могу ли я сделать эти вычисления (например, 'cos (rY)') в шейдере один раз за призыв на призыв – gromit190

+1

@Birger Я был бы очень удивлен из-за того, как GPU запускает шейдеры. Чтобы грубо описать каждое исполнение шейдера (для каждой вершины, если мы говорим о вершинных шейдерах и для каждого пикселя в случае фрагментарных шейдеров) получает свое собственное состояние и кусок памяти. И синхронизация и обмен данными между ними были бы несколько громоздкими и потенциально медленными. –

2

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

Матрица проецирования делает то, что ее название подразумевает проецирование точек в перспективе или ортогональном (вы можете думать об этом как о объективе вашей камеры). Матрица представления представляет собой преобразование для перевода/поворота этой проекции (положение и ориентация камеры), в то время как матрица мира/модели для объекта содержит преобразования (перевод, поворот и масштаб) отдельного объекта.

В вашем шейдере вы затем превратить вашу позицию вершины в мировом пространстве, используя за объект модели/мировую матрицу, а затем, наконец, превратить его в пространство камеры с помощью матрицы ViewProjection предварительно умноженные:

gl_Position = matViewProjection * (matWorld * vPosition) 

Как вы рисования точек в зависимости от вашего usecase вы могли бы уменьшить матрицу мира только вектором перевода.

+0

Это очень поучительно, спасибо! – gromit190

 Смежные вопросы

  • Нет связанных вопросов^_^