跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • WebGL 实现简单滤镜
未分類
6 1 月 2021

WebGL 实现简单滤镜

WebGL 实现简单滤镜

資深大佬 : zoule 0

1. WebGL 介绍

WebGL (全写 Web Graphics Library )是一种 3D 绘图协议,这种绘图技术标准允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定。

2. WebGL 、OpenGL 、OpenGL ES 三者的关系

WebGL 实现简单滤镜

3. WebGL 基础介绍

const webgl = document.getElementById("webGl-layer").getContext("webgl");  

4. 基本原理

  • 首先使用 webgl 纹理绘制图片

这里如果参照 https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-cors-permission.html

  • 绘制过程中使用片段做着色器对其 rgb 值进行修改

5. 具体实现

WebGL 实现简单滤镜

<!DOCTYPE html> <html lang="ch"> <head>     <meta charset="UTF-8">     <title>VertexBuffer</title> </head> <body> <canvas id="webGl-layer"  width="532" height="300"></canvas> <div>     <label for="r1">饱和度:</label><input type="range" id="r1" value="0"/> </div>  <div>     <label for="r2">R:</label><input type="range" id="r2" value="0"/> </div>  <div>     <label for="r3">G:</label><input type="range" id="r3" value="0"/> </div>  <div>     <label for="r4">B:</label><input type="range" id="r4" value="0"/> </div>  <script>     const webgl = document.getElementById("webGl-layer").getContext("webgl");     const range1 = document.getElementById("r1"),         range2 = document.getElementById("r2"),         range3 = document.getElementById("r3"),         range4 = document.getElementById("r4");      webgl.viewport(0, 0, 532, 300);      const vertexShader2D = `         precision mediump float;         attribute vec4 position;         attribute vec4 inputTextureCoordinate;         varying vec2 textureCoordinate;          void main() {             gl_Position = position;             textureCoordinate = vec2((position.x+1.0)/2.0, 1.0-(position.y+1.0)/2.0);         }     `;      const fragmentShader2D = `         precision mediump float;         varying vec2 textureCoordinate;         uniform sampler2D inputImageTexture;         uniform float size;         uniform float saturation;         uniform float r;         uniform float g;         uniform float b;         uniform float a;          void main() {             vec4 texture = texture2D(inputImageTexture, textureCoordinate);             texture.r += r; // 图片整体 r 值             texture.g += g; // 图片整体 g 值             texture.b += b; // 图片整体 b 值             // texture.a = 0.5; // 图片整体 a 值              //内阴影             // float dist = distance(textureCoordinate, vec2(0.5, 0.5));             // texture.rgb *= smoothstep(0.8, size * 0.799, dist * (1.0 + size));              //饱和度             float average = (texture.r + texture.g + texture.b) / 3.0;             if (saturation > 0.0) {                 texture.rgb += (average - texture.rgb) * (1.0 - 1.0 / (1.001 - saturation));             } else {                 texture.rgb += (average - texture.rgb) * (-saturation);             }              gl_FragColor = texture;          }     `;      function createShader(gl, type, source) {         const shader = gl.createShader(type);         gl.shaderSource(shader, source);         gl.compileShader(shader);         if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {             return shader;         }         console.log(gl.getShaderInfoLog(shader));         gl.deleteShader(shader);     }      function createProgram(gl, vertexShader, fragmentShader) {         const program = gl.createProgram();         gl.attachShader(program, vertexShader);         gl.attachShader(program, fragmentShader);         gl.linkProgram(program);         if (gl.getProgramParameter(program, gl.LINK_STATUS)) {             webgl.useProgram(program);             return program;         }         console.error(gl.getProgramInfoLog(program));         gl.deleteProgram(program);     }      function createTextureByImageObject(gl, imgObject) {         gl.activeTexture(gl.TEXTURE0);         const textureObject = gl.createTexture();         gl.bindTexture(gl.TEXTURE_2D, textureObject);         gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imgObject);         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)         return textureObject;     }      const vertices = [         1.0, 1.0,         1.0, -1.0,         -1.0, 1.0,         -1.0, -1.0     ];      const vertexShader = createShader(webgl, webgl.VERTEX_SHADER, vertexShader2D),         fragmentShader = createShader(webgl, webgl.FRAGMENT_SHADER, fragmentShader2D),         program = createProgram(webgl, vertexShader, fragmentShader),         buffer = webgl.createBuffer();      webgl.bindBuffer(webgl.ARRAY_BUFFER, buffer);     webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(vertices), webgl.STATIC_DRAW);      let v4PositionIndex = webgl.getAttribLocation(program, "position");     webgl.enableVertexAttribArray(v4PositionIndex);     webgl.vertexAttribPointer(v4PositionIndex, 2, webgl.FLOAT, false, 0, 0);      let img = new Image();     img.crossOrigin = "anonymous";     img.src = "http://static.atvideo.cc/2021/01/04/09/47/1609724837(1).jpg";     img.onload = function () {         document.body.append(img);         createTextureByImageObject(webgl, img);         let saturationUniform = webgl.getUniformLocation(program, "saturation");         let rUniform = webgl.getUniformLocation(program, "r");         let gUniform = webgl.getUniformLocation(program, "g");         let bUniform = webgl.getUniformLocation(program, "b");          // let sizeUniform = webgl.getUniformLocation(program, "size");         // webgl.uniform1f(sizeUniform, 2.0);          const uniform = webgl.getUniformLocation(program, "inputImageTexture");         webgl.uniform1i(uniform, 0);         webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);          range1.addEventListener("change", function () {             const val = Number(range1.value) / 100;             webgl.uniform1f(saturationUniform, val);             webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);         });          range2.addEventListener("change", function () {             const val = Number(range2.value) / 100;             webgl.uniform1f(rUniform, val);             webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);         });          range3.addEventListener("change", function () {             const val = Number(range3.value) / 100;             webgl.uniform1f(gUniform, val);             webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);         });          range4.addEventListener("change", function () {             const val = Number(range4.value) / 100;             webgl.uniform1f(bUniform, val);             webgl.drawArrays(webgl.TRIANGLE_STRIP, 0, 4);         });     }  </script>  </body> </html>  

大佬有話說 (0)

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具