# How to set texel invisible depending on a texture from another object

**URL:** <https://discourse.threejs.org/t/how-to-set-texel-invisible-depending-on-a-texture-from-another-object/33387>\
**Category:** Questions\
**Tags:** transparency, textures, shaders\
**Created:** [January 7, 2022, 5:37pm UTC](https://discourse.threejs.org/t/how-to-set-texel-invisible-depending-on-a-texture-from-another-object/33387 "2022-01-07T17:37:11Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![nwaucheul](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/nwaucheul/32/23320_2.png) [@nwaucheul](https://discourse.threejs.org/u/nwaucheul)\
**Post date:** [January 7, 2022, 5:37pm UTC](https://discourse.threejs.org/t/how-to-set-texel-invisible-depending-on-a-texture-from-another-object/33387/1 "2022-01-07T17:37:11Z")

</div>

Hello everyone,

**Introduction**

I wan’t to be able to create a sort of fog of war for my app using shaders. I feel that I might be close, but I cant figure out how to make it work… (maybe I don’t have the right approach all together lol, I hope not)

**Here is the context:**

- I have a plane that has a canvas texture. The user will be able to draw in black on this plane.  
We call it the “ **board** ”.

- I have objects that slide on this plane.  
We call them “ **tokens** ”.

**What I want:**

- I want to **set invisibe** the tokens once they are over a part of the board that is black.

- If the token is half in the black part, half in the non-black part, **only the part of the token over the black part will be invisible.**

**What I implemented so far**

Typescript part:

```javascript
// Create canvas element and color a half of it black, the other half transparent
this.FowCanvas = document.createElement('canvas');
this.fowContext = this.FowCanvas.getContext('2d');
this.fowContext.fillStyle = 'rgb(0, 0, 0)';
this.fowContext.fillRect(0, 0, this.FOWCanvas.width/2, this.FOWCanvas.height);

// Create board

const texture = new THREE.CanvasTexture(this.FowCanvas);

const material = new THREE.MeshBasicMaterial({
  map: texture,
  transparent: true
});

const board= new THREE.Mesh(
  new THREE.PlaneBufferGeometry(canvas.width / WORLD_UNIT, canvas.height / WORLD_UNIT),
  material
);

board.receiveShadow = false;
board.rotation.x = - Math.PI * 0.5;
board.position.y = BOARD_POSITION_Y; // this is like 0.05 for pixel fighting purposes

// Applying shader to my object's materials
token.traverse((object) => {
  const material = this.board.material as THREE.MeshBasicMaterial;
  if (object instanceof THREE.Mesh) {
    if (object.material instanceof Array) {
      for (let i = 0; i < object.material.length; i ++) {
        this.applyFOWShader(object.material[i], material.map);
      }
    } else {
      this.applyFOWShader(object.material, material.map);
    }
});

applyFOWShader(material, texture) {
  material.transparent = true;
  material.onBeforeCompile = (shader) => {
    fowShader(texture, shader);
  };
} 

```

Now, here is the actual shader

```javascript
const fowShader = (texture, shader) => {
  shader.uniforms.uTexture = texture;

  // Vertex Shader overwrite before Main() for uniforms and varyings declaration
  shader.vertexShader = shader.vertexShader.replace(
    '#include <common>',
    `
      #include <common>

      varying vec4 vFragPos;
      `
  );

  // Vertex Shader overwrite inside Main() for calculations
  shader.vertexShader = shader.vertexShader.replace(
    '#include <begin_vertex>',
    `
      #include <begin_vertex>
      vec4 vFragPos = modelMatrix * vec4(position, 1.0);
    `
  );

  // Fragment Shader before Main() for uniforms and varyings declaration
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <common>',
    `
      #include <common>
      uniform sampler2D uTexture;
      varying vec4 vFragPos;
      
      `
  );

  // Fragment Shader inside Main() for calculations
  shader.fragmentShader = shader.fragmentShader.replace(
    '#include <output_fragment>',
    `
      #ifdef OPAQUE
      diffuseColor.a = 1.0;
      #endif
      
      // https://github.com/mrdoob/three.js/pull/22425
      #ifdef USE_TRANSMISSION
      diffuseColor.a *= transmissionAlpha + 0.1;
      #endif

      vec4 texColor = texture2D(uTexture, vFragPos.xy);

    if (texColor.a != 0.0) {
      diffuseColor.a = 0.0;
    }

    gl_FragColor = vec4( outgoingLight, diffuseColor.a );
    `
  );
};

export default fowShader;

```

So there you go.

TLDR would be this

```javascript
vec4 texColor = texture2D(uTexture, vFragPos.xy);

      if (texColor.r == 0.0 && texColor.g == 0.0 && texColor.b == 0.0) {
        diffuseColor.a = 0.0;
      }

      gl_FragColor = vec4( outgoingLight, diffuseColor.a );

```

I try to get the texColor of my boardTexture at the position of my token.  
If this color is not transparent, then I want to have the color of my token transparent 100%.

**Some images to show the status**

 ![explanation](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/3X/b/0/b06e449d2fceeaeb3f52812ecee36ef811f72f50.jpeg)  
Note: the battlemap that you see next to the black can be ignored, it is the actual board with a battlemap and is not used in this context.

Note2: You can see that the canvas texture is well updated and visible on the scene. I think it is being sent to the shader without issue. So maybe the problem is in the shader itself? idk…

So there it is. I am quite new to threejs and shaders, so maybe all this does not make sense at all and maybe a better approach could be used…  
Right now I am hopeless!

Thank you for reading this! 🙂
