欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > webgl-插值渲染原理理解

webgl-插值渲染原理理解

2024/10/25 6:33:24 来源:https://blog.csdn.net/hr_beginner/article/details/141883687  浏览:    关键词: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>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com