WebGL学习记录1-点的绘制

96 阅读3分钟

lesson1 点的绘制

静态点

<!DOCTYPE html>
<body>
	<!-- 顶点着色器源码 -->
	<script type="shader-source" id="vertexShader">
	 void main(){
  		//声明顶点位置
  		gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
  		//声明要绘制的点的大小。
  		gl_PointSize = 10.0;
  	}
	</script>
	
	<!-- 片元着色器源码 -->
	<script type="shader-source" id="fragmentShader">
	void main(){
	 	//设置像素颜色为红色
		gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
    }
	</script>
    
	
	<canvas id="canvas"></canvas>
    <!-- javascript -->
	<script src="./1webgl-helper.js"></script>
    <script>
        drawPoint('#canvas', '#vertexShader', '#fragmentShader')
    </script>
</body>
</html>
var random = Math.random;
function randomColor() {
  return {
    r: random() * 255,
    g: random() * 255,
    b: random() * 255,
    a: random() * 1
  };
}
function drawPoint(canvasSelector, vertexShaderSelector, fragmentShaderSelector, isDynamic) {
    // #获取 WebGL 绘图环境
    var canvas = document.querySelector(canvasSelector);
    var gl = canvas.getContext('webgl') || canvas.getContext("experimental-webgl");

    // #创建顶点着色器对象
    // ##获取顶点着色器源码
    var vertexShaderSource = document.querySelector(vertexShaderSelector).innerHTML;
    // ##创建顶点着色器对象
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    // ##将源码分配给顶点着色器对象
    gl.shaderSource(vertexShader, vertexShaderSource);
    // ##编译顶点着色器程序
    gl.compileShader(vertexShader);

    // #创建片元着色器
    // ##获取片元着色器源码
    var fragmentShaderSource = document.querySelector(fragmentShaderSelector).innerHTML;
    // ##创建片元着色器程序
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    // ##将源码分配给片元着色器对象
    gl.shaderSource(fragmentShader, fragmentShaderSource);
    // 编译片元着色器
    gl.compileShader(fragmentShader);

    // #创建着色器程序
    var program = gl.createProgram();
    //将顶点着色器挂载在着色器程序上。
    gl.attachShader(program, vertexShader); 
    //将片元着色器挂载在着色器程序上。
    gl.attachShader(program, fragmentShader);
    //链接着色器程序
    gl.linkProgram(program);

    // #使用刚创建好的着色器程序。
    gl.useProgram(program);

    if(isDynamic) {
        // 此处省略,虽然是学习记录,担心侵权
    }

    //#绘制
    //设置清空画布颜色为黑色。
    gl.clearColor(0.0, 0.0, 0.0, 1.0);

    //用上一步设置的清空画布颜色清空画布。
    gl.clear(gl.COLOR_BUFFER_BIT);

    //绘制点。
    gl.drawArrays(gl.POINTS, 0, 1);
}



动态点

<!DOCTYPE html>
<body>
	<!-- 顶点着色器源码 -->
	<script type="shader-source" id="vertexShader">
        precision mediump float;
        // 接收点在 canvas 坐标系上的坐标 (x, y)
        attribute vec2 a_Position;
        // 接收 canvas 的宽高尺寸
        attribute vec2 a_Screen_Size;
        void main(){
            //start 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
           vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0; 
           position = position * vec2(1.0, -1.0);
           gl_Position = vec4(position, 0, 1);
           //end 将屏幕坐标系转化为裁剪坐标(裁剪坐标系)
           //声明要绘制的点的大小。
           gl_PointSize = 10.0;
        }
	</script>
	
	<!-- 片元着色器源码 -->
	<script type="shader-source" id="fragmentShader">
        //设置浮点数精度为中等精度
        precision mediump float;
        //接收 JavaScript 传过来的颜色值(RGBA)。
        uniform vec4 u_Color;
        void main(){
            //将普通的颜色表示转化为 WebGL 需要的表示方式,即将【0-255】转化到【0,1】之间。
           vec4 color = u_Color / vec4(255, 255, 255, 1);
           gl_FragColor = color; 
        }
	</script>

    
	
	<canvas id="canvas" width="1000px" height="600px"></canvas>
    <!-- javascript -->
	<script src="./1webgl-helper.js"></script>
    <script>
        drawPoint('#canvas', '#vertexShader', '#fragmentShader', true)
    </script>
</body>
</html>

api

GLSL

  1. gl_Position: 内置变量,用来设置顶点坐标。
  2. gl_PointSize: 内置变量,用来设置顶点大小。
  3. vec2:2 维向量容器,可以存储 2 个浮点数。
  4. gl_FragColor: 内置变量,用来设置像素颜色。
  5. vec4:4 维向量容器,可以存储 4 个浮点数。
  6. precision:精度设置限定符,使用此限定符设置完精度后,之后所有该数据类型都将沿用该精度,除非单独设置。
  7. 运算符:向量的对应位置进行运算,得到一个新的向量。 vec * 浮点数: vec2(x, y) * 2.0 = vec(x * 2.0, y * 2.0)。 vec2 * vec2:vec2(x1, y1) * vec2(x2, y2) = vec2(x1 * x2, y1 * y2)。 加减乘除规则基本一致。但是要注意一点,如果参与运算的是两个 vec 向量,那么这两个 vec 的维数必须相同。

JavaScript 程序如何连接着色器程序

createShader:创建着色器对象 shaderSource:提供着色器源码 compileShader:编译着色器对象 createProgram:创建着色器程序 attachShader:绑定着色器对象 linkProgram:链接着色器程序 useProgram:启用着色器程序 JavaScript 如何往着色器中传递数据

JavaScript 如何往着色器中传递数据

getAttribLocation:找到着色器中的 attribute 变量地址。 getUniformLocation:找到着色器中的 uniform 变量地址。 vertexAttrib2f:给 attribute 变量传递两个浮点数。 uniform4f:给uniform变量传递四个浮点数。

WebGL 绘制函数

drawArrays: 用指定的图元进行绘制。

WebGL 图元

gl.POINTS: 将绘制图元类型设置成点图元。

绘制原理

vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0

上面这句代码用来将浏览器窗口坐标转换成裁剪坐标,之后通过透视除法,除以 w 值(此处为 1 )转变成设备坐标(NDC坐标系)。这个算法首先将(x,y) 转化到【0, 1】区间,再将 【0, 1】之间的值乘以 2 转化到 【0, 2】区间,之后再减去 1 ,转化到 【-1, 1】之间的值,即 NDC 坐标。