WebGL 绘制矩形

上一节绘制了圆点,调用的绘制方法如下:gl.drawArrays(gl.POINTS, 0, 1);   第一个参数明显是个枚举类型,肯定还有其他值,如下所示:

  • POINTS 可视的点
  • LINES 单独线段
  • LINE_STRIP 线条
  • LINE_LOOP 闭合线条
  • TRIANGLES 单独三角形
  • TRIANGLE_STRIP 三角带
  • TRIANGLE_FAN 三角扇

这小节尝试一下 绘制单独线段、线条、闭合线条、三角带(可构成矩形)

代码如下所示:

<template>
  <div class="wrapper">
    <div class="point-wrapper">
      <div style="margin-bottom: 20px">绘制点</div>
      <canvas id="point" width="280" height="250"></canvas>
    </div>
    <div class="point-mouse">
      <div style="margin-bottom: 20px">鼠标绘制点</div>
      <canvas id="pointByMouse" width="280" height="250"></canvas>
    </div>
  </div>
</template>

<script>
export default {
  name: "point",
};
</script>


<script setup>
import { onMounted } from "vue";
import { initShaders } from "@/utils/myGL.js";

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute float a_PointSize;
void main() {
 gl_Position = a_Position;
 gl_PointSize = a_PointSize;
}
`;

const fragmentShaderSrc = `
precision mediump float;
uniform vec4 u_FragColor;
void main() {
  gl_FragColor = u_FragColor;
}
`;

const fragmentShaderSrcCircle = `
precision mediump float;
void main() {
  float d = distance(gl_PointCoord, vec2(0.5, 0.5));
  if(d < 0.5) {
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
  } else { 
    discard; 
  }
}
`;

const drawPointStatic = () => {
  const canvas = document.getElementById("point");
  // webgl画笔
  const gl = canvas.getContext("webgl");
  // 初始化着色器
  initShaders(gl, vertexShaderSrc, fragmentShaderSrc);
  const a_position = gl.getAttribLocation(gl.program, "a_Position");
  const a_pointSize = gl.getAttribLocation(gl.program, "a_PointSize");
  const u_FragColor = gl.getUniformLocation(gl.program, "u_FragColor");
  gl.vertexAttrib3f(a_position, 0, 0.0, 0.0);
  gl.vertexAttrib1f(a_pointSize, 20.0);
  gl.uniform4f(u_FragColor, 1.0, 0.0, 0.0, 1.0);
  // 指定将要用来清理绘图区的颜色
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // 清理绘图区
  gl.clear(gl.COLOR_BUFFER_BIT);
  // 绘制顶点
  gl.drawArrays(gl.POINTS, 0, 1);
  setTimeout(() => {
    initShaders(gl, vertexShaderSrc, fragmentShaderSrcCircle);
    // 指定将要用来清理绘图区的颜色
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    // 清理绘图区
    gl.clear(gl.COLOR_BUFFER_BIT);
    // 绘制顶点
    gl.drawArrays(gl.POINTS, 0, 1);
  }, 2000);
};

const drawPointByMouse = () => {
  const canvas = document.getElementById("pointByMouse");
  // webgl画笔
  const gl = canvas.getContext("webgl");
  // 初始化着色器
  initShaders(gl, vertexShaderSrc, fragmentShaderSrc);
  // // 指定将要用来清理绘图区的颜色
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // // 清理绘图区
  gl.clear(gl.COLOR_BUFFER_BIT);
  let pointArrs = [];
  document.addEventListener("click", (event) => {
    const { clientX, clientY } = event;
    const { left, top, width, height } = canvas.getBoundingClientRect();
    const [cssX, cssY] = [clientX - left, clientY - top];
    const [halfWidth, halfHeight] = [width / 2, height / 2];
    const [xBaseCenter, yBaseCenter] = [cssX - halfWidth, cssY - halfHeight];
    const yBaseCenterTop = -yBaseCenter;
    const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight];
    const a_Position = gl.getAttribLocation(gl.program, "a_Position");
    const a_pointSize = gl.getAttribLocation(gl.program, "a_PointSize");
    const u_FragColor = gl.getUniformLocation(gl.program, "u_FragColor");
    pointArrs.push({
      x,
      y,
      z: Math.random() * 50,
      color: {
        r: Math.random() * 1,
        g: Math.random() * 1,
        b: Math.random() * 1,
      },
    });
    gl.clear(gl.COLOR_BUFFER_BIT);
    pointArrs.forEach((item) => {
      gl.vertexAttrib2f(a_Position, item.x, item.y);
      gl.vertexAttrib1f(a_pointSize, item.z);
      gl.uniform4f(u_FragColor, item.color.r, item.color.g, item.color.b, 1.0);
      gl.drawArrays(gl.POINTS, 0, 1);
    });
  });
};
onMounted(() => {
  drawPointStatic();
  drawPointByMouse();
});
</script>

<style lang="scss" scoped>
.wrapper {
  display: flex;
}
.point-wrapper {
  width: 300px;
  height: 300px;
  background-color: gray;
}
.point-mouse {
  margin-left: 20px;
  width: 300px;
  height: 300px;
  background-color: gray;
}
</style>

绘制图形如下所示:

注意在代码中引入了initShaders  方法,如下:

function loadShader(gl, type, source) {
  //根据着色类型,建立着色器对象
  const shader = gl.createShader(type);
  //将着色器源文件传入着色器对象中
  gl.shaderSource(shader, source);
  //编译着色器对象
  gl.compileShader(shader);
  //返回着色器对象
  return shader;
}
export function initShaders(gl, vsSource, fsSource) {
  //创建程序对象
  const program = gl.createProgram();
  //建立着色对象
  const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
  const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
  //把顶点着色对象装进程序对象中
  gl.attachShader(program, vertexShader);
  //把片元着色对象装进程序对象中
  gl.attachShader(program, fragmentShader);
  //连接webgl上下文对象和程序对象
  gl.linkProgram(program);
  //启动程序对象
  gl.useProgram(program);
  //将程序对象挂到上下文对象上
  gl.program = program;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值