WebGL

WebGL

可供参考的链接:

MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL2RenderingContext

网站:https://webglfundamentals.org/webgl/lessons/zh_cn/

初步介绍
  • 绘制流程:页面添加canvas元素 - 获取webgl对象 - 清空屏幕 - 设置好着色器等 - 绘制

    • 页面添加canvas元素

      <canvas id="canvas" width="400" height="400"></canvas>
      
    • 获取webgl对象

       var canvas = document.getElementById('canvas'),  //绘制canvas
      	 webgl = canvas.getContext('webgl');  //获取webgl
      
    • 清空屏幕

      webgl.clearColor(0.043,0.5,0.2,1.0);  //使用一种颜色清空之前的颜色
      	webgl.clear(webgl.COLOR_BUFFER_BIT);  //使用clear填入进去	
      
  • 着色器

    使用的是glsl es语言

    • 顶点着色器(vertex shader)

      是指二维或二维空间的一个点,比如二维或二维空间线与线之间的交叉点或端点

    • 片元着色器(fragment shader)

      可以将其理解为像素

    • 着色器变量类型

      attribute:属性,传输与顶点相关的数据 - 顶点

      uniform:全局变量,传输所有顶点都相同的数据 - 片元

      varying:可变量,从顶点着色器向片元着色器传输数据 - 顶点向片元传输数据

    • 着色器的设置

      定义着色器字符串 - 创建着色器对象并绑定好对应的着色器字符串 - 创建着色器程序并添加前面创建的着色器对象 - 把着色起程序链接成一个完整的程序并使用它

      • 定义着色器字符串

        var vs_source = `
            void main() {
                //vec4中表示内容的大小 只能是0-1的范围 是float类型
                gl_Position = vec4(0.5, 0.0, 1.0, 1.0);  //设置位置
                gl_PointSize = 20.0;  //设置尺寸
            }
        `;
        
        //片元着色器
        var fs_source = `
            void main(){
            	gl_FragColor = vec4(0.78,0.0,1.0,1.0); 
        	}
        `;
        
      • 创建着色器对象并绑定好对应的着色器字符串

        //创建顶点着色器容器
        var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);
        //将着色器容器与资源绑定
        webgl.shaderSource(vertexShader, vs_source);
        //编译顶点着色器
        webgl.compileShader(vertexShader);
        
        //片元着色器的容器创建 绑定 编译
        var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);
        webgl.shaderSource(fragmentShader, fs_source);
        webgl.compileShader(fragmentShader);
        
      • 创建着色器程序并添加前面创建的着色器对象

        //创建着色器程序
        var glProgram = webgl.createProgram();
        //添加到着色器程序中
        webgl.attachShader(glProgram,vertexShader);
        webgl.attachShader(glProgram,fragmentShader);
        
        
      • 把着色起程序链接成一个完整的程序并使用它

        webgl.linkProgram(glProgram);
        webgl.useProgram(glProgram);
        
      • 绘制

        webgl.drawArrays(webgl.POINTS,0,1);
        
    • 注意点:

      • 关于着色器对象的定义有两种方式

        在使用第二种方式进行定义时,要注意一句话的结尾 必须加上;

        方式1<script type="x-sharder/x-vertex" id="shader-vx">
            void main() {
                //vec4中表示内容的大小 只能是0-1的范围 是float类型
                gl_Position = vec4(0.5, 0.0, 1.0, 1.0);  //设置位置
                gl_PointSize = 20.0;  //设置尺寸
            }
         </script>
        <!-- 片元着色器 -->
        <script type="x-sharder/x-fragment" id="sharder-fs">
            void main(){
                //设置片元颜色 类似于rgba 最后为透明度 前面在webgl中也是从0-1 对应0-255
                gl_FragColor = vec4(0.78,0.0,1.0,1.0);  
            }
        </script>
        
        方式2var vs_source = `
            attribute vec4 a_Position;  
            attribute float a_PointSize;
            void main(){
                gl_Position = a_Position;
                gl_PointSize = a_PointSize;  
            }
        `;
        
        //片元着色器
        var fs_source = `
            void main(){
                gl_FragColor = vec4(0.78,0.0,1.0,1.0); 
            }
        `;
        
      • 可以设置变量 来动态改变点的位置、大小

        
        var vs_source = `
            attribute vec4 a_Position;   //声明一个变量 变量名可随便赋值
            attribute float a_PointSize;  //注意声明变量的类型 要与之后所传递值的类型对应
            void main(){
                gl_Position = a_Position;
                gl_PointSize = a_PointSize;  
            }
        `;
        
        在绘制点之前进行赋值
        
        //获取attribute变量的存储位置,返回对应的地址信息
        var aPosition = webgl.getAttribLocation(glProgram, 'a_Position');
        /**
        * vertexAttrib 顶点属性
        * f float类型 
        * 3 3个参数 代表位置信息
        */
        webgl.vertexAttrib3f(aPosition,0.5, 0.0, 1.0)  //给变量赋值  
        
        var aPointSize = webgl.getAttribLocation(glProgram, 'a_PointSize');
        webgl.vertexAttrib1f(aPointSize, 50.0); //类型为浮点型 相互对应
        
        //5、绘制
        /**
        * 第一个参数 表示你绘制的形状  gl.POINTS 绘制一个点
        * 第二个参数 0 表示你从哪个位置开始绘制
        * 第三个参数 1 表示到哪儿结束
        */
        webgl.drawArrays(webgl.POINTS,0,1);
        
      • 关于动态改变点的位置 两种方式

        方式1var aPosition = webgl.getAttribLocation(glProgram, 'a_Position');
        /**
        * vertexAttrib 顶点属性
        * f float类型 
        * 3 3个参数 代表位置信息
        */
        webgl.vertexAttrib3f(aPosition,0.5, 0.0, 1.0)  //给变量赋值 
        
        方式2var aPosition = webgl.getAttribLocation(glProgram, 'a_Position');  //允许读取变量
        var p = new Float32Array([0.5, 0.0, 1.0]);
        webgl.vertexAttrib3fv(aPosition,p);  //赋值
        
绘制圆点

需要利用webgl中,glsl es语言

将绘制片元着色器时 超过半径为0.5的区域设置为与半径融合的颜色 则将其不显示

进而实现绘制圆点的要求

var fs_source = `
#ifdef GL_ES  
	precision mediump float;
#endif
void main(){
    float d = distance(gl_PointCoord, vec2(0.5,0.5));
    if(d<0.5){
    	gl_FragColor = vec4(1.0,0.0,0.0,1.0);  
    }else{
    	discard;
    }
}
`;
在片元着色器中使用变量 定义片元颜色

片元语言没有默认的浮点数精度修饰符。因此,对于浮点数,浮点数向量和矩阵变量声明,要么声明必须包含一个精度修饰符,要不默认的精度修饰符在之前已经被声明过了。

var fs_source = `
    #ifdef GL_ES
        precision mediump float;  //必须包含这条语句
    #endif
    uniform vec4 u_FragColor;
    void main(){
        gl_FragColor = u_FragColor;  
    }
`
//允许读取变量
var uFragColor = webgl.getUniformLocation(glProgram, 'u_FragColor');
//赋值
webgl.uniform4f(uFragColor,1.0,0.5,0.5,1.0)
绘制多个圆 - 缓冲区

需要借用到缓冲区

  • 定义各原点位置 在写入数据时传入缓冲区

    var p = new Float32Array([
        0.0, 0.0, 0.8,
        0.5, 0.0, 0.8,
        0.5, 0.0, 0.4
    ]);
    
  • 创建缓冲区:WebGLRenderingContext.createBuffer()

    var vertexBuffer = webgl.createBuffer();
    
  • 绑定缓冲区,将缓冲区绑定到目标,在内存中申请一片区域:WebGLRenderingContext.bindBuffer()

    /**
    * webgl.bindBuffer(target, buffer)
    * 第一个参数 指定缓冲区的目标类型
    * 第二个参数 创建的缓冲区对象
    */
    webgl.bindBuffer(webgl.ARRAY_BUFFER, vertexBuffer);
    
  • 向缓冲区写入数据:WebGLRenderingContext.bufferData()

    /**
    * 第一个参数 指定缓冲区的目标类型
    * 第二个参数 数据
    * 第三个参数 静态绘制
    */
    webgl.bufferData(webgl.ARRAY_BUFFER, p, webgl.STATIC_DRAW);
    
  • 获取变量位置 坐标值

    var aPosition = webgl.getAttribLocation(glProgram, 'a_Position');
    
  • 把缓冲区对象分配给变量a_Position

    /**
    * aPosition 修改的位置
    * 2 顶点的组成数量
    * webgl.FLOAT 每个元素的数据类型
    * false 转换为浮点数时是否应该将整数数值归一化到特定的范围
    * 0 紧密打包
    * 0 顶点属性数组中第一部分的字节偏移量
    */
    webgl.vertexAttribPointer(aPosition, 2, webgl.FLOAT, false, 0, 0);
    
  • 链接缓冲区对象和a_Position:

    webgl.enableVertexAttribArray(aPosition)
    
  • 绘制你想要几个顶点

    //0 数组中下标为0
    //3 数组中下标为2
    webgl.drawArrays(webgl.POINTS,0,3);  
    
绘制三角形 - 即为连接三个点

可改变要连接点的起始位置和末尾位置 绘制三角形

webgl.drawArrays(webgl.TRIANGLES,0,3);
整体代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<!-- canvas的宽度和高度设置 尽量使用width这种形式定义 不要使用style这种形式 -->
		<canvas id="canvas" width="400" height="400"></canvas>
		<script>
			/*
			var canvas = document.getElementById('canvas'),  //绘制canvas
				webgl = canvas.getContext('webgl');  //获取webgl
			webgl.viewport(0, 0, canvas.width, canvas.height);  //视口
			webgl.clearColor(0.043,0.5,0.2,1.0);  //使用一种颜色清空之前的颜色
			webgl.clear(webgl.COLOR_BUFFER_BIT);  //使用clear填入进去
			*/
		   //1、 获取webgl
		    var canvas = document.getElementById('canvas'),  //绘制canvas
				webgl = canvas.getContext('webgl');  //获取webgl
			
			webgl.clearColor(0.043,0.5,0.2,1.0);  //使用一种颜色清空之前的颜色
			webgl.clear(webgl.COLOR_BUFFER_BIT);  //使用clear填入进去
			
			
			//顶点着色器 可以使用上面那种方式 也可以使用这种
			//每一句的分号结尾不可省略
			//a_Position;  //声明一个变量 变量名可随便赋值
			//在声明变量时 注意你声明的类型 要与之后你所传递值的类型对应
			var vs_source = `
				attribute vec4 a_Position;  
				attribute float a_PointSize;
				void main(){
					gl_Position = a_Position;
					gl_PointSize = a_PointSize;  
				}
			`;
			
			//片元着色器
			var fs_source = `
				#ifdef GL_ES
					precision mediump float;
				#endif
				uniform vec4 u_FragColor;
				void main(){
					gl_FragColor = u_FragColor;  
				}
			`
			
			
			
			//2、创建着色器对象并绑定好对应的着色器字符串
			//创建顶点着色器容器
			var vertexShader = webgl.createShader(webgl.VERTEX_SHADER);
			//将着色器容器与资源绑定
			webgl.shaderSource(vertexShader, vs_source);
			//编译顶点着色器
			webgl.compileShader(vertexShader);
			
			//片元着色器的容器创建 绑定 编译
			var fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER);
			webgl.shaderSource(fragmentShader, fs_source);
			webgl.compileShader(fragmentShader);
			
			//3、创建着色器程序并添加前面创建的着色器对象
			//创建着色器程序
			var glProgram = webgl.createProgram();
			//添加到着色器程序中
			webgl.attachShader(glProgram,vertexShader);
			webgl.attachShader(glProgram,fragmentShader);
			
			
			//4、把着色起程序链接成一个完整的程序并使用它
			webgl.linkProgram(glProgram);
			webgl.useProgram(glProgram);
			
			
			/**
			 * vertexAttrib 顶点属性
			 * f float类型 
			 * 3 3个参数 代表位置信息
			 */
			var p = new Float32Array([
				0.0, 0.0, 0.8,
				0.5, 0.0, 0.8,
				0.5, 0.0, 0.4
			]);
			
			//1、创建缓冲区
			var vertexBuffer = webgl.createBuffer();
			
			//2、绑定缓冲区,将缓冲区绑定到目标,在内存中申请一片区域
			/**
			 * webgl.bindBuffer(target, buffer)
			 * 第一个参数 指定缓冲区的目标类型
			 * 第二个参数 创建的缓冲区对象
			 */
			webgl.bindBuffer(webgl.ARRAY_BUFFER, vertexBuffer);
			
			//3、向缓冲区写入数据
			/**
			 * 第一个参数 指定缓冲区的目标类型
			 * 第二个参数 数据
			 * 第三个参数 静态绘制
			 */
			webgl.bufferData(webgl.ARRAY_BUFFER, p, webgl.STATIC_DRAW);
			
			//4、获取attribute变量的存储位置,返回对应的地址信息
			var aPosition = webgl.getAttribLocation(glProgram, 'a_Position');
			
			//5、把缓冲区对象分配给变量aPosition
			/**
			 * aPosition 修改的位置
			 * 2 顶点的组成数量
			 * webgl.FLOAT 每个元素的数据类型
			 * false 转换为浮点数时是否应该将整数数值归一化到特定的范围
			 * 0 紧密打包
			 * 0 顶点属性数组中第一部分的字节偏移量
			 */
			webgl.vertexAttribPointer(aPosition, 2, webgl.FLOAT, false, 0, 0);
			
			//6、链接缓冲区对象和a_Position
			webgl.enableVertexAttribArray(aPosition)
			
			
			//给变量赋值  
			var aPointSize = webgl.getAttribLocation(glProgram, 'a_PointSize');
			webgl.vertexAttrib1f(aPointSize, 10.0);
			
			var uFragColor = webgl.getUniformLocation(glProgram, 'u_FragColor');
			webgl.uniform4f(uFragColor,1.0,0.5,0.5,1.0);
			
			
			
			//5、绘制
			/**
			 * 第一个参数 表示你绘制的形状  gl.POINTS 绘制一个点
			 * 第二个参数 0 表示你从哪个位置开始绘制
			 * 第三个参数 1 表示到哪儿结束
			 */
			webgl.drawArrays(webgl.TRIANGLES,0,3);
			
		</script>
	</body>
</html>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值