# TSL: Using the output of \`pass()\` in \`.colorNode\` in screen space

**URL:** <https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178>\
**Category:** Questions\
**Tags:** textures, materials, shaders\
**Created:** [July 14, 2025, 8:29pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178 "2025-07-14T20:29:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 14, 2025, 8:29pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/1 "2025-07-14T20:29:47Z")

</div>

I’m trying to do a screen space effect using a custom material. I want the logo on the sphere in screen space, not mapped to the UVs of the model. I can do a screen space effect with the material using the `screenUV` node (e.g. a vertical split) but I want to try and use the output of a render pass instead.

Here is a fiddle:

> **[TSL: Output of pass node into screen space - JSFiddle - Code Playground](https://jsfiddle.net/ys618dqx/)**
>
> JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.

```javascript
 material.colorNode = Fn(() => {
        // This works, a screen space effect
        // const maskVal = step(0.5, screenUV.x);

        // This doesn't work, why can't i use the texture in screen space?
        // const maskVal = maskScenePass.getTextureNode().sample(screenUV).r
        
        // Using the pass like this works, but its mapped to the geometry
        const maskVal = maskScenePass.r;
        return mix(color(1,0,0), color(0,1,0), maskVal);
    })()

```

Is it possible to do this sort of thing or is this just fundamentally the wrong way to do it? Should I be using postprocessing instead? The fact that I can get the texture data onto the material makes me feel like there is a way to do this?

---

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 15, 2025, 6:57am UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/2 "2025-07-15T06:57:34Z")

</div>

@sunag, any insights here? Thanks!

---

<div class="post-metadata">

**Author:** ![sunag](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sunag/32/29472_2.png) [@sunag](https://discourse.threejs.org/u/sunag)\
**Post date:** [July 15, 2025, 3:26pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/3 "2025-07-15T15:26:44Z")

</div>

I think that with `viewportSharedTexture()` it is easier and more performant because it does not need multiple passes, it will obtain the texture of what has already been rendered.

```js
const material = new THREE.NodeMaterial();
const customUV = screenUV.add( .1 ); /* add here your distortion effect, simple .1 offset to test*/
material.colorNode = viewportSharedTexture( customUV ).rgb;
material.transparent = true; // important to render-order

```

---

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 15, 2025, 7:33pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/4 "2025-07-15T19:33:59Z")

</div>

Nice, that’s working, thanks. Although for my actual use case I’m working with a more complicated scene where I may not have so much control over render order of the scene and this neat solution may not always apply. I’m also sometimes wanting to render the mask separately and not display the output in the scene. Do you have any idea why I can’t do something like this inside of `material.colorNode`?

```javascript
maskVal = maskScenePass.getTextureNode().sample(screenUV).r

```

---

<div class="post-metadata">

**Author:** ![sunag](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sunag/32/29472_2.png) [@sunag](https://discourse.threejs.org/u/sunag)\
**Post date:** [July 15, 2025, 7:54pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/5 "2025-07-15T19:54:57Z")

</div>

You can contextualize the UV, we prefer not to define at this time that it would be the `screenUV` because `pass()` could be used in the texture of a TV, for example. Try use:

```js
maskVal = maskScenePass.context( { getUV: () => screenUV } );

```

`maskScenePass.getTextureNode().sample(screenUV).r` It could be an alternative, I think the system should solve this, or could, but I need to check.

---

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 15, 2025, 7:59pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/6 "2025-07-15T19:59:28Z")

</div>

> [@sunag](#):
>
> ```javascript
> maskVal = maskScenePass.context( { getUV: () => screenUV } );
> 
> ```

Wow it works, thanks! I understand that the API is still not fully done and this might not be the way later on, but thanks again for giving me this little tip 😉

---

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 15, 2025, 8:01pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/7 "2025-07-15T20:01:06Z")

</div>

Updated fiddle:

> **[TSL: Output of pass node into screen space - JSFiddle - Code Playground](https://jsfiddle.net/b5d3c20x/)**
>
> JSFiddle - Test your JavaScript, CSS, HTML or CoffeeScript online with JSFiddle.

---

<div class="post-metadata">

**Author:** ![sunag](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/sunag/32/29472_2.png) [@sunag](https://discourse.threejs.org/u/sunag)\
**Post date:** [July 16, 2025, 3:49pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/8 "2025-07-16T15:49:22Z")

</div>

It has been fixed [here](https://github.com/mrdoob/three.js/pull/31431).  
If you wish to use your original approach 🙂

> <https://github.com/mrdoob/three.js/pull/31431>
>
> Related issue: https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-c…olornode-in-screen-space/85178/4
> 
> \*\*Description\*\*
> 
> Fix \`pass()\` build during \`sample()\` call using \`Mesh\`.
> 
> \`\`\`js
> // material
> const material = new THREE.NodeMaterial();
> 
> const maskScenePass = pass( maskScene, camera );
> 
> material.colorNode = Fn( () =\> {
> 
> const maskTexture = maskScenePass.getTextureNode();
> 
> const maskVal = maskTexture.sample( screenUV ).r
> 
> return mix( color( 1, 0, 0 ), color( 0, 1, 0 ), maskVal );
> 
> } )();
> 
> // mesh
> mesh = new THREE.Mesh( geometry, material );
> scene.add( mesh );
> \`\`\`

---

<div class="post-metadata">

**Author:** ![funwithtriangles](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/funwithtriangles/32/3938_2.png) [@funwithtriangles](https://discourse.threejs.org/u/funwithtriangles)\
**Post date:** [July 16, 2025, 9:12pm UTC](https://discourse.threejs.org/t/tsl-using-the-output-of-pass-in-colornode-in-screen-space/85178/9 "2025-07-16T21:12:47Z")

</div>

This is cool, thanks! I’ll give it a go for r179 and maybe even submit an example PR making use of it 😉
