惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Martin Fowler
Martin Fowler
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
博客园_首页
Engineering at Meta
Engineering at Meta
The Cloudflare Blog
MongoDB | Blog
MongoDB | Blog
Blog — PlanetScale
Blog — PlanetScale
T
The Blog of Author Tim Ferriss
雷峰网
雷峰网
D
Docker
博客园 - 司徒正美
S
SegmentFault 最新的问题
M
MIT News - Artificial intelligence
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
U
Unit 42
J
Java Code Geeks
A
About on SuperTechFans
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Security Affairs
I
Intezer
Cisco Talos Blog
Cisco Talos Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog RSS Feed
P
Privacy & Cybersecurity Law Blog
T
Tenable Blog
T
Threatpost
H
Hacker News: Front Page
G
Google Developers Blog
博客园 - 【当耐特】
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research
L
Lohrmann on Cybersecurity
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
A
Arctic Wolf
S
Secure Thoughts
GbyAI
GbyAI
NISL@THU
NISL@THU
S
Security @ Cisco Blogs
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Webroot Blog
Webroot Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
O
OpenAI News
Spread Privacy
Spread Privacy
Application and Cybersecurity Blog
Application and Cybersecurity Blog

WebGL

请教一个 webgl 问题,例子里面的代码在 windows 与 Linux 上表现正常, mac 上提示 Vertex buffer is not big enough for the draw call - V2EX 做了一些仿 Hopf 纤维丛的图 - V2EX 求 webgl(threejs)成体系的教程 - V2EX 求 WebGL 和 three.js 学习路线 - V2EX 这个 WebGL 3D 渲染效果太美不敢看 WebGL Water Simulator - V2EX
WebGL 实现简单滤镜 - V2EX
zoule · 2021-01-04 · via WebGL

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

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

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. 具体实现

<!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>