Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to use StencilTest #150

Open
ruofeng618 opened this issue Nov 25, 2021 · 2 comments
Open

how to use StencilTest #150

ruofeng618 opened this issue Nov 25, 2021 · 2 comments
Labels
sample request Request for a new sample

Comments

@ruofeng618
Copy link

A simple demo can be provided?
I tried it, but it didn't work
``

@ruofeng618
Copy link
Author

ruofeng618 commented Nov 27, 2021

a simple demo

async function init() {
  const gpu = navigator.gpu; 
  const adapter = await gpu.requestAdapter();
  const device = await adapter.requestDevice();
  
  const cvs = document.createElement('canvas');
  cvs.width = 1024;
  cvs.height = 768;
  document.body.appendChild(cvs);
  const depthTexture = device.createTexture({
    size: {
      width: cvs.width,
      height: cvs.height,
      depthOrArrayLayers: 1
    },
    format: "depth24plus-stencil8",
    usage: GPUTextureUsage.RENDER_ATTACHMENT
  });
  const ctx = cvs.getContext('webgpu');
  const swapChainFormat = "bgra8unorm";
  const presentationFormat = ctx.getPreferredFormat(adapter);
  ctx.configure({
    device: device,
    format: swapChainFormat
  });
  let data=new Float32Array(
    [
      -1.0, -1.0, 0.0, 1.0,
      0.0, 1.0, 0.0, 1.0,
      1.0, -1.0, 0.0, 1.0
    ]);
  let vertexBuffer = device.createBuffer({
    size: data.byteLength,
    usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
  });
  device.queue.writeBuffer(vertexBuffer, 0, data);
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  const uniformsBindGroupLayout = device.createBindGroupLayout({
    entries: [
      {
        binding: 0,
        visibility: GPUShaderStage.VERTEX,

        buffer: {
          type: 'uniform',
        },
      }
    ]
  });
  const uniformsBindGroupLayout1 = device.createBindGroupLayout({
    entries: [
      {
        binding: 0,
        visibility: GPUShaderStage.VERTEX,

        buffer: {
          type: 'uniform',
        },
      }
    ]
  });
  const matrixSize = 16 * Float32Array.BYTES_PER_ELEMENT; // 4x4 matrix
  const uniformBufferSize = matrixSize ;

  const uniformBuffer = device.createBuffer({
    size: uniformBufferSize,
    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
  });
  const uniformBuffer1 = device.createBuffer({
    size: uniformBufferSize,
    usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
  });
  const uniformBindGroup = device.createBindGroup({
    layout: uniformsBindGroupLayout,
    entries: [
      {
        binding: 0,
        resource: {
          buffer: uniformBuffer,
          offset: 0,
          size: uniformBufferSize
        }
      }
    ]
  });
  const uniformBindGroup1 = device.createBindGroup({
    layout: uniformsBindGroupLayout1,
    entries: [
      {
        binding: 0,
        resource: {
          buffer: uniformBuffer1,
          offset: 0,
          size: uniformBufferSize
        }
      }
    ]
  });

  const pipelineWriteMask = device.createRenderPipeline({
    layout: device.createPipelineLayout({bindGroupLayouts: [uniformsBindGroupLayout]}),
    vertex: {
      module:  device.createShaderModule({
        code: basicVertWGSL,
      }),
      entryPoint: 'main',
      buffers: [
        {
          arrayStride: 4 * 4,
          attributes: [
            {
              // position
              shaderLocation: 0,
              offset: 0,
              format: "float32x4"
            }
          ]
        }
      ]
    },
    fragment: {
      module: device.createShaderModule({
        code: basicFragWGSL,
      }),
      entryPoint: 'main',
      targets: [
        {
          format: presentationFormat,
          writeMask:0x00,//关闭color写入
        },
      ],
    },
    primitive: {
      topology: 'triangle-list',
    },
    depthStencil: {
      depthWriteEnabled: true,
      depthCompare: "always",
      format: "depth24plus-stencil8",
      stencilFront:{
          compare:"always",
          failOp:"keep",
          depthFailOp:"keep",
          passOp:"replace",
      },
        stencilBack:{
          compare:"always",
          failOp:"keep",
          depthFailOp:"keep",
          passOp:"replace",
        },
      },
  });
  const pipelineUseMask = device.createRenderPipeline({
    layout: device.createPipelineLayout({bindGroupLayouts: [uniformsBindGroupLayout1]}),
    vertex: {
      module: device.createShaderModule({
        code: basicVertWGSL,
      }),
      entryPoint: 'main',
      buffers: [
        {
          arrayStride: 4 * 4,
          attributes: [
            {
              // position
              shaderLocation: 0,
              offset: 0,
              format: "float32x4"
            }
          ]
        }
      ]
    },
    fragment: {
      module: device.createShaderModule({
        code: basicFragWGSL,
      }),
      entryPoint: 'main',
      targets: [
        {
          format: presentationFormat,
        },
      ],
    },
    primitive: {
      topology: 'triangle-list',
    },
    depthStencil: {
      depthWriteEnabled: false,
      depthCompare: "always",
      format: "depth24plus-stencil8",
      stencilFront:{
          compare: "equal",
      },
        stencilBack:{
          compare:"equal",
        },
      },
  });
  let modelMatrix = mat4.create();
  let modelMatrix1 = mat4.create();
  let render = async function () {
    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginRenderPass({
      colorAttachments: [{
        view:  ctx.getCurrentTexture().createView(),
        loadValue: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
      }],
      depthStencilAttachment: {
        view: depthTexture.createView(),
        depthLoadValue: 0.0,
        depthStoreOp: "store",
        stencilLoadValue: 0.0,
        stencilStoreOp: "store",
      }
    });
    /*******************第一次渲染**********************/
    passEncoder.setVertexBuffer(0, vertexBuffer);
    passEncoder.setPipeline(pipelineWriteMask);
    mat4.identity(modelMatrix);
    mat4.scale(modelMatrix, modelMatrix, [-0.2,-0.2, 1]);
    passEncoder.setBindGroup(0, uniformBindGroup);
    //将三角区域模板值写入1
    passEncoder.setStencilReference(1)
    device.queue.writeBuffer(uniformBuffer, 0, modelMatrix);
    passEncoder.draw(3, 1, 0, 0);
    /****************第二次渲染********************/
    mat4.identity(modelMatrix1);
    mat4.scale(modelMatrix1, modelMatrix1, [0.6,0.6, 1]);
    passEncoder.setVertexBuffer(0, vertexBuffer);
    passEncoder.setPipeline(pipelineUseMask);
    passEncoder.setBindGroup(0,uniformBindGroup1);
    //渲染模板值等于0的区域
    passEncoder.setStencilReference(0)
    device.queue.writeBuffer(uniformBuffer1, 0, modelMatrix1);
    passEncoder.draw(3, 1, 0, 0);

     passEncoder.endPass();
    const test = commandEncoder.finish();
    device.queue.submit([test]);
  };
  render();
}
init()
const basicVertWGSL = `
  [[block]] struct Uniforms {
    modelMatrix : mat4x4<f32>;
  };
  [[binding(0), group(0)]] var<uniform> uniforms : Uniforms;
  
  struct VertexOutput {
    [[builtin(position)]] Position : vec4<f32>;
  };
  
  [[stage(vertex)]]
  fn main([[location(0)]] position : vec4<f32>) -> VertexOutput {
    var output : VertexOutput;
    output.Position = uniforms.modelMatrix * position;
    return output;
  }
	`;
const basicFragWGSL = `
  [[stage(fragment)]]
  fn main() -> [[location(0)]] vec4<f32> {
    return vec4<f32>(1.0, 0.0, 0.0, 1.0);
  }
`;

@kainino0x kainino0x added the sample request Request for a new sample label Mar 5, 2024
@kainino0x
Copy link
Collaborator

I think Dawn used to have a sample that used stencil testing to render a reflective floor?
Something like that would make a good sample.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sample request Request for a new sample
Projects
None yet
Development

No branches or pull requests

2 participants