Three.js: [EffectComposer] Проблема с 2 последовательными RenderPass

Созданный на 1 февр. 2012  ·  18Комментарии  ·  Источник: mrdoob/three.js

Связь

http://demo.bkcore.com/threejs/webgl_tron_glow.html

Код

glowcomposer = new THREE.EffectComposer( renderer, renderTarget );

glowcomposer.addPass( renderModelGlow ); // RenderPass
glowcomposer.addPass( hblur ); // ShaderPass
glowcomposer.addPass( vblur ); // ShaderPass
glowcomposer.addPass( effectSave ); // SavePass

glowcomposer.addPass( renderModel ); // RenderPass
glowcomposer.addPass( finalPass ); // ShaderPass

Контекст

У меня есть две сцены с одним и тем же объектом / камерой / светом. Один с диффузной текстурой (http://demo.bkcore.com/threejs/webgl_tron.html) и другой со светящейся текстурой (светящиеся области белые на черном).

Мой конвейер рендеринга выглядит следующим образом:
Сначала я визуализирую сцену свечения и применяю к ней размытие по горизонтали и вертикали, а затем сохраняю результат в frameBuffer с помощью SavePass.
Затем я хочу визуализировать диффузную сцену.
И, наконец, смешайте это с фреймбуфером свечения.

Проблема

Мой образец свечения 2D хорошо передается моему шейдеру finalPass, но, как вы можете видеть в демонстрации, второй вызов RenderPass для диффузной сцены не работает. Выводит только черный цвет.

Я попытался отрендерить диффузную сцену за один проход рендеринга, и это сработало. Когда я использую его как второй RenderPass, он не работает.

Есть идеи ?

Спасибо.
Тибо Д.

Question

Самый полезный комментарий

Похоже, исходная демонстрация больше не работает:

FWIW Я сделал урезанную демонстрацию выборочного применения FX и компоновки с помощью Additive Blend (с использованием Three.js v79) здесь: https://www.airtightinteractive.com/demos/selective-fx/

Все 18 Комментарий

Я думаю, это потому, что буфер глубины разрушается, см. №1017.

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

Что-то вроде этого:

glowComposer = new THREE.EffectComposer( renderer, renderTargetGlow );

glowComposer.addPass( renderModelGlow ); // RenderPass
glowComposer.addPass( hblur ); // ShaderPass
glowComposer.addPass( vblur ); // ShaderPass

finalComposer = new THREE.EffectComposer( renderer, renderTargetFinal );
finalComposer.addPass( renderModel ); // RenderPass
finalComposer.addPass( finalPass ); // ShaderPass

Теперь диффузный слой будет доступен как обычный образец текстуры tDiffuse в finalComposer и слой свечения, который вы предоставите из glowComposer .

Это будет либо glowComposer.renderTarget1 или glowComposer.renderTarget2 зависимости от конкретного количества проходов и от того, переключают ли проходы передний и задний буферы, проще всего попробовать оба и посмотреть, какой из них работает.

finalshader.uniforms[ 'tGlow' ].texture = glowComposer.renderTarget1;

Я попробовал, но получил очень неожиданный результат.

Это предложенный вами код:
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
TDiffuse из renderModel по-прежнему черный.

И это точно такой же код, только два прохода рендеринга поменяны местами (диффузная сцена находится в компоновщике свечения, а сцена свечения - в финальном композиторе):
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
Это, конечно, не тот эффект, который я ищу, поскольку размывается диффузный, а не свечение, но, как вы можете видеть, семплеры tGlow и tDiffuse работают ...

И все, что я сделал, это поменял местами (строки 130 и 175):
новый THREE.RenderPass (сцена, камера);
с участием
новый THREE.RenderPass (световая сцена, световая камера);

Это поразительно.

Если вы используете прозрачность, вам нужно использовать формат RGBA для целей рендеринга.

Что ж, я согласен, но я не использую прозрачность, так как мой проход свечения отображает белый цвет на черном, а мой диффузный проход хорошо ... диффузный на черном. Затем я составляю их с добавлением, поэтому прозрачность не нужна.

Тем не менее, на всякий случай я изменил формат RT на RGBA, но это ничего не изменило.

Странная проблема заключается в том, что выполнение RenderPass моей сцены / камеры после моего RenderPass glowscene / glowcamera не работает, в то время как выполнение RenderPass моей сцены / камеры до моего RenderPass glowscene / glowcamera.

Хммм, похоже, проблема с разделением геометрии для разных материалов (см. №1211).

Попробуй это:

function createScene( geometry, x, y, z, b ) {

    zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );

    // ...

    var geometryClone = THREE.GeometryUtils.clone( geometry );
    var gmat = new THREE.MeshBasicMaterial( { map: gtex } );
    var gmesh = new THREE.Mesh( geometryClone, gmat );

    // ...
}

Да ! Вот и все.

Два моих пробоотборника теперь правильно заполнены. Спасибо :)

РЕДАКТИРОВАТЬ

Хм ... Еще одно странное поведение, два моих семплера хороши, когда я

gl_FragColor = texel;

Я получаю диффузное изображение правильно (http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html)

Когда я делаю

gl_FragColor = glow;

Я получаю свечение правильно.

Но когда я пытаюсь сделать простую добавку на обоих
gl_FragColor = тексель + свечение;
Я получаю только свечение (http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html).

Извините за то, что задаю так много вопросов, я пытался заставить это работать, но безуспешно ..

РЕДАКТИРОВАТЬ2

На самом деле кажется, что делая

gl_FragColor = texel + glow;

В отношении вывода рендеринга это выглядит примерно так:

gl_FragColor = glow + glow;

Это похоже на то, что тексель vec4 необъяснимым образом заменяется свечением vec4. Звучит безумно.

Вам нужно поместить текстуры в разные текстурные блоки:

uniforms: {
    tDiffuse: { type: "t", value: 0, texture: null },
    tGlow:    { type: "t", value: 1, texture: null }
},

Отлично!
http://demo.bkcore.com/threejs/webgl_tron_glow.html

Еще раз спасибо :)

Летом!

Если кого-то интересует селективный рендеринг свечения с помощью Three.js, я только что опубликовал небольшую статью об этом: http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html

Надеюсь, поможет.

Ницца ;)

В качестве альтернативы, вместо клонирования геометрии, другим более дешевым вариантом было бы использование более похожих материалов (чтобы геометрия в обоих проходах требовала одинаковых буферов).

В этом случае вместо использования основного материала для прохода свечения вы можете попробовать материал Ламберта с нулевым диффузным освещением, только с окружающим светом.

Что-то вроде этого:

glowScene.add( new THREE.AmbientLight( 0xffffff ) );

// ...

var gmat = new THREE.MeshLambertMaterial( { map: gtex, ambient: 0xffffff, color: 0x000000 } );
var gmesh = new THREE.Mesh( geometry, gmat );

Действительно, это отлично работает.

http://demo.bkcore.com/threejs/webgl_tron_glow_seq.html

Я обновлю свою статью об этом решении. Спасибо !

Я портирую этот код на r60 и, как ни странно, сталкиваюсь с той же проблемой с цепочкой композиторов эффектов. У меня работает пропуск Godray, если я визуализирую его на экране. Но последний проход выводит только модель. Выход oclcomposer на канал текстуры "tadd" кажется нормальным, если я не использую отдельный Effect Composer !! Я пробовал использовать renderer.PreserveDrawingBuffer = true, но это тоже не сработало. Я пробовал установить для autoclear значение false, но это было не так.

Если я визуализирую oclcomposer после последнего композитора и передаю вывод godray на экран, я могу видеть Godrays, но не модели.

Вместо того, чтобы направлять вывод oclcomposer в канал tadd на последнем проходе, если я перенаправляю его в MeshBasicMaterial и создаю текстурированный четырехугольник и добавляю его в основную сцену, теперь я могу видеть модель и лучи (на плоскости), а не эффект, который я хочу, но он говорит мне, что конвейер текстуры работает.

// COMPOSERS
//-------------------
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBufer: false };

renderTargetOcl = new THREE.WebGLRenderTarget( SCREEN_WIDTH/2, SCREEN_HEIGHT/2, renderTargetParameters );

hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );
var bluriness = 2;

hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH*2;
vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT*2;

var renderModel = new THREE.RenderPass( scene, camera );
var renderModelOcl = new THREE.RenderPass( oclscene, oclcamera );

grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
grPass.needsSwap = true;
grPass.renderToScreen = false;

oclcomposer = new THREE.EffectComposer( renderer, renderTargetOcl );

oclcomposer.addPass( renderModelOcl );
oclcomposer.addPass( hblur );
oclcomposer.addPass( vblur );
oclcomposer.addPass( grPass );

var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
finalPass.needsSwap = true;
finalPass.renderToScreen = true;
finalPass.uniforms[ 'tAdd' ].texture = oclcomposer.renderTarget1;

renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
finalcomposer = new THREE.EffectComposer( renderer, renderTarget );

finalcomposer.addPass( renderModel );
finalcomposer.addPass( finalPass );

//RENDER
//-----------
oclcomposer.render(0.1);
finalcomposer.render( 0.1 );

@bbiswas У меня такая же проблема с последней версией. Вы что-нибудь узнали?

Да, все заработало - вот код

var renderTargetOcl = new THREE.WebGLRenderTarget( webGL_window_width/4, webGL_window_height/4, renderTargetParameters );

            hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalBlur" ] );
            vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalBlur" ] );

            var bluriness = 3;

            hblur.uniforms[ 'h' ].value = bluriness / webGL_window_width*2;
            vblur.uniforms[ 'v' ].value = bluriness / webGL_window_height*2;

            var renderModel = new THREE.RenderPass( scene, camera );
            var renderModelOcl = new THREE.RenderPass( g_occlusion_buffer, g_occlusion_camera );

            grPass = new THREE.ShaderPass( THREE.Extras.Shaders.Godrays );
            grPass.needsSwap = true;
            grPass.renderToScreen = false;

            g_volumetric_light_composer = new THREE.EffectComposer( webGLRenderer, renderTargetOcl );

            g_volumetric_light_composer.addPass( renderModelOcl );
            g_volumetric_light_composer.addPass( hblur );
            g_volumetric_light_composer.addPass( vblur );
            g_volumetric_light_composer.addPass( hblur );
            g_volumetric_light_composer.addPass( vblur );
            g_volumetric_light_composer.addPass( grPass );

            var finalPass = new THREE.ShaderPass( THREE.Extras.Shaders.Additive );
            finalPass.needsSwap = true;
            finalPass.renderToScreen = true;
            finalPass.uniforms[ 'tAdd' ].value = g_volumetric_light_composer.renderTarget1;

            finalcomposer.addPass( renderModel );
            finalcomposer.addPass( finalPass );

//in Render Loop



                g_occlusion_camera.position = camera.position;

                g_occlusion_camera.lookAt( new THREE.Vector3(0,0,0) );
                camera.lookAt( new THREE.Vector3(0,0,0)  );

                vlight.position = pointLight1.position;
                vlight.updateMatrixWorld();

                var lPos = THREE.Extras.Utils.projectOnScreen(pointLight1, camera);
                grPass.uniforms["fX"].value = lPos.x;
                grPass.uniforms["fY"].value = lPos.y;

                g_volumetric_light_composer.render(0.1);
                finalcomposer.render( 0.1 );

Большое спасибо!
Это была строка с finalPass.uniforms[ 'tAdd' ].value . У меня раньше был finalPass.uniforms[ 'tAdd' ].texture .

Привет, bbiswas, не могли бы вы добавить, где вы создали g_occlusion_buffer для этой части:

var renderModelOcl = новый THREE.RenderPass (g_occlusion_buffer, g_occlusion_camera);

Похоже, исходная демонстрация больше не работает:

FWIW Я сделал урезанную демонстрацию выборочного применения FX и компоновки с помощью Additive Blend (с использованием Three.js v79) здесь: https://www.airtightinteractive.com/demos/selective-fx/

Была ли эта страница полезной?
0 / 5 - 0 рейтинги