zoukankan      html  css  js  c++  java
  • WebGL之通过外部传入a_PontSize值改变点着色器vshader内置变量gl_PointSize的值

    最近分配到一个看起来非常简单的优化需求、通过地图上设置工具来改变地图上显示的点的大小和透明度。无非过程就是从控件面板获取到用户设置的值保存到数据库中、然后地图上画点的时候取出设置的值渲染出点即可。前端绘制图形无非canvas、这个方面我之前也是不怎么涉及的部分、所以趁这次分配的任务比较轻时间相对宽裕的情况下、可谓是好好学了一把WebGL的内容。通过一个星期的查找学习、总算有了比较清晰的理解、足以好好理解代码了。

    俗话说、工欲善其事必先利其器、我这次可是深刻体会了一把。一开始觉得好像蛮容易的、后来怎么也搞不到一起才静下心来认认真真看了webGL的内容、比较不好理解、反正我对着代码翻来覆去看了四五六七遍以上吧、才终于理解了代码执行的逻辑顺序。

    学习准备:

    WebGL教程:  http://www.yanhuangxueyuan.com/WebGL_course.html   (推荐、跟着里面说明的方法来学习理解)

    W3C关于WebGL的基础学习 (动手前最好看明白的基础理论学习) https://www.w3cschool.cn/webgl/157h1oh3.html

    WebGL入门教程(一)-初识webgl  (可以跟着搞起来的实例教程)  http://www.cnblogs.com/bsman/p/6128447.html

    从OpenGL传颜色数值到Shader,改变绘图颜色(看了这篇才找到答案的)   http://blog.csdn.net/huutu/article/details/21460835

    WebGL基础(辅助理解)  https://www.cnblogs.com/mazhenyu/p/3804518.html

    开始解题:

    1.大体的思路如下图、代码有省略

    其实图上看明白了题已经解了、屡一下思路、WebGL先要声明点着色器和片着色器、然后放在program上建立起来、在建立好program后我们定义一个变量gl.aPointSize,将点着色器的一个属性值a_pointSize赋值给这个变量gl.aPointSize,然后我们根据实际项目需求通过控制这个gl.aPointSize进而改变点着色器中内部变量gl_PointSize。就这么简单,主要是看明白webGL每一个语句的用法,就容易做了。

    2.代码参考

    ①在main.aspx中声明点着色器

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Ext5.Master" Inherits="System.Web.Mvc.ViewPage" %>
    <%@ Import Namespace="F5WS.Web" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    
        <script type="text/javascript">var tinyItems = <%= ViewData["TinyItems"] %></script>
        <script id="vshader" type="x-shader/x-vertex">
            uniform mat4 u_matrix;
            attribute vec4 a_vertex;
            attribute float a_pointSize;
            attribute vec4 a_color;
            varying vec4 v_color;
    
            void main() {
            // Set the size of the point
            // a_pointSize;
    
            gl_PointSize = a_pointSize;
            
            // multiply each vertex by a matrix.
            gl_Position = u_matrix * a_vertex;
    
    
            // pass the color to the fragment shader
            v_color = a_color;
            }
        </script>
        <!-- fragment shader -->
    
        <!-- vec4 color1 = vec4(v_color[0], v_color[1], v_color[2], 0.6);调整透明度在这里 -->
        <script id="fshader" type="x-shader/x-fragment">
            precision mediump float;
            varying vec4 v_color;
            uniform sampler2D uSampler;
            void main() {
    
            float border = 0.1;
            float radius = 0.5;
            vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
            // 最后一个参数为 透明度设定
            vec4 color1 = vec4(v_color[0], v_color[1], v_color[2], v_color[3]);
    
            vec2 m = gl_PointCoord.xy - vec2(0.5, 0.5);
            float dist = radius - sqrt(m.x * m.x + m.y * m.y);
    
            float t = 0.0;
            if (dist > border)
            t = 1.0;
            else if (dist > 0.0)
            t = dist / border;
    
            // float centerDist = length(gl_PointCoord - 0.5);
            // works for overlapping circles if blending is enabled
    
            gl_FragColor = mix(color0, color1, t);
    
            }
    
        </script>
    
        </script>
    </asp:Content>
    main.aspx

    ②在CanvasOverlayGL.js中使用、截取了WebGL部分的代码、方便核对自己的代码理解

        setWebGL: function () {
            var me = this;
            var gl = this._canvas.getContext('experimental-webgl', { antialias: true });
            if (!gl) {
                me._usingGL = false;
                return;
            }
    
            me._gl = gl;
    
            this._pixelsToWebGLMatrix = new Float32Array(16);
            this._mapMatrix = new Float32Array(16);
    
            // -- WebGl setup
            if (!gl) return;
            var vertexShader = gl.createShader(gl.VERTEX_SHADER);
            if (!document.getElementById('vshader')) return;
            gl.shaderSource(vertexShader, document.getElementById('vshader').text);
            gl.compileShader(vertexShader);
    
            var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
            if (!document.getElementById('fshader')) return;
            gl.shaderSource(fragmentShader, document.getElementById('fshader').text);
            gl.compileShader(fragmentShader);
    
            // link shaders to create our program
            var program = gl.createProgram();
            gl.attachShader(program, vertexShader);
            gl.attachShader(program, fragmentShader);
            gl.linkProgram(program);
            gl.useProgram(program);
            gl.enable(gl.BLEND);
    
            gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    
            // look up the locations for the inputs to our shaders.
            this._u_matLoc = gl.getUniformLocation(program, "u_matrix");
            this._colorLoc = gl.getAttribLocation(program, "a_color");
            this._vertLoc = gl.getAttribLocation(program, "a_vertex");
            gl.aPointSize = gl.getAttribLocation(program, "a_pointSize");
    
            // Set the matrix to some that makes 1 unit 1 pixel.
            this._pixelsToWebGLMatrix.set([2 / this._canvas.width, 0, 0, 0, 0, -2 / this._canvas.height, 0, 0, 0, 0, 0, 0, -1, 1, 0, 1]);
            gl.viewport(0, 0, this._canvas.width, this._canvas.height);
    
            gl.uniformMatrix4fv(this._u_matLoc, false, this._pixelsToWebGLMatrix);
        },
        loadData: function (data, total) {
    
            var me = this;
            var gl = me._gl;
            var usingGL = me._usingGL;
            var verts = data;  //你自己要渲染的数据
    
            this._size = verts[2];    //我这里的verts[2] = -50
            this._cSize = verts[7]; // 我这里的verts[7] = 5.0
    
            this._numPoints = total;
            if (usingGL) {
                if (!this._buffer) {
                    var vertBuffer = gl.createBuffer();
                    this._buffer = vertBuffer;
                    gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
                    gl.enableVertexAttribArray(this._vertLoc);
                    gl.enableVertexAttribArray(this._colorLoc);
                }
    
                var vertArray = new Float32Array(verts);
    
                var fsize = vertArray.BYTES_PER_ELEMENT;
    
                gl.bufferData(gl.ARRAY_BUFFER, vertArray, gl.STATIC_DRAW);
    
                gl.vertexAttribPointer(0, 3, gl.FLOAT, false, fsize * 7, 0);
    
                // -- offset for color buffer
                gl.vertexAttribPointer(this._colorLoc, 4, gl.FLOAT, false, fsize * 7, fsize * 3);
    
            }
    
            this.redraw();
        },
        drawingOnCanvas: function () {
            if (this._gl == null) return;
            var gl = this._gl;
            gl.clear(gl.COLOR_BUFFER_BIT);
            this._pixelsToWebGLMatrix.set([2 / this._canvas.width, 0, 0, 0, 0, -2 / this._canvas.height, 0, 0, 0, 0, 0, 0, -1, 1, 0, 1]);
    
            //debugger;
            var pointSize = 78271.5170 / Math.pow(2, this._map.getZoom() - 1);
            var size = this._size;
            if (size < 0.0) {
                size = -size / pointSize;
                if (size < 7.0) {
                    //size = 7.0;
                    size = this._cSize + 2 ;  //我这里 this._cSize=5,我想设定点大小为7,所以+2了
                }
            }
    
           // console.log(size);
            gl.vertexAttrib1f(gl.aPointSize, size);  //将size传给点着色器的gl.aPointSize,从而改变到点的大小了
    
            // -- set base matrix to translate canvas pixel coordinates -> webgl coordinates
            this._mapMatrix.set(this._pixelsToWebGLMatrix);
            //debugger;
            var bounds = this._map.getBounds();
            var topLeft = new L.LatLng(bounds.getNorth(), bounds.getWest());
    
            var newLatlng = this.offsetFn(topLeft.lat, topLeft.lng);
    
            var offset = this.LatLongToPixelXY(topLeft.lat - newLatlng.lat + topLeft.lat, topLeft.lng - newLatlng.lng + topLeft.lng);
    
            this._offset.x = offset.x;
            this._offset.y = offset.y;
            this._offset.topLeft = topLeft;
    
            // -- Scale to current zoom
            var scale = Math.pow(2, this._map.getZoom());
            this.scaleMatrix(this._mapMatrix, scale, scale);
    
            this.translateMatrix(this._mapMatrix, -offset.x, -offset.y);
    
            // -- attach matrix value to 'mapMatrix' uniform in shader
            gl.uniformMatrix4fv(this._u_matLoc, false, this._mapMatrix);
            //debugger;
            gl.drawArrays(gl.POINTS, 0, this._numPoints);
        },
        LatLongToPixelXY: function (latitude, longitude) {
            var pi_180 = Math.PI / 180.0;
            var pi_4 = Math.PI * 4;
            var sinLatitude = Math.sin(latitude * pi_180);
            var pixelY = (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (pi_4)) * 256;
            var pixelX = ((longitude + 180) / 360) * 256;
    
            var pixel = { x: pixelX, y: pixelY };
    
            return pixel;
        },
        translateMatrix: function (matrix, tx, ty) {
            // translation is in last column of matrix
            matrix[12] += matrix[0] * tx + matrix[4] * ty;
            matrix[13] += matrix[1] * tx + matrix[5] * ty;
            matrix[14] += matrix[2] * tx + matrix[6] * ty;
            matrix[15] += matrix[3] * tx + matrix[7] * ty;
        },
        scaleMatrix: function (matrix, scaleX, scaleY) {
            // scaling x and y, which is just scaling first two columns of matrix
            matrix[0] *= scaleX;
            matrix[1] *= scaleX;
            matrix[2] *= scaleX;
            matrix[3] *= scaleX;
    
            matrix[4] *= scaleY;
            matrix[5] *= scaleY;
            matrix[6] *= scaleY;
            matrix[7] *= scaleY;
        },
    CanvasOverlayGL.js
  • 相关阅读:
    处理流之转换流
    处理流之缓冲流 buffered
    java学习笔记 字符流Reader与Writer
    java学习笔记 OutputStream与InputStream
    java学习笔记 Map接口
    java 学习笔记 Iterator 迭代器
    java学习笔记 genenic 范形
    应急响应介绍
    安全之红蓝对抗简介
    密码学基础下篇
  • 原文地址:https://www.cnblogs.com/GuliGugaLiz/p/8578199.html
Copyright © 2011-2022 走看看