Skip to content
This repository has been archived by the owner on Apr 5, 2023. It is now read-only.

Add mask layers #33

Open
supermoos opened this issue Apr 29, 2022 · 7 comments
Open

Add mask layers #33

supermoos opened this issue Apr 29, 2022 · 7 comments
Labels
enhancement New feature or request

Comments

@supermoos
Copy link

supermoos commented Apr 29, 2022

Hi, is it possible to make a layer that's last in line in the fragment shader renderer. The reason I ask is because I'm trying to create a an AlphaGradient Layer, essentially the same as the Gradient layer, except it works as a "mask" for the whole object, so you should be able to use it to fade out an object selectively using the same params as you use to control the Gradient Layer.

Here's a test were I just tried hardcoding the alpha value to be 0.0 to make it invisible, however this quick test revealed that the alpha value doesn't seem to propegate / override the main material?

import { Abstract } from 'lamina/vanilla'

export default class AlphaGradient extends Abstract {
  static u_colorA = 'white'
  static u_colorB = 'black'
  static u_alpha = 1

  static u_start = 1
  static u_end = -1
  static u_contrast = 1

  static vertexShader = `
		varying vec3 v_position;

		vod main() {
      v_position = lamina_mapping_template;
		}
  `

  static fragmentShader = `
    uniform vec3 u_colorA;
    uniform vec3 u_colorB;
    uniform vec3 u_axis;
    uniform float u_alpha;
    uniform float u_start;
    uniform float u_end;
    uniform float u_contrast;

		varying vec3 v_position;

    void main() {

      float f_step = smoothstep(u_start, u_end, v_position.axes_template * u_contrast);
      vec3 f_color = mix(u_colorA, u_colorB, f_step);

      return vec4(f_color, 0.0);
    }
  `

  axes: 'x' | 'y' | 'z' = 'x'
  mapping: 'local' | 'world' | 'uv' = 'local'

  constructor(props?) {
    super(
      AlphaGradient,
      {
        name: 'AlphaGradient',
        ...props,
      },
      (self: AlphaGradient) => {
        self.schema.push({
          value: self.axes,
          label: 'axes',
          options: ['x', 'y', 'z'],
        })

        self.schema.push({
          value: self.mapping,
          label: 'mapping',
          options: ['uv', 'world', 'local'],
        })

        const mapping = AlphaGradient.getMapping(self.mapping)

        self.vertexShader = self.vertexShader.replace('lamina_mapping_template', mapping || 'local')
        self.fragmentShader = self.fragmentShader.replace('axes_template', self.axes || 'x')
      }
    )
  }

  private static getMapping(type?: string) {
    switch (type) {
      default:
      case 'local':
        return `position`
      case 'world':
        return `(modelMatrix * vec4(position,1.0)).xyz`
      case 'uv':
        return `vec3(uv, 0.)`
    }
  }
}
@FarazzShaikh
Copy link
Member

Nope the alpha for all layers along with the base material must be <0 for the overall material to be transparent. Masking is currently not supported. PRs are welcome though 😊

@FarazzShaikh FarazzShaikh changed the title AlphaGradient Layer? Add mask layers Apr 29, 2022
@FarazzShaikh FarazzShaikh added the enhancement New feature or request label Apr 29, 2022
@supermoos
Copy link
Author

Got it! do you mean <1 ?

@FarazzShaikh
Copy link
Member

Ah yes sorry! <1 Oops 😅

@supermoos
Copy link
Author

Could you give me a pointer on how to start something like an override layer, i.e. a layer that runs last in the shader and can modify the final color output?

@FarazzShaikh
Copy link
Member

FarazzShaikh commented Apr 29, 2022

For a layer to appear last it needs to be composed laast in the layer stack.

In react:

<LayerMaterial>
    { /* Some other layers */ }
    <YourLastLayer />
</LayerMaterial>

In vanialla:

new LayerMaterial({
    layers: [
        // Some other layers
        new YourLastLayer()
    ]
})

With the nomal blend mode, the last layer will override all the previous ones

@supermoos
Copy link
Author

Right, but it only overrides the previous layers right, not the basematerial or did I miss something?

@FarazzShaikh
Copy link
Member

If you use the basic (default) lighting mode then yeah it will override the base material. In other lighting modes there's shading, so you can think of it only overriding the Diffuse color.

Please reach out on the pmndrs discord for discussions/questions. Link is in the readme

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants