Рендеринг WebGL в текстуру - как мне записать данные в альфа-канал?

В качестве предисловия я пытаюсь воспроизвести алгоритм рендеринга воды, описанный в этой статье http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter19.html. Часть этого алгоритма требует рендеринга альфа-маски во фреймбуфер, чтобы использовать ее позже для выборки текстуры из первоначально визуализированной сцены. Вкратце алгоритм выглядит так:

  1. Визуализируйте геометрию сцены в текстуру S, пропуская преломляющие сетки и заменяя ее альфа-маской
  2. Визуализируйте преломляющие сетки, выбирая текстуру S с возмущением, ЕСЛИ она находится внутри альфа-маски, в противном случае просто напрямую выбирайте текстуру S

К сожалению, я все еще изучаю WebGL и на самом деле не знаю, как это сделать. Кроме того, в этой статье используется HLSL, и преобразование для меня нетривиально. Очевидно, что попытка сделать это во фрагментном шейдере не сработает:

void main( void ) {
    gl_FragColor = vec4( 0.0 );
}

потому что он будет просто смешиваться с ранее визуализированной геометрией, а значение альфа по-прежнему будет равно 1.0.

Вот краткий обзор того, что у меня есть:

function animate(){
    ... snip ...
    renderer.render( scene, camera, rtTexture, true );

    renderer.render( screenScene, screenCamera );
}

// water fragment shader
void main( void ){
    // black out the alpha channel
    gl_FragColor = vec4(0.0);
}

// screen fragment shader 
varying vec2 vUv;
uniform sampler2D screenTex;

void main( void ) {
    gl_FragColor = texture2D( screenTex, vUv );

    // just trying to see what the alpha mask would look like
    if( gl_FragColor.a < 0.1 ){
        gl_FragColor.b = 1.0;
    }
}

Полный код можно найти на странице http://scottrabin.github.com/Terrain/.


person Scott R    schedule 19.02.2012    source источник


Ответы (1)


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

Решать вам. Просто используйте правильные режимы наложения:

glBlendFuncSeparate(..., ..., GL_ONE, GL_ZERO);

glBlendFuncSeparate устанавливает раздельное смешивание для частей цвета RGB и Alpha. В этом случае он записывает исходную альфу прямо в место назначения.

Обратите внимание: если вы рисуете что-то непрозрачное, вам не нужны режимы наложения. Выходной альфа-канал будет записан как есть, как и цвет.

person Nicol Bolas    schedule 19.02.2012
comment
Я использую Three.js, и вызов renderer.context.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ZERO) не заставляет шейдер фрагмента экрана отображать синий цвет, как хотелось бы. В спецификации GL также говорится, что вам нужно включить GL_BLEND, который ничего не изменил, когда я его тоже вставил. Я что-то там упускаю? - person Scott R; 19.02.2012