今天下班比较早,早早吃完饭,开始我们的第二课,给三角形和正方形涂上颜色。
本人声明:这是我学习webGL 的笔记,仅供参考,有不当之处,请多多指教!
现对上一课做个总结:
(1)使用具有"x-shader/x-vertex"和"x-shader/x-fragment"类型的script标签定义了顶点渲染器和片段渲染器;
(2)在initGL函数中初始化了一个WebGL的上下文;
(3)使用getShader和initShaders函数装载渲染器到一个WebGL对象中;
(4)定义了模型矩阵以及操作该矩阵的函数loadIdentity、multMatrix和mvTranslate;
(5)定义了投影矩阵pMatrix和一个操作该矩阵的函数perspective;
(6)定义了setMatrixUniforms函数用于将模型视图矩阵和投影矩阵,以便渲染器根据initBuffers加载场景缓存区;
(7)定义场景绘制函数drawScene;
(8)定义webGLStart函数在网页起始位置设置webGL的环境;
(9)最后用body的onload事件调用webGLStart函数
本节课,我们依然沿用这个编程思路,对代码作少许改动,为图形填上颜色。
在上节课代码的基础上我们做如下变化(红色为添加代码):
(1)顶点渲染器代码:
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;//顶点位置变化属性
[color=red] attribute vec4 aVertexColor;//顶点颜色变化属性[/color]
uniform mat4 uMVMatrix;//同一变量 模型矩阵
uniform mat4 uPMatrix;//同一变量 投影矩阵
[color=red]varying vec4 vColor;//可变颜色 输出值[/color]
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
[color=red] vColor = aVertexColor;[/color]
}
</script>
(2)片段渲染器(像素渲染器):
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
[color=red]varying vec4 vColor;[/color]
void main(void) {
[color=red]gl_FragColor = vColor;//此处 由上一课的直接赋值变为接受顶点渲染器的输出值vColor[/color]
}
(3)initShaders()函数:
[color=red]shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");//这是关于我们如何针对每个顶点获得一个传入到顶点渲染器属性引用的处理 -----------渲染器绑定颜色变化矩阵
gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);//转化为数组[/color]
(4)initBuffers函数:
triangleVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
var vertices = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
triangleVertexPositionBuffer.itemSize = 3;
triangleVertexPositionBuffer.numItems = 3;
[color=red]//设置三角形颜色缓存
triangleVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
var colors = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
triangleVertexColorBuffer.itemSize = 4;
triangleVertexColorBuffer.numItems = 3;[/color]
squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices = [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
squareVertexPositionBuffer.itemSize = 3;
squareVertexPositionBuffer.numItems = 4;
[color=red]//设置正方形颜色矩阵
squareVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
colors = [];
for (var i=0; i < 4; i++) {
colors = colors.concat([0.5, 0.5, 1.0, 1.0]);
}
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
squareVertexColorBuffer.itemSize = 4;
squareVertexColorBuffer.numItems = 4;[/color]
(5)drawSence函数:
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);//绑定三角形颜色缓存
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);
mat4.translate(mvMatrix, [3.0, 0.0, 0.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);//绑定正方形颜色缓存
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms();
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
至此,我么针对上一课的代码的改动已经完成,结果是:我们的三角形和正方形都有了渐变的颜色而且是光滑的!如下图:
在此,需要补充以下几点:
(1)shader的几个变量:
1.uniform变量
uniform变量是外部application程序传递给(vertex和fragment)shader的变量。因此它是application通过函数glUniform**()函数赋值的。在(vertex和fragment)shader程序内部,uniform变量就像是C语言里面的常量(const ),它不能被shader程序修改。(shader只能用,不能改)
如果uniform变量在vertex和fragment两者之间声明方式完全一样,则它可以在vertex和fragment共享使用。(相当于一个被vertex和fragment shader共享的全局变量)
uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。
以下是例子:
uniform mat4 viewProjMatrix; //投影+视图矩阵
uniform mat4 viewMatrix; //视图矩阵
uniform vec3 lightPosition; //光源位置
2.attribute变量
attribute变量是只能在vertex shader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用)
一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。
在application中,一般用函数glBindAttribLocation()来绑定每个attribute变量的位置,然后用函数glVertexAttribPointer()为每个attribute变量赋值。
以下是例子:
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord;
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
3.varying变量
varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。application不能使用此变量。
以下是例子:
// Vertex shader
uniform mat4 u_matViewProjection;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoord; // Varying in vertex shader
void main(void)
{
gl_Position = u_matViewProjection * a_position;
v_texCoord = a_texCoord0;
}
// Fragment shader
precision mediump float;
varying vec2 v_texCoord; // Varying in fragment shader
uniform sampler2D s_baseMap;
uniform sampler2D s_lightMap;
void main()
{
vec4 baseColor;
vec4 lightColor;
baseColor = texture2D(s_baseMap, v_texCoord);
lightColor = texture2D(s_lightMap, v_texCoord);
gl_FragColor = baseColor * (lightColor + 0.25);
}
(2)shader渲染器的渲染过程,如下图:
此图,显示了显卡渲染图形的过程,每次调用像drawArrays这样的函数,WebGL都要处理先前以属性(如第一课中用于顶点的缓冲区)和统一变量(其用于投影矩阵和模型视图矩阵)的形式提交给它的数据,并将其传入到顶点渲染器。
对每个顶点调用一次顶点渲染器,每次都为该顶点设置合适的属性。同时,将统一变量传入到顶点渲染器。但是,统一变量正如它们的名字,在调用的过程并不发生改变。顶点渲染器用第一课中提到的这个数据来工作,它使用投影和模型视图矩阵以便顶点能根据当前的模型视图状态来将其置入场景中和在场景中移动,并将结果放入varying variables中。它也能输出一些varying variables。其中一个比较特殊的是gl_Position,它是必须的,它包含了渲染器完成顶点着色以后的顶点坐标。
一旦顶点渲染器完成其工作,WebGL就会从这些可变变量中将三维图像转化为二维图像,接着它在图像中为每一个像素调用一次片段渲染器。(由于这个原因,在一些三维图像系统中片段渲染器被认作为像素渲染器。)当然,这意味着片段渲染器用于那些没有顶点的像素——即,顶点结束的像素之间的像素。对于组成三角形的顶点位置,WebGL将通过线性插值的方法在两个顶点间填充一些像素。线性插值处理填充了组成可见三角形的顶点分隔的空间。片段渲染器的作用是返回每一个插值点的颜色,它在gl_FragColor可变变量中返回这个颜色值。
一旦片段渲染器处理完成,WebGL对其结果稍作混合,再将其放入帧缓冲区(frame buffer),此即屏幕上最终显示的东西。
很明显,这一课最重要的就是要教会你如何通过所有运行在片段渲染器上的JavaScript代码给顶点着色,我们不会从一个顶点到另一个顶点来直接获取。
我们所采用的方法是基于如下事实:我们能从顶点渲染器中传出可变变量(而不是位置信息),然后我们可以在片段渲染器中重新获得它们。因此,我们把颜色信息传入到顶点渲染器,然后顶点渲染器直接将该信息置入一个可以在片段渲染器中获得的可变变量中。
这种方法很方便地为我们提供了颜色的渐变,且不花费任何代价。当在顶点间生成片段时,除了位置信息,所有顶点渲染器设置的可变变量都是线性插值的。顶点间的线性颜色插值为我们提供了平滑渐变,就像你在图中的三角形看到的那样。
最后,希望你能在上一课代码的基础上,改出本课的效果,祝君好运!
- 大小: 7.5 KB
- 大小: 40.2 KB
分享到:
相关推荐
【标题】"WebGL喷泉粒子发射动画特效"是一个利用WebGL技术实现的创新视觉效果,它基于HTML5的Canvas 2D接口,为用户提供了一种全屏的彩虹粒子喷泉展示。这种特效通常用于网站设计,提升用户体验,或者作为交互式艺术...
本书名为《交互式计算机图形学——基于WebGL的自顶向下技术 英文第七版》,是电子工业出版社出版的教材,由Edward Angel与Dave Shreiner共同撰写,张荣华、宋雨等人翻译。该书的标签为“计算机图形学”和“WebGL”,...
基于WebGL和AJAX的WEB3D应用研究——以在线3D协作交互式设计为例 本文主要研究基于WebGL和AJAX的WEB3D应用,提出了一套WEB3D引擎的构建方案,并以多人在线协作式3D设计为例,给出了整套架构方案的代码实现。WEB3D...
3. **颜色与光照**:介绍颜色理论,包括RGB、RGBA模型,以及WebGL中的颜色混合和透明度处理。同时,讲解光照模型,如环境光、漫射光、镜面光等。 4. **顶点和图元**:讲解几何体的基本构建块——顶点,以及如何使用...
在“HiWebGL-《拥抱 3D 网络世界 —— WebGL 的现状和未来》”中,可能包含以下内容: 1. **上下文创建**:在JavaScript中,我们使用`canvas.getContext('webgl')`来获取WebGL渲染上下文,这是开始所有WebGL操作的...
标题提到的问题——"解决webgl输入框无法输入中文插件",是WebGL应用中常见的一个挑战。通常,当用户尝试在WebGL场景中使用HTML输入框输入中文时,可能会遇到输入困难或无法输入的情况。这主要是因为WebGL与HTML元素...
3. **着色器**:WebGL使用两种类型的着色器——顶点着色器和片段着色器。顶点着色器处理顶点数据,片段着色器决定像素颜色。 4. **缓冲区**:WebGL使用缓冲区存储顶点数据,如位置、颜色和纹理坐标。`gl.bindBuffer...
在WebGL编程中,着色器是至关重要的组成部分,它们负责处理图形渲染的计算工作。在WebGL的上下文中,着色器分为两种主要类型:顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。这些着色器程序可以使用...
本文将详细介绍一种新的解决方案——WebGL着色器,它能够帮助开发者实现几乎任何类型的视频滤镜效果。 #### 二、问题概述及传统方法局限性 ##### 2.1 CSS3滤镜的局限性 在讨论WebGL着色器之前,我们首先回顾一下...
##### WebGL——技术定义 WebGL是一种用于在Web浏览器中绘制3D图形的标准API(应用程序编程接口)。它基于OpenGL ES 2.0标准的一个子集,并且被设计成可以直接在HTML5的canvas元素上运行,无需任何插件或额外的软件...
课程分享——地图Web3D可视化-WebGL、Three.js,附源码 课程概述 - 本课程讲解如何在web上实现地图3D可视化 - 学习本课程有前端基础即可,如果了解three.js更好 适用人群 有前端基础,想基于Web实现地图数据的3D...
- 本书最后章节提供了一个完整的实战项目——开发一个基于WebGL的赛车游戏应用。 - 该项目涵盖了从设计到实现的全过程,包括3D模型的选择、场景布局的设计、物理引擎的集成以及用户界面的开发等方面。 - 通过实际...
在本项目"html5_3d_webgl_多个旋转地球materials"中,我们关注的是HTML5的一个强大特性——WebGL,这是一种用于在浏览器中实现3D图形的API。WebGL基于OpenGL标准,允许开发者在无需任何插件的情况下在网页上呈现复杂...
3. **顶点着色器和片段着色器**:WebGL使用两种主要的着色器——顶点着色器和片段着色器。顶点着色器处理3D几何,而片段着色器决定像素的颜色。学习者需要编写GLSL(OpenGL Shading Language)代码来实现这两个着色...
Unity 2019.3引入了新的渲染管线——Universal Render Pipeline (URP),这是一个高性能、跨平台的渲染系统,旨在提高渲染质量和效率。Universal WebGL Template就是基于URP的WebGL构建选项。使用此模板,你可以利用...
本篇将详细介绍四个与WebGL相关的函数库——cuon-matrix、cuon-utils、webgl-debug以及webgl-utils,它们是WebGL开发中的常用工具,极大地简化了WebGL编程。 1. cuon-matrix: cuon-matrix是一个专门处理矩阵运算...
3. **着色器**:WebGL使用两种类型的着色器——顶点着色器和片段着色器。顶点着色器处理每个顶点,而片段着色器处理每个像素。这些着色器用GLSL(OpenGL Shading Language)编写,通过`gl.createShader()`和`gl....
在这个场景中,我们提到的几个JavaScript文件——cuon-matrix.js, cuon-utils.js, webgl-debug.js, 和 webgl-utils.js,都是WebGL编程中常用的公用函数库,它们为开发者提供了便利的功能,简化了WebGL编程的复杂性。...
交互式计算机图形学 基于WEBGL的自顶向下方法 原书第7版
4. **着色器(Shader)**:WebGL使用两种类型的着色器——顶点着色器和片段着色器。顶点着色器处理每个顶点,而片段着色器处理像素颜色。它们是用GLSL(OpenGL Shading Language)编写的,并通过`gl.createShader()`和...