Skip to content

how to use StencilTest #150

Description

@ruofeng618

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

Activity

  1. ruofeng618 commented on Nov 27, 2021

    @ruofeng618
    Author

    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);
      }
    `;
    
  2. kainino0x commented on Mar 5, 2024

    @kainino0x
    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions