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年前可以问我,有时间尽量回答;过了时间,可能我就不作回答了;
2019年在浏览器用原生js写WebGL,绘制图形;的更多相关文章
- 原生 js 写分页
欢迎留言或者加本人QQ172360937咨询 这段代码是用原生 js 写的一个分页的效果 <!doctype html> <html lang="en"> ...
- 原生js写Ajax
//原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.挺对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...
- 原生js写的贪吃蛇网页版游戏特效
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <bo ...
- 用原生JS写移动动画案例及实际应用
js很强大 相信很多人都知道,那么它有哪些强大之处呢?有兴趣的人可以去查查,这里就不赘述了,因为不在本片文章讨论的范围. 我们要讲的是怎么用原生JS写移动动画?我们先举一个最简单的动画例子,很多网站的 ...
- 原生JS写的ajax函数
参照JQuery中的ajax功能,用原生JS写了一个ajax,功能相对JQuery要少很多,不过基本功能都有,包括JSONP. 调用的方式分为两种: 1. ajax(url, {}); 2. ajax ...
- 用原生js写一个"多动症"的简历
用原生js写一个"多动症"的简历 预览地址源码地址 最近在知乎上看到@方应杭用vue写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生js来实现. 会动的简历实现 ...
- 用原生JS写一个网页版的2048小游戏(兼容移动端)
这个游戏JS部分全都是用原生JS代码写的,加有少量的CSS3动画,并简单的兼容了一下移动端. 先看一下在线的demo:https://yuan-yiming.github.io/2048-online ...
- 使用原生js写ajax
// 使用原生js 封装ajax // 兼容xhr对象 function createXHR(){ if(typeof XMLHttpRequest != "undefined") ...
- 原生js写的一个弧形菜单插件
弧形菜单是一种半弧式或者全弧形菜单,是一种不同于传统横向或者竖向菜单形式的菜单.最近在网上看到好多人写出了这种效果,于是也尝试自己写了一个. 实现方式:原生态js 主要结构: 1.参数合并 var d ...
- 自己用原生JS写的轮播图,支持移动端触屏滑动,面向对象思路。分页器圆点支持click和mouseover。
自己用原生javascript写的轮播图,面向对象思路,支持移动端手指触屏滑动.分页器圆点可以选择click点击或mouseover鼠标移入时触发.图片滚动用的setInterval,感觉setInt ...
随机推荐
- [转帖]s3fs - 使用S3FS存储桶目录允许其他用户使用权限
https://www.coder.work/article/6661505 我在使用S3FS时遇到问题.我正在使用 ubuntu@ip-x-x-x-x:~$ /usr/bin/s3fs --ve ...
- [转帖]JMeter学习(二)搭建骨架--JMeter重要组件
https://www.cnblogs.com/tian-yong/p/4460665.html JMeter的属性和变量 JMeter属性统一定义在jmeter.properties文件中.JMet ...
- [转帖]InnoDB表聚集索引层高什么时候发生变化
导读 本文略长,主要解决以下几个疑问 1.聚集索引里都存储了什么宝贝 2.什么时候索引层高会发生变化 3.预留的1/16空闲空间做什么用的 4.记录被删除后的空间能回收重复利用吗 1.背景信息 1.1 ...
- Oracle 查看所有表大小的SQL
Oracle 查看所有表大小的SQL 比较坑的是 lob 字段和 表的大小不在一个地方 为了出结果 我这边使用了 union all 慢的一逼... SELECT sum( tablesize ), ...
- Mysql localhost 无法登录 root用户的处理过程
问题说明: 前段时间同事修改密码, 但是发现修改了密码之后,外面可以连接root用户, 但是本地无法连接了. 怀疑是密码修改存在问题,需要重新进行处理 这里进行简单的描述. 问题现象 使用 mysql ...
- echarts饼状图自定义legend的样式付费
先看效果图 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- Docker系列教程01--简介
Docker 入门教程 作者: 阮一峰 日期: 2018年2月 9日 2013年发布至今, Docker 一直广受瞩目,被认为可能会改变软件行业. 但是,许多人并不清楚 Docker 到底是什么, ...
- # 重要-即时通讯IM开源项目OpenIM关于版本管理及v2.3.0发布计划
越来越多的客户把OpenIM用到了生产环境,由于新特性持续迭代和bug修复,会涉及到后续的升级方案,为了让大家后续从容应对,本文重点总结OpenIM对未来版本管理的思路和方案.同时,官网对于文档进行了 ...
- vim 从嫌弃到依赖(6)——插入模式
插入模式是vim中主要用来处理输入的一种模式,在这种模式中,用户的输入的字符会显示在窗口中.该模式中的行为与在普通编辑器中输入类似.由于在该模式中输入的字符会被当做有效输入,因此该模式下涉及的到命令也 ...
- 6.8 Windows驱动开发:内核枚举Registry注册表回调
在笔者上一篇文章<内核枚举LoadImage映像回调>中LyShark教大家实现了枚举系统回调中的LoadImage通知消息,本章将实现对Registry注册表通知消息的枚举,与LoadI ...