mfc图片控件显示图片_WebGL:显示图片

WebGL显示图片

简述

WebGL显示图片相对来说还是比较简单,跟Android,Python,IOS,C++等的用法都是差不多的,具体的opengl概念可以自己搜索。下面的介绍主要是基于Vue框架来设计做的Demo,不用vue的也可以简单的把代码移植过去。

开始做一个Demo

  • 首先需要Canvas,opengl都是基于Canvas来操作的, 宽高可以自己设定。

    <canvas id="canvas" height="600" width="600">canvas>
  • 获取gl对象,用于后面的gl相关操作

    this.gl = document.getElementById('canvas').getContext("webgl");
  • 初始化着色器,opengl显示需要通过着色器脚本来计算显示

    • 编写顶点着色器脚本

      vertexShaderSource: `    attribute vec4 a_Position;    attribute vec2 a_TexCoord;    varying vec2 v_TexCoord;    void main(){        gl_Position = a_Position;        v_TexCoord = a_TexCoord;    }`
    • 编写片元着色器脚本

      fragmentShaderSource: `    precision mediump float;    uniform sampler2D u_Sampler;    varying vec2 v_TexCoord;    void main(){    gl_FragColor = texture2D(u_Sampler, v_TexCoord);    }`
    • 绑定和使用着色器

      let vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);// 创建顶点着色器this.gl.shaderSource(vertexShader, this.vertexShaderSource);// 绑定顶点着色器源码this.gl.compileShader(vertexShader);// 编译定点着色器let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);// 创建片元着色器this.gl.shaderSource(fragmentShader, this.fragmentShaderSource);// 绑定片元着色器源码this.gl.compileShader(fragmentShader);// 编译片元着色器let shaderProgram = this.gl.createProgram();// 创建着色器程序this.gl.attachShader(shaderProgram, vertexShader);// 指定顶点着色器this.gl.attachShader(shaderProgram, fragmentShader);// 指定片元着色色器this.gl.linkProgram(shaderProgram);// 链接程序this.gl.useProgram(shaderProgram);//使用着色器this.gl.program = shaderProgram;
  • 设置顶点坐标

    • 定义顶点坐标和纹理坐标

      vertexs: new Float32Array([        -1, 1, 0.0, 0.0, 1.0, //左边三位表示顶点坐标的x、y、z,右边两位表示顶点对应的纹理坐标        -1, -1, 0.0, 0.0, 0.0,        1, 1, 0.0, 1.0, 1.0,        1, -1, 0.0, 1.0, 0.0])
    • 设置顶点坐标和纹理坐标

      let vertexsBuffer = this.gl.createBuffer();if (vertexsBuffer === null) {console.log("vertexsBuffer is null");return false;}this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexsBuffer);this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexs, this.gl.STATIC_DRAW);let a_Position = this.gl.getAttribLocation(this.gl.program, "a_Position");if (a_Position < 0) {console.log("a_Position < 0");return false;}let a_TexCoord = this.gl.getAttribLocation(this.gl.program, "a_TexCoord");if (a_TexCoord < 0) {console.log("a_TexCoord < 0");return false;}//将顶点坐标的位置赋值this.gl.vertexAttribPointer(a_Position, 3, this.gl.FLOAT, false, this.vertexs.BYTES_PER_ELEMENT * 5, 0);this.gl.enableVertexAttribArray(a_Position);//将纹理坐标赋值this.gl.vertexAttribPointer(a_TexCoord, 2, this.gl.FLOAT, false, this.vertexs.BYTES_PER_ELEMENT * 5, this.vertexs.BYTES_PER_ELEMENT * 3);this.gl.enableVertexAttribArray(a_TexCoord);
  • 加载图片

    let image = new Image();image.src = require('@/assets/qw.png');this.image = image;
  • 设置纹理

    let textureId = this.gl.createTexture(); //创建纹理对象      if (textureId === null) {        console.log("textureId is null");        return false;      }      this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1); // 对纹理图像进行y轴反转      this.gl.activeTexture(this.gl.TEXTURE0); // 开启0号纹理单元      this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); // 向target绑定纹理对象      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);// 配置纹理参数      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);      this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.image); // 配置纹理图像      let u_Sampler = this.gl.getUniformLocation(this.gl.program, "u_Sampler");      if (u_Sampler < 0) {        console.log("u_Sampler < 0");        return false;      }      this.gl.uniform1i(u_Sampler, 0); // 将0号纹理传递给着色器      
  • 画出图片

    this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);

渲染出来的结果如图下图:

6931cf8d1b8c036cc683229aeb237f48.png

总结

  • opengl对于初学者可能会难一些,可以多了解下着色器和使用流程,就比较容易上手了。

  • 直接上源码

    <template>  <div>    <canvas id="canvas" height="600" width="600">canvas>  div>template><script>export default {  name: "GLImage",  data() {    return {      gl: null,      vertexs: new Float32Array([        -1, 1, 0.0, 0.0, 1.0,        -1, -1, 0.0, 0.0, 0.0,        1, 1, 0.0, 1.0, 1.0,        1, -1, 0.0, 1.0, 0.0]),      vertexShaderSource: `                attribute vec4 a_Position;                attribute vec2 a_TexCoord;                varying vec2 v_TexCoord;                void main(){                gl_Position = a_Position;                v_TexCoord = a_TexCoord;            }`,      fragmentShaderSource: `                precision mediump float;                uniform sampler2D u_Sampler;                varying vec2 v_TexCoord;                void main(){                    gl_FragColor = texture2D(u_Sampler, v_TexCoord);            }`    }  },  methods: {    initShader() {      let vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);// 创建顶点着色器      this.gl.shaderSource(vertexShader, this.vertexShaderSource);// 绑定顶点着色器源码      this.gl.compileShader(vertexShader);// 编译定点着色器      let fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);// 创建片元着色器      this.gl.shaderSource(fragmentShader, this.fragmentShaderSource);// 绑定片元着色器源码      this.gl.compileShader(fragmentShader);// 编译片元着色器      let shaderProgram = this.gl.createProgram();// 创建着色器程序      this.gl.attachShader(shaderProgram, vertexShader);// 指定顶点着色器      this.gl.attachShader(shaderProgram, fragmentShader);// 指定片元着色色器      this.gl.linkProgram(shaderProgram);// 链接程序      this.gl.useProgram(shaderProgram);//使用着色器      this.gl.program = shaderProgram;      return true    },    initVertexs() {      let vertexsBuffer = this.gl.createBuffer();      if (vertexsBuffer === null) {        console.log("vertexsBuffer is null");        return false;      }      this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexsBuffer);      this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexs, this.gl.STATIC_DRAW);      let a_Position = this.gl.getAttribLocation(this.gl.program, "a_Position");      if (a_Position < 0) {        console.log("a_Position < 0");        return false;      }      let a_TexCoord = this.gl.getAttribLocation(this.gl.program, "a_TexCoord");      if (a_TexCoord < 0) {        console.log("a_TexCoord < 0");        return false;      }      //将顶点坐标的位置赋值      this.gl.vertexAttribPointer(a_Position, 3, this.gl.FLOAT, false, this.vertexs.BYTES_PER_ELEMENT * 5, 0);      this.gl.enableVertexAttribArray(a_Position);      //将纹理坐标赋值      this.gl.vertexAttribPointer(a_TexCoord, 2, this.gl.FLOAT, false, this.vertexs.BYTES_PER_ELEMENT * 5, this.vertexs.BYTES_PER_ELEMENT * 3);      this.gl.enableVertexAttribArray(a_TexCoord);      return true;    },    initTextures() {      let textureId = this.gl.createTexture(); //创建纹理对象      if (textureId === null) {        console.log("textureId is null");        return false;      }      this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1); // 对纹理图像进行y轴反转      this.gl.activeTexture(this.gl.TEXTURE0); // 开启0号纹理单元      this.gl.bindTexture(this.gl.TEXTURE_2D, textureId); // 向target绑定纹理对象      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR); // 配置纹理参数      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);      this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);      this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.image); // 配置纹理图像      let u_Sampler = this.gl.getUniformLocation(this.gl.program, "u_Sampler");      if (u_Sampler < 0) {        console.log("u_Sampler < 0");        return false;      }      this.gl.uniform1i(u_Sampler, 0); // 将0号纹理传递给着色器      return true    },    renderImage() {      if (!this.initShader()) {        console.log('initShader is failed')        return;      }      if (!this.initVertexs()) {        console.log('drawVertexs is failed')        return;      }      if (!this.initTextures()) {        console.log('drawTextures is failed')        return;      }      this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);    }  },  mounted() {    this.gl = document.getElementById('canvas').getContext("webgl");    let image = new Image();    image.src = require('@/assets/qw.png');    this.image = image;    image.onload = this.renderImage;  }}script><style scoped>style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值