Three.js: [EffectComposer] 2 ํšŒ ์—ฐ์† RenderPass ๋ฌธ์ œ

์— ๋งŒ๋“  2012๋…„ 02์›” 01์ผ  ยท  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)์™€ ๊ธ€๋กœ์šฐ ํ…์Šค์ฒ˜ (๋น›๋‚˜๋Š” ์˜์—ญ์€ ๊ฒ€์ • ๋ฐ”ํƒ•์— ํฐ์ƒ‰ ์ž„)๊ฐ€์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ๋ Œ๋”๋ง ํŒŒ์ดํ”„ ๋ผ์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋จผ์ € ๊ธ€๋กœ์šฐ ์”ฌ์„ ๋ Œ๋”๋งํ•˜๊ณ  H / V ๋ธ”๋Ÿฌ๋ฅผ ์ ์šฉํ•œ ๋‹ค์Œ SavePass๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถœ๋ ฅ์„ frameBuffer์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ํ™•์‚ฐ ์žฅ๋ฉด์„ ๋ Œ๋”๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰์œผ๋กœ ๊ธ€๋กœ์šฐ ํ”„๋ ˆ์ž„ ๋ฒ„ํผ์™€ ํ˜ผํ•ฉํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ

๋‚ด ๊ธ€๋กœ์šฐ sampler2D๋Š” ๋‚ด finalPass ์…ฐ์ด๋”๋กœ ์ž˜ ์ „๋‹ฌ๋˜์ง€๋งŒ ๋ฐ๋ชจ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ํ™•์‚ฐ ์žฅ๋ฉด์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ RenderPass ํ˜ธ์ถœ์ด ์ œ๋Œ€๋กœ ์ˆ˜ํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฒ€์€ ์ƒ‰ ๋งŒ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ผ ๋ Œ๋” ํŒจ์Šค์—์„œ ํ™•์‚ฐ ์žฅ๋ฉด์„ ๋ Œ๋”๋งํ•˜๋ ค๊ณ ํ–ˆ๋Š”๋ฐ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋‘ ๋ฒˆ์งธ RenderPass๋กœ ์‚ฌ์šฉํ•  ๋•Œ์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ์•„์ด๋””์–ด?

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.
ํ‹ฐ๋ณด D.

Question

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์›๋ž˜ ๋ฐ๋ชจ ๊ฐ€ ๋” ์ด์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

FWIW ์—ฌ๊ธฐ์—์„œ Additive Blend (Three.js v79 ์‚ฌ์šฉ)๋ฅผ ํ†ตํ•ด FX๋ฅผ ์„ ํƒ์ ์œผ๋กœ ์ ์šฉํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ๋ชจ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค : 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

์ด์ œ ํ™•์‚ฐ ๋ ˆ์ด์–ด๋Š” finalComposer ์—์„œ ์ผ๋ฐ˜ tDiffuse ํ…์Šค์ฒ˜ ์ƒ˜ํ”Œ๋Ÿฌ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ glowComposer ์—์„œ ์ œ๊ณต ํ•  ๊ธ€๋กœ์šฐ ๋ ˆ์ด์–ด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠน์ • ํŒจ์Šค ์ˆ˜์™€ ํŒจ์Šค๊ฐ€ ์ „๋ฉด ๋ฐ ํ›„๋ฉด ๋ฒ„ํผ๋ฅผ ์ „ํ™˜ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ glowComposer.renderTarget1 ๋˜๋Š” glowComposer.renderTarget2 ๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๋ฅผ ๋ชจ๋‘ ์‹œ๋„ํ•˜๊ณ  ์–ด๋–ค ๊ฒƒ์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ๋งค์šฐ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‹น์‹ ์ด ์ œ์•ˆํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
http://demo.bkcore.com/threejs/webgl_tron_glow_swap.html
renderModel์˜ tDiffuse๋Š” ์—ฌ์ „ํžˆ ๊ฒ€์€ ์ƒ‰์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ๋‘ ๊ฐœ์˜ ๋ Œ๋” ํŒจ์Šค ๋งŒ ๋ฐ”๊พผ ๋˜‘๊ฐ™์€ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค (ํ™•์‚ฐ ์”ฌ์€ ๊ธ€๋กœ์šฐ ์ปดํฌ์ €์— ์žˆ๊ณ  ๊ธ€๋กœ์šฐ ์”ฌ์€ ์ตœ์ข… ์ปดํฌ์ €์— ์žˆ์Œ).
http://demo.bkcore.com/threejs/webgl_tron_glow_swap2.html
๋ฌผ๋ก  ๋””ํ“จ์ฆˆ๊ฐ€ ํ๋ ค์ง€๊ณ  ๊ธ€๋กœ์šฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๊ฐ€ ์ฐพ๊ณ ์žˆ๋Š” ์ดํŽ™ํŠธ๋Š” ์•„๋‹ˆ์ง€๋งŒ, tGlow์™€ tDiffuse ์ƒ˜ํ”Œ๋Ÿฌ๊ฐ€ ๋ชจ๋‘ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‚ด๊ฐ€ ํ•œ ๊ฒƒ์€ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ๋ฟ์ž…๋‹ˆ๋‹ค (130 & 175 ํ–‰).
new THREE.RenderPass (scene, camera);
์™€
new THREE.RenderPass (glowscene, glowcamera);

๊ฝค ๋†€๋ž์Šต๋‹ˆ๋‹ค.

ํˆฌ๋ช…๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋ Œ๋”๋ง ๋Œ€์ƒ์— RGBA ํ˜•์‹์„ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

๊ธ€์Ž„์š”, ๋™์˜ ํ•ฉ๋‹ˆ๋‹ค๋งŒ, ๊ธ€๋กœ์šฐ ํŒจ์Šค๊ฐ€ ๊ฒ€์ •์— ํฐ์ƒ‰์„ ๋ Œ๋”๋งํ•˜๊ณ  ๋””ํ“จ์ฆˆ ํŒจ์Šค๊ฐ€ ์ž˜ ... ๊ฒ€์ •์— ๋””ํ“จ์ฆˆ๋ฅผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํˆฌ๋ช…๋„๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํˆฌ๋ช…์„ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š๋„๋ก ์ถ”๊ฐ€๋กœ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜๋„ RT์˜ ํ˜•์‹์„ RGBA๋กœ ๋ณ€๊ฒฝํ–ˆ์ง€๋งŒ ์•„๋ฌด๊ฒƒ๋„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ด์ƒํ•œ ๋ฌธ์ œ๋Š” ๋‚ด glowscene / glowcamera RenderPass๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋™์•ˆ ๋‚ด ์žฅ๋ฉด / ์นด๋ฉ”๋ผ RenderPass๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ ๋‚ด glowscene / glowcamera RenderPass๊ฐ€ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ „์— ๋‚ด ์žฅ๋ฉด / ์นด๋ฉ”๋ผ RenderPass๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ , ๋‹ค๋ฅธ ์žฌ๋ฃŒ์— ๋Œ€ํ•œ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ๊ณต์œ  ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค (# 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).

๋„ˆ๋ฌด ๋งŽ์€ ์งˆ๋ฌธ์„ํ•ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ์ง€๋งŒ ์•„๋ฌด ์†Œ์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค ..

EDIT2

์‚ฌ์‹ค์€

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

๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ข‹์€;)

๋˜๋Š” ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ๋ณต์ œ ๋Œ€์‹  ๋” ์ €๋ ดํ•œ ๋‹ค๋ฅธ ์˜ต์…˜์€ ๋” ์œ ์‚ฌํ•œ ์žฌ์งˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค (๋‘ ํŒจ์Šค์˜ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ์— ๋™์ผํ•œ ๋ฒ„ํผ๊ฐ€ ํ•„์š”ํ•จ).

์ด ๊ฒฝ์šฐ ๊ธ€๋กœ์šฐ ํŒจ์Šค์— ๊ธฐ๋ณธ ์žฌ์งˆ์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ์ฃผ๋ณ€ ์กฐ๋ช… ๋งŒ ์‚ฌ์šฉํ•˜์—ฌ ํ™•์‚ฐ ์กฐ๋ช…์ด 0 ์ธ Lambert ์žฌ์งˆ์„ ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฐ™์€:

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 ํŒจ์Šค๊ฐ€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ์ข… ํŒจ์Šค๋Š” ๋ชจ๋ธ ๋งŒ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. "tadd"ํ…์Šค์ฒ˜ ์ฑ„๋„์— ๋Œ€ํ•œ oclcomposer ์ถœ๋ ฅ์€ ๋ณ„๋„์˜ Effect Composer๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค !! renderer.PreserveDrawingBuffer = true๋กœ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. autoclear๋ฅผ false๋กœ ์„ค์ •ํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ ๊ทธ๊ฒŒ ์•„๋‹™๋‹ˆ๋‹ค.

์ตœ์ข… ์ž‘๊ณก๊ฐ€ ์ดํ›„์— oclcomposer๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  godray๊ฐ€ ํ™”๋ฉด์— ์ถœ๋ ฅ์„ ์ „๋‹ฌํ•˜๋ฉด godray๋Š” ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ชจ๋ธ์€ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

oclcomposer ์ถœ๋ ฅ์„ ์ตœ์ข… ํŒจ์Šค์—์„œ tadd ์ฑ„๋„๋กœ ๋ณด๋‚ด๋Š” ๋Œ€์‹  MeshBasicMaterial๋กœ ํŒŒ์ดํ”„ํ•˜๊ณ  ํ…์Šค์ฒ˜ ์ฟผ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฉ”์ธ ์žฅ๋ฉด์— ์ถ”๊ฐ€ํ•˜๋ฉด ์ด์ œ ๋ชจ๋ธ๊ณผ Godrays (ํ‰๋ฉด์—์„œ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ํšจ๊ณผ์ด์ง€๋งŒ ํ…์Šค์ฒ˜ ํŒŒ์ดํ•‘์ด ์ž‘๋™ํ•˜๊ณ  ์žˆ์Œ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

// 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 = new THREE.RenderPass (g_occlusion_buffer, g_occlusion_camera);

์›๋ž˜ ๋ฐ๋ชจ ๊ฐ€ ๋” ์ด์ƒ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

FWIW ์—ฌ๊ธฐ์—์„œ Additive Blend (Three.js v79 ์‚ฌ์šฉ)๋ฅผ ํ†ตํ•ด FX๋ฅผ ์„ ํƒ์ ์œผ๋กœ ์ ์šฉํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ๋ชจ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค : https://www.airtightinteractive.com/demos/selective-fx/

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰