<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
/* 移除边界 */
body {
border: 0;
background-color: white;
}
/* 设置欢度大小为视域大小 */
canvas {
width: 100vw;
height: 100vh;
display: block;
}
</style>
<body>
<canvas id="c"></canvas>
<script id="2d-vertex-shader2" type="notjs">
attribute vec4 a_position;
void main(){
gl_Position = a_position;
}
</script>
<script id="2d-vertex-shader" type="notjs">
attribute vec2 a_position;
uniform vec2 u_resolution;
void main(){
//从像素坐标转换到0.0到1.0
vec2 zeroToOne = a_position / u_resolution;
//在吧0->1转换0->2
vec2 zeroToTwo = zeroToOne * 2.0;
//把0->2转换到-1->+1剪裁空间
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace* vec2(1,-1),0,1);
}
</script>
<script>
function resize(canvas) {
// 获取浏览器中画布的显示尺寸
var displayWidth = canvas.clientWidth;
var displayHeight = canvas.clientHeight;
// 检尺寸是否相同
if (canvas.width != displayWidth ||
canvas.height != displayHeight) {
// 设置为相同的尺寸
canvas.width = displayWidth;
canvas.height = displayHeight;
}
}
</script>
<script id="2d-fragment-shader" type="notjs">
precision mediump float;
uniform vec4 u_color;
void main(){
gl_FragColor = u_color;
}
</script>
<script src="js/webgl-utils.js"></script>
<script src="js/helloworld.js"></script>
</body>
</html>
"use strict";
function createShader(gl,type,source){
var shader = gl.createShader(type);//创建着色器对象
gl.shaderSource(shader,source);//提供数据按
gl.compileShader(shader);//编译-》生成着色器
var success = gl.getShaderParameter(shader,gl.COMPILE_STATUS);
if(success){
return shader;
}
console.log(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
function createProgram(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
var success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (success) {
return program;
}
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
function main(){
var canvas = document.getElementById("c");
var gl=canvas.getContext("webgl");
if(!gl){
return ;
}
/**
* 初始化代码*/
//以下函数为创建着色器方法,输入参数,渲染上下文,着色器类型,数据源
//利用以上方法创建着色器
var vertexShaderSource=document.getElementById("2d-vertex-shader").text;
var fragmentShaderSource=document.getElementById("2d-fragment-shader").text;
var vertexShader = createShader(gl,gl.VERTEX_SHADER,vertexShaderSource);
var fragmentShader = createShader(gl,gl.FRAGMENT_SHADER,fragmentShaderSource);
//将两个着色器link到一个program着色程序上
//调用上面的函数
var program = createProgram(gl, vertexShader, fragmentShader);
var program=createProgram(gl,vertexShader,fragmentShader);
//后面要给着色程序提供数据,先找到属性值的位置
var positionAttributeLocation = gl.getAttribLocation(program,"a_position");//此步骤应该在初始化时完成
var resolutionUniformLocation = gl.getUniformLocation(program,"u_resolution");
var colorUniformLocation = gl.getUniformLocation(program, "u_color");
//属性值从缓冲获取数据,所以我们创建一个缓冲
var positionBuffer = gl.createBuffer();
//绑定点操控全局范围的数据,可以想象成全局变量,下面操作是绑定点指向数据源。
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
//通过绑定点向缓冲中存放数据,这其实就是opengl中的VBO
var positions = [
10,20,
80,20,
10,30,
10,30,
80,20,
80,30,
];
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(positions),gl.STATIC_DRAW);
//这里WEBGL需要强类型数据,所以nwe Float32Array,通过讲数据绑定到绑定点,最终被传递到positionBuffer,后面的参数是数据使用方式
/**
* 渲染代码*/
//画布:两个属性:1,实际像素个数。 2,画布的显示大小 //应该尽可能使用css设置画布大小
//初始化代码只执行一次,渲染代码在每次需要渲染的时候执行
webglUtils.resizeCanvasToDisplaySize(gl.canvas);
//通过gl.viewport将把gl_Position剪裁空间坐标对应到画布像素坐标
gl.viewport(0,0,gl.canvas.width,gl.canvas.height);
//清空画布
gl.clearColor(0,0,0,0);
gl.clear(gl.COLOR_BUFFER_BIT);
//告诉webgl运行那个着色程序
gl.useProgram(program);//设置当前使用的周色程序
//接下来告诉webgl从之前准备的缓冲中获取数据给着色器中的属性
gl.enableVertexAttribArray(positionAttributeLocation);
//指定从缓冲中读取数据的方式
//讲绑定点绑定到缓冲数据
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
//告诉属性怎么从positionBuffer中读取数据,因为已经绑定就是从ARRAY_BUFFER中
var size=2;//每次迭代运行提取两个数据单元
var type=gl.FLOAT; // 每个单位的数据类型是32位浮点型
var normalize=false; //不需要归一化数据
var stride = 0;//0=移动单位*每个单位的占用内存(sizeof(type))
//每次迭代运动多少内存到下一个数据开始点
var offset=0; //从缓冲起始位置开始读取
gl.vertexAttribPointer(
positionAttributeLocation,size,type,normalize,stride,offset
);
//gl.vertexAtrribPointer是将属性绑定到当前ARRAY_BUFFER,所以就绑定到了positionBuffer上
//设置全局变量 分辨率
gl.uniform2f(resolutionUniformLocation,gl.canvas.width,gl.canvas.height);
//运行GLSL着色程序
var primitiveType = gl.TRIANGLES;
var offset=0;
var count=6;
gl.uniform4f(colorUniformLocation,0,0,0,1);//设置黑色
gl.drawArrays(primitiveType,offset,count);
drawRandomRect50();
function drawRandomRect50(){
for(var ii=0;ii<50;++ii){
//创建一个随机矩阵
//并将写入位置缓冲 因为此时位置缓冲是我们绑定在ARRAY_BUFFER绑定点上的最后一个缓冲
setRectangle(gl,randomInt(300),randomInt(300),randomInt(300),randomInt(300));
//设置一个随机颜色
gl.uniform4f(colorUniformLocation,Math.random(),Math.random(),Math.random(),1);
//绘制矩形
gl.drawArrays(gl.TRIANGLES,0,6);
}
function randomInt(range){
return Math.floor(Math.random()*range);
}
function setRectangle(gl,x,y,width,height){
var x1=x;
var x2=x+width;
var y1=y;
var y2=y+height;
//注意gl.bufferData(gl.ARRAY_BUFFER)将会影响到当前绑定的缓冲
//目前只有一个缓冲,如果我们有多个缓冲
//我们需要先将所需缓冲绑定到ARRAY_BUFFER
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
x1,y1,
x2,y1,
x1,y2,
x1,y2,
x2,y1,
x2,y2
]),gl.STATIC_DRAW);
}
}
}
//一下例子绘制50个随机颜色矩形
main();
结果: