WebGL绘制一个点(HTML框架文件)
源码下载学习建议
- 初学者,前几十节入门课程一定要按照顺序学习,不要跳过
- 学习前面入门课程,可以不求甚解,有个整体印象即可
- 学习前面入门课程,可以不用动手写代码,但是一定要动手改代码,做到复制、粘贴、替换就可以
- 后面关于WebGL硬件、渲染管线、着色器语言、数学、光照模型等章节根据需要可以随时阅读,对照前面的入门案例与后面的系统总结学习更好
- 明白自己欠缺哪些知识,有选择地学习本教程
- 本教程入门部分以具体案例作为驱动学习,面向工程编程,不面向科学编程
本节课不需要记住具体知识,有个框架印象即可,尝试更改几个参数,体验效果,互动学习,可以让自己更沉浸其中
本着先实验,后讲解的学习精神,先给大家列出一个完整的WebGL代码,麻雀虽小,五脏俱全,可以通过上面链接下载源码,是一个.html格式文档,也就是浏览器可以打开并解析的文档。 这一节课涉及的关键词有超文本语言HTML、脚本语言Javascript、着色器语言GLSL ES和WebGL API。学习之前先看看自己懂什么知识,不懂什么知识,课程尽 量在新知识学习时照顾不同专业和领域的人,但是个人最起码有基本的编程能力。对于编程基础非常好只是恰好之前没接触WebGL的相关知识,建议可以利用本教程的源代码边修改边测试边学习,没必要 上来就先把各个模块的知识补充完再来学习。如果你擅长java、Python等语言,学习Javascript语言也不是什么难事,你对C语言非常了解,与C一样是强类型的着色器语言GLSL ES也很好理解。对于经常用 C++和OpenGL API开发基于操作系统应用的工程师来说,学习WebGL只是迁移一个生态系统,切换到了互联网生态圈,图形学本质的东西没有变。对于你来说,主要是了解前端的一些知识,网上关于html和Javascript 的教程非常多,但是都是侧重于网页设计,对于你来说很多知识是冗余的,教程又臭又长,估计也没有学习的心情。本教程为了照顾这部分人的需求会讲解html的知识,但是仅仅讲解本节课会用到的,多余的不会讲解, 遇到不懂得,不必深究,互联网是一个大生态,不可能什么都会。大家可以把这节课的html文档当成WebGl开发的一个HTML框架,平时只需要写关于图形学的内容,对于body、head、meta等名词不用管什么意思。你当它 不存在,每一次写程序直接拿过来补充添加就行。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>使用WebGL绘制一个点</title> 6 </head> 7 <body> 8 <!--canvas标签创建一个宽高均为500像素,背景为蓝色的矩形画布--> 9 <canvas id="webgl" width="500" height="500" style="background-color: blue"></canvas> 10 11 12 <script> 13 //通过getElementById()方法获取canvas画布 14 var canvas=document.getElementById('webgl'); 15 //通过方法getContext()获取WebGL上下文 16 var gl=canvas.getContext('webgl'); 17 18 //顶点着色器源码 19 var vertexShaderSource = '' + 20 'void main(){' + 21 //给内置变量gl_PointSize赋值像素大小 22 ' gl_PointSize=20.0;' + 23 //顶点位置,位于坐标原点 24 ' gl_Position =vec4(0.0,0.0,0.0,1.0);' + 25 '}'; 26 27 //片元着色器源码 28 var fragShaderSource = '' + 29 'void main(){' + 30 //定义片元颜色 31 ' gl_FragColor = vec4(1.0,0.0,0.0,1.0);' + 32 '}'; 33 34 //初始化着色器 35 var program = initShader(gl,vertexShaderSource,fragShaderSource); 36 //开始绘制,显示器显示结果 37 gl.drawArrays(gl.POINTS,0,1); 38 39 //声明初始化着色器函数 40 function initShader(gl,vertexShaderSource,fragmentShaderSource){ 41 //创建顶点着色器对象 42 var vertexShader = gl.createShader(gl.VERTEX_SHADER); 43 //创建片元着色器对象 44 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 45 //引入顶点、片元着色器源代码 46 gl.shaderSource(vertexShader,vertexShaderSource); 47 gl.shaderSource(fragmentShader,fragmentShaderSource); 48 //编译顶点、片元着色器 49 gl.compileShader(vertexShader); 50 gl.compileShader(fragmentShader); 51 52 //创建程序对象program 53 var program = gl.createProgram(); 54 //附着顶点着色器和片元着色器到program 55 gl.attachShader(program,vertexShader); 56 gl.attachShader(program,fragmentShader); 57 //链接program 58 gl.linkProgram(program); 59 //使用program 60 gl.useProgram(program); 61 //返回程序program对象 62 return program; 63 } 64 </script> 65 </body> 66 </html>
体验测试
没有永久的真理,任何语言都是对当前实际现象的总结。如果你从不了解图形学,建议你分别进行下面的测试,相比文字更容易记住视觉的变化。
- 第22行代码,更改为gl_PointSize=10.0,观察屏幕点的大小变化
- 第24行代码,更改为gl_Position =vec4(0.5,0.5,0.0,1.0),观察屏幕点的位置变化
- 第31行代码,更改为gl_FragColor = vec4(0.0,0.0,1.0,1.0),观察屏幕点的颜色变化
代码执行流程简述
整体代码基本原则是从上到下执行,Javascript的执行细节不再详述。程序执行到35行时,程序会调用第40行初始化着色器函数initShader(),主要是把顶点着色器源代码vertexShaderSource, 片元着色器源代码fragShaderSource,进行编译处理,并通过CPU控制GPU进行相关的配置,等待下一步的相关操作,程序执行到37行代码,drawArrays会告诉GPU开始把设置好的顶点绘制出来,顶点从 gl_Position =vec4(0.0,0.0,0.0,1.0);设置的空间坐标,到显示在显示器上的像素,经历一个比较复杂的过程,也就是渲染管线,过去是固定管线,现在支持可编程,可以暂不去了解。