WebGL笔记:WebGL中JS与GLSL ES 语言通信,着色器间的数据传输示例:用鼠标控制点位

用鼠标控制点位

<canvas id="canvas">canvas>


<script id="vertexShader" type="x-shader/x-vertex">
  attribute vec4 a_Position;
  void main() {
      // 点位
      gl_Position = a_Position;
      // 尺寸
      gl_PointSize = 50.0;
  }
script>


<script id="fragmentShader" type="x-shader/x-fragment">
    void main() {
        gl_FragColor = vec4(1,1,0,1);
    }
  script>

<script type="module">
  import { initShaders } from "./utils.js";

  const canvas = document.querySelector("#canvas");
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  // 获取着色器文本
  const vsSource = document.querySelector("#vertexShader").innerText;
  const fsSource = document.querySelector("#fragmentShader").innerText;

  // 三维画笔
  const gl = canvas.getContext("webgl");

  // 初始化着色器
  initShaders(gl, vsSource, fsSource);

  // 设置attribute 变量
  const a_Position = gl.getAttribLocation(gl.program, "a_Position");

  gl.vertexAttrib1f(a_Position, 0.1);

  // 声明颜色 rgba
  gl.clearColor(0, 0, 0, 1);
  // 刷底色
  gl.clear(gl.COLOR_BUFFER_BIT);

  // 绘制顶点
  gl.drawArrays(gl.POINTS, 0, 1);

  // 鼠标点击事件
  canvas.addEventListener("click", ({ clientX, clientY }) => {
    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,
    ];
    // 解决y 方向的差异
    const yBaseCenterTop = -yBaseCenter;
    // 解决坐标基底的差异
    const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight];

    gl.vertexAttrib2f(a_Position, x, y);
    // gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.POINTS, 0, 1);
  });
script>

utils.js

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;
  return true;
}

function loadShader(gl, type, source) {
  // 根据着色类型,建立着色器对象
  const shader = gl.createShader(type);
  // 将着色器源文件传入着色器对象中
  gl.shaderSource(shader, source);
  // 编译着色器对象
  gl.compileShader(shader);
  // 返回着色器对象
  return shader;
}
  • 这里核心点主要在: canvas坐标系和webgl坐标系之间的差异,由此计算出鼠标在webgl坐标系中的位置,并且控制点的位置

两者坐标系的核心算法

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
];
// 解决y 方向的差异
const yBaseCenterTop = -yBaseCenter;
// 解决坐标基底的差异
const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight];
  • 这里最终的 x, y 就是鼠标在canvas画布上,webgl坐标系下的位置信息
  • 参考:https://blog.csdn.net/Tyro_java/article/details/133023988

你可能感兴趣的:(Canvas,Webgl,Three.js,webgl,着色器)