当前位置: 首页 > news >正文

webgl-插值渲染原理理解

  • 问题背景
  • 解决思路
  • demo案例效果
  • 矩阵转换--GLSL着色程序
  • index.vue

问题背景

需要用webgl 优化 kriging.grid 物理计算量大的问题
在这里插入图片描述

解决思路

借助 GPU 的性能,采用 webgl 替代克里金的计算量大的方法

demo案例效果

矩阵转换–GLSL着色程序

注意glsl语句

void main() {// 将位置和矩阵相乘gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);// 从裁减空间转换到颜色空间// 裁减空间范围 -1.0 到 +1.0// 颜色空间范围 0.0 到 1.0  RGBAv_color = gl_Position * 0.5 + 0.5;// 实现 b 固定为0.5 ,a 固定为 1// v_color = vec4(gl_Position.x * 0.5 + 0.5,gl_Position.y * 0.5 + 0.5,0,1); // 改成b固定为0,a固定为 1  实现 越往上 g 越大,越往右 r 越大}

让我们从上例的三个顶点开始分析

我们的给顶点着色器施加了一个包含平移,旋转和缩放的的矩阵,并将结果转换到裁剪空间。 默认平移,旋转和缩放值为:平移 = 200, 150旋转 = 0缩放 = 1,所以这里只进行了平移。 画布大小(背景缓冲)为 400×300,所以三个顶点在裁剪空间中为以下坐标值。

写入 gl_Position 的值
在这里插入图片描述
同时将这些值转换到颜色空间中赋给我们定义的可变量v_color。
写入 v_color 的值
在这里插入图片描述
注意:这个怎么来的呢
在这里插入图片描述
利用这三个值进行插值后传进每个像素运行的片段着色器中。
在这里插入图片描述

index.vue

<!--/**
* @author: liuk
* @date: 2024-09-04
* @describe:webgl 工作原理
*/-->
<template><div class="workingPrinciple1-box"><div class="block"><el-form-item label="x:" label-width="50"><el-slider v-model="translationx" :max="gl.canvas.width" @change="drawScene"/></el-form-item><el-form-item label="y:" label-width="50"><el-slider v-model="translationy" :max="gl.canvas.height" @change="drawScene"/></el-form-item><el-form-item label="angle:" label-width="50"><el-slider v-model="angleInRadians"  :max="360"  @change="drawScene"/></el-form-item><el-form-item label="scalex:" label-width="50"><el-slider v-model="scalex" :min="-5" :max="5" :step="0.01" @change="drawScene"/></el-form-item><el-form-item label="scaley:" label-width="50"><el-slider v-model="scaley" :min="-5" :max="5" :step="0.01" @change="drawScene"/></el-form-item></div></div></template><script lang="ts" setup>
import {useWebglDemoStore} from "@/store/modules/webglDemo";
import {onBeforeUnmount, onMounted, reactive, toRefs} from "vue";
import m3 from "@/utils/m3.js"const model = reactive({translationx: 200,translationy:150,angleInRadians: 0,scalex: 1,scaley: 1,
})
const {translationx, translationy, angleInRadians, scalex, scaley} = toRefs(model)const webglDemoStore = useWebglDemoStore()
const gl = webglDemoStore.gl/*
* 概念:
* WebGL在GPU上的工作基本上分为两部分
* 1.将顶点(或数据流)转换到裁剪空间坐标
* 2.基于第一部分的结果绘制像素点 - ”光栅化“
* */onMounted(() => {init()
})onBeforeUnmount(() => {gl.clearColor(0, 0, 0, 0);gl.clear(gl.COLOR_BUFFER_BIT);
})// 初始化
let program, positionBuffer, positionAttributeLocation, matrixLocation
const init = () => {// 创建两个着色器const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);// 创建着色程序program = createProgram(gl, vertexShader, fragmentShader)// 从刚才创建的GLSL着色程序中找到 a_position 属性值所在的位置positionAttributeLocation = gl.getAttribLocation(program, "a_position");gl.enableVertexAttribArray(positionAttributeLocation);// 全局变量所在的位置matrixLocation = gl.getUniformLocation(program, "u_matrix");// 创建缓冲positionBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);// 三个二维点坐标,把 gl.bufferData 复制这些数据到GPU的 positionBuffer 对象上const positions = [0, -100, 150, 125, -175, 100];gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);drawScene()
}// 创建GLSL字符串 - 多行模板文字方式
const vertexShaderSource = `attribute vec2 a_position;uniform mat3 u_matrix;varying vec4 v_color;void main() {// 将位置和矩阵相乘gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);// 从裁减空间转换到颜色空间// 裁减空间范围 -1.0 到 +1.0// 颜色空间范围 0.0 到 1.0  RGBA// v_color = gl_Position * 0.5 + 0.5;// 实现 b 固定为0.5 ,a 固定为 1v_color = vec4(gl_Position.x * 0.5 + 0.5,gl_Position.y * 0.5 + 0.5,0,1); // 改成b固定为0,a固定为 1  实现 越往上 g 越大,越往右 r 越大}
`
const fragmentShaderSource = `precision mediump float;varying vec4 v_color;void main() {gl_FragColor = v_color;}
`// 创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
const createShader = (gl, type, source) => {const shader = gl.createShader(type); // 创建着色器对象gl.shaderSource(shader, source); // 提供数据源gl.compileShader(shader); // 编译 -> 生成着色器const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);if (success) {return shader;}console.warn(gl.getShaderInfoLog(shader));gl.deleteShader(shader);
}// 创建着色程序,将这两个着色器 link(链接)到一个 program(着色程序)
const createProgram = (gl, vertexShader, fragmentShader) => {const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);const success = gl.getProgramParameter(program, gl.LINK_STATUS);if (success) {return program;}console.warn(gl.getProgramInfoLog(program));gl.deleteProgram(program);
}const drawScene = () => { // 渲染// 调整 canvas 尺寸gl.canvas.width = gl.canvas.clientWidth;gl.canvas.height = gl.canvas.clientHeight;// 渲染gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);// 清空画布gl.clearColor(0, 0, 0, 0);gl.clear(gl.COLOR_BUFFER_BIT);// 告诉它用我们之前写好的着色程序(一个着色器对)gl.useProgram(program);gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);// 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)const size = 2;          // 每次迭代运行提取两个单位数据const type = gl.FLOAT;   // 每个单位的数据类型是32位浮点型const normalize = false; // 不需要归一化数据const stride = 0;        // 0 = 移动单位数量 * 每个单位占用内存(sizeof(type))// 每次迭代运行运动多少内存到下一个数据开始点const offset = 0;        // 从缓冲起始位置开始读取gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset)// Compute the matrixconsole.log(model.translationx, model.translationy)var matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);matrix = m3.translate(matrix, model.translationx, model.translationy);matrix = m3.rotate(matrix, model.angleInRadians);matrix = m3.scale(matrix, model.scalex, model.scaley);// Set the matrix.gl.uniformMatrix3fv(matrixLocation, false, matrix);// WebGL运行我们的GLSL着色程序const primitiveType = gl.TRIANGLES; //图元类型const offset1 = 0;const count = 3; // 顶点着色器将运行三次gl.drawArrays(primitiveType, offset1, count);
}</script><style lang="scss" scoped>
.workingPrinciple1-box {position: absolute;right: 20px;top: 80px;width: 250px;padding: 10px;box-sizing: border-box;background: #ccc;
}:deep(.el-form-item) {margin-bottom: 0;.el-form-item__label {color: #000 !important;}
}
</style>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • YC教父的创始人模式VS职业经理人模式:AI时代的独立开发者崛起
  • 4-1.Android Camera 之 CameraInfo 编码模板(前后置摄像头理解、摄像头图像的自然方向理解)
  • SpringBoot和Mybatis框架怎么防止SQL注入
  • Hystrix-熔断原理分析
  • [论文笔记]Dimensionality Reduction by Learning an Invariant Mapping
  • 828华为云征文|基于华为云Flexus云服务器X搭建jumpserver堡垒机软件
  • vue3 el-menu 菜单Maximum recursive updates exceeded 报错
  • qt事件过滤器
  • 《机器学习》数据预处理 删除、替换、填充 案例解析及实现
  • zabbix6.4连接钉钉发出警告
  • 【计算机网络】TCP协议(下)
  • 基于stm32f407的pwm输出以及初始化(84mhz)
  • 电影、视频拍摄基础知识 | 所有岗位及职能描述、任职要求速览
  • LC1860C 后来怎么样了
  • 浅谈人工智能之python调用通义千问API
  • [Vue CLI 3] 配置解析之 css.extract
  • Asm.js的简单介绍
  • chrome扩展demo1-小时钟
  • Docker: 容器互访的三种方式
  • ES2017异步函数现已正式可用
  • ES6 学习笔记(一)let,const和解构赋值
  • JDK 6和JDK 7中的substring()方法
  • Map集合、散列表、红黑树介绍
  • mongo索引构建
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 番外篇1:在Windows环境下安装JDK
  • 每天10道Java面试题,跟我走,offer有!
  • 普通函数和构造函数的区别
  • 数组的操作
  • 赢得Docker挑战最佳实践
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • ​iOS实时查看App运行日志
  • ​软考-高级-系统架构设计师教程(清华第2版)【第1章-绪论-思维导图】​
  • # linux 中使用 visudo 命令,怎么保存退出?
  • ###C语言程序设计-----C语言学习(6)#
  • #FPGA(基础知识)
  • #Linux(帮助手册)
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (2015)JS ES6 必知的十个 特性
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (done) 两个矩阵 “相似” 是什么意思?
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (pojstep1.1.2)2654(直叙式模拟)
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (一)插入排序
  • (转)编辑寄语:因为爱心,所以美丽
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net Application的目录
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .NET中winform传递参数至Url并获得返回值或文件