2019年在浏览器用原生js写WebGL,绘制图形;
因为JavaScript高级程序设计(第三版)中的运行书上15.3WebGL部分的代码时在chrome和firefox浏览器下报错,在后面我网上初步找了一圈,好像没人做出真正可以用的代码;所以我就自己重写了一下:
书上代码有些错误,错误原因应该是书出了太久,WebGL的规则已经有些改变了.并且,可能浏览器也有一些相关的规则改变了;
新的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用WebGL上下文对象绘图</title>
</head>
<body>
<canvas id="drawing" width="800" height="800">您的浏览器不支持canvas标签;</canvas>
<!--开始04.使用脚本script标签编写着色器文本;-->
<!--开始使用脚本script标签编写顶点着色器文本;-->
<script type="x-webgl/x-shader" id="vertex-shader">
#ifdef GL_ES
precision mediump float;
#endif
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}
</script>
<!--结束使用脚本script标签编写顶点着色器文本;-->
<!--开始使用脚本script标签编写片段着色器文本;-->
<script type="x-webgl/x-shader" id="fragment-shader">
#ifdef GL_ES
precision mediump float;
#endif
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
</script>
<!--结束使用脚本script标签编写片段着色器文本;-->
<!--结束04.使用脚本script标签编写着色器文本;-->
<script>
var drawing = document.getElementById("drawing");
var theContextSetting;
var gl;
var buffer;
var vertices;
var thisProgram;
var vertexShader;
var fragmentShader;
var node;
if (drawing.getContext){
try {
theContextSetting = {
alpha: true,
depth: true,
stencil: false,
antialias: true,
premultipliedAlpha: true,
preserveDrawingBuffer: false
}
gl = drawing.getContext("experimental-webgl",theContextSetting);
} catch (ex) {
console.log("浏览器无法创建WebGL上下文并抛出错误,此时抛出的错误参数ex--->",ex);
}
if (gl){
//开始01.准备绘图;
gl.clearColor(1.0,0.0,1.0,1.0); //首先必须使用clearColor()方法来指定要使用的颜色值,该方法接收4个参数: 红、绿、蓝和透明度;每个参数必须是一个0到1之间的数值,表示每种分量在最终颜色中的强度;
gl.clear(gl.COLOR_BUFFER_BIT); //调用了clear()方法,传入的参数gl.COLOR_BUFFER_BIT告诉WebGL上下文对象使用之前定义的颜色来填充相应区域;
//结束01.准备绘图;
//开始02.定义WebGL上下文对象的视口;
gl.viewport(0,0,drawing.width,drawing.height);
//结束02.定义WebGL上下文对象的视口;
//开始03.设置缓冲区;
buffer = gl.createBuffer();
vertices = new Float32Array([0,1,1,-1,-1,-1]);
//开始将数据放入缓冲区;
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
//结束将数据放入缓冲区;
//结束03.设置缓冲区;
//开始05.编写着色器对象并链接到着色器程序中;
//开始编写顶点着色器对象;
node = document.getElementById("vertex-shader");
vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, node.text);
gl.compileShader(vertexShader);
//结束编写顶点着色器对象;
//开始编写片段着色器对象;
node = document.getElementById("fragment-shader");
fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, node.text);
gl.compileShader(fragmentShader);
//结束编写片段着色器对象;
//开始创建着色器程序并把两个着色器对象链接到到着色器程序中;
thisProgram = gl.createProgram();
gl.attachShader(thisProgram, vertexShader);
gl.attachShader(thisProgram, fragmentShader);
gl.linkProgram(thisProgram);
gl.useProgram(thisProgram);
//结束创建着色器程序并把两个着色器对象链接到到着色器程序中;
//结束05.编写着色器对象并链接到着色器程序中;
//开始06.为着色器传入值;
var vertexSetSize = 2;
var vertexSetCount = vertices.length/vertexSetSize;
var uColor;
var aVertexPosition;
//开始为片段着色器进行赋值;
uColor = gl.getUniformLocation(thisProgram, "uColor");
var uColorValue = [1.0,1.0,0.0,1.0];
gl.uniform4fv(uColor,uColorValue);
//结束为片段着色器进行赋值;
//开始为顶点着色器进行赋值;
aVertexPosition = gl.getAttribLocation(thisProgram, "aVertexPosition");
gl.enableVertexAttribArray(aVertexPosition);
gl.vertexAttribPointer(aVertexPosition, vertexSetSize, gl.FLOAT, false, 0, 0);
//结束为顶点着色器进行赋值;
//结束06.为着色器传入值;
//开始07.绘图;
gl.drawArrays(gl.TRIANGLES,0,vertexSetCount);
//结束07.绘图;
} else {
console.log("您的浏览器不支持WebGL画图;");
}
}
</script>
</body>
</html>
如果有兴趣,可以自己对比两者代码,了解到底有那些部份改变了;了解原书作者在写那书时,可能没考虑到那些东西;
原书代码如下:
<!DOCTYPE html>
<html>
<head>
<title>WebGL Example</title>
</head>
<body>
<canvas id="drawing" width="1200" height="1200">Your browser doesn't suppor the canvas tag.(您的浏览器不支持canvas标签;)</canvas>
<script type="x-webgl/x-shader" id="vertex-shader">
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}
</script>
<script type="x-webgl/x-shader" id="fragment-shader">
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
</script>
<script>
window.onload = function(){
var drawing = document.getElementById("drawing");
var gl;
var program;
var vertexShader;
var fragmentShader;
var node;
if (drawing.getContext){
try {
var theContextSetting = {
alpha: true,
depth: true,
stencil: false,
antialias: true,
premultipliedAlpha: true,
preserveDrawingBuffer: false
}
gl = drawing.getContext("experimental-webgl",theContextSetting);
*/
} catch (ex) {
//noop;
}
if (gl){
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0, drawing.height, drawing.width, drawing.height);
//create the vertex shader
node = document.getElementById("vertex-shader");
vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, node.text);
gl.compileShader(vertexShader);
//create the fragment shader
node = document.getElementById("fragment-shader");
fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, node.text);
gl.compileShader(fragmentShader);
//create the shader program
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
//debugging
if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)){
console.log(gl.getShaderInfoLog(vertexShader));
}
if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)){
console.log(gl.getShaderInfoLog(fragmentShader));
}
if(!gl.getProgramParameter(program, gl.LINK_STATUS)){
console.log(gl.getProgramInfoLog(program));
}
//define three vertices, x and y for each
var vertices = new Float32Array([ 0, 1, 1, -1, -1, -1 ]),
buffer = gl.createBuffer(),
vertexSetSize = 2,
vertexSetCount = vertices.length/vertexSetSize,
uColor, aVertexPosition;
//put data into the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
//pass color to fragment shader
uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(uColor, [ 0, 0, 0, 1 ]);
//pass vertex information to shader
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(aVertexPosition);
gl.vertexAttribPointer(aVertexPosition, vertexSetSize, gl.FLOAT, false, 0, 0);
//draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, vertexSetCount);
} else {
alert("Your browser doesn't support WebGL;");
}
}
};
</script>
</body>
</html>
注:以上代码我修改过,但没多大改变,和原书作者的意思差不多;如果有兴趣,可以结合两份代码进行对比;不懂的话,到2019年6年前可以问我,有时间尽量回答;过了时间,可能我就不作回答了;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)