Оптимизация шейдера теневого объема (GLSL)

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

void main(void) {
  vec3 lightDir = (gl_ModelViewMatrix * gl_Vertex 
                   - gl_LightSource[0].position).xyz;

  // if the vertex is lit
  if ( dot(lightDir, gl_NormalMatrix * gl_Normal) < 0.01 ) {

    // don't move it
    gl_Position = ftransform();
  } else {

    // move it far, is the light direction
    vec4 fin = gl_ProjectionMatrix * (
                 gl_ModelViewMatrix * gl_Vertex 
                 + vec4(normalize(lightDir) * 100000.0, 0.0)
               );
    if ( fin.z > fin.w ) // if fin is behind the far plane
      fin.z = fin.w; // move to the far plane (needed for z-fail algo.)
    gl_Position = fin;
  }
}

person Franck Freiburger    schedule 25.03.2010    source источник
comment
Такое проецирование каждой вершины кажется болезненным для каждого прохода. Рассматривали ли вы возможность найти силуэты объектов в явном виде, а затем просто спроецировать их? Для сетки N вершин существует порядка sqrt(N) вершин силуэта, так что это большая победа. Особенно потому, что вы можете эффективно вычислить силуэт, если источники света и объекты движутся плавно.   -  person Michael Daum    schedule 12.04.2010


Ответы (1)


Если вы не хотите трогать свой основной алгоритм (как предложил Майкл Даум в своем комментарии), вы можете заменить некоторые части своего кода:

uniform mat4 infiniteProjectionMatrix;

if(...) {
   ...
} else {
   gl_Position = infiniteProjectionMatrix * vec4(lightDir, 0.0);
}    

где InfiniteProjectionMatrix — настраиваемая матрица проекции, в которой дальняя плоскость установлена ​​на бесконечность (см. http://www.terathon.com/gdc07_lengyel.pdf на слайде 7) и выглядит примерно так:

*  0  0  0
0  *  0  0
0  0 -1  *
0  0 -1  0

Поскольку вы проецируете на бесконечность, вам не нужен коэффициент масштабирования «100000,0», а смещением «gl_ModelViewMatrix * gl_Vertex» можно пренебречь (по сравнению с бесконечной длиной вектора lightDir).

person Community    schedule 27.03.2014