Skip to content

Commit 380882e

Browse files
committed
颜色与纹理
varying 变量
1 parent 7ed526c commit 380882e

File tree

4 files changed

+385
-1
lines changed

4 files changed

+385
-1
lines changed

docs/.vitepress/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ module.exports = {
172172
items: [
173173
{ text: '第一章', link: '/WebGL/' },
174174
{ text: '第二章', link: '/WebGL/Chapter2'},
175-
{ text: '第三章', link: '/WebGL/Chapter3'}
175+
{ text: '第三章', link: '/WebGL/Chapter3'},
176+
{ text: '第四章', link: '/WebGL/Chapter4'}
176177
]
177178
}
178179
},

docs/WebGL/Chapter4.md

Lines changed: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
---
2+
editLink: false
3+
outline: deep
4+
outlineText: "33"
5+
---
6+
7+
# 颜色与纹理
8+
9+
# 颜色和纹理
10+
11+
1. 将顶点的其他(非坐标)数据 ————颜色等————传入顶点着色器
12+
2. 发生在顶点着色器和片元着色器之间的从图形到片元的转化,又称为**图元光栅化**
13+
3. 将图像(或纹理)映射到图形或三维对象的表面上
14+
15+
## 将非坐标数据传入顶点着色器
16+
17+
```js
18+
const VSHADER_SOURCE =
19+
'attribute vec4 a_Position;\n' +
20+
'attribute float a_PointSize;\n' +
21+
'void main() {\n' +
22+
'gl_Position = a_Position;\n' +
23+
'gl_PointSize = a_PointSize;\n' +
24+
'}\n'
25+
const FSHADER_SOURCE =
26+
' void main() {\n' +
27+
'gl_FragColor = vec4(1.0, 1.0, 0.0,1.0);\n' +
28+
'}\n'
29+
30+
function main() {
31+
var canvas = document.getElementById('webgl')
32+
var gl = getWebGLContext(canvas)
33+
if (!gl) {
34+
console.error('Failed to get the rendering context for WebGL')
35+
return;
36+
}
37+
38+
// 初始化着色器
39+
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
40+
console.error('Failed to initialize shaders.')
41+
return;
42+
}
43+
44+
// 设置顶点着色器
45+
var n = initVertexBuffers(gl);
46+
47+
if (n < 0) {
48+
console.error('Failed to set the positions of the vertices')
49+
return;
50+
}
51+
52+
// 获取attribut变量的存储位置
53+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
54+
55+
56+
if (a_Position < 0) {
57+
console.error('Failed to get the storage location of a_Position')
58+
return;
59+
}
60+
61+
// 设置canvas背景色
62+
gl.clearColor(0.0, 0.0, 0.0, 1.0)
63+
64+
// 清空canvas
65+
gl.clear(gl.COLOR_BUFFER_BIT);
66+
67+
// 绘制三个点
68+
gl.drawArrays(gl.POINTS, 0, n)
69+
70+
}
71+
72+
73+
function initVertexBuffers(gl) {
74+
var vertices = new Float32Array([
75+
0.0, 0.5, -0.5,-0.5, 0.5,-0.5
76+
])
77+
var n =3 // 点的个数
78+
79+
var sizes = new Float32Array([
80+
10.0, 20.0, 30.0
81+
])
82+
// 创建缓冲区对象
83+
var vertexBuffer = gl.createBuffer();
84+
var sizeBuffer = gl.createBuffer();
85+
if (!vertexBuffer) {
86+
console.error('Failed to create the buffer object')
87+
return -1;
88+
}
89+
90+
// 将缓冲区对象绑定到目标
91+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
92+
93+
94+
// 向缓冲区对象中写入数据
95+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
96+
97+
98+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
99+
100+
101+
// 将缓冲区对象分配给a_Position变量
102+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
103+
104+
105+
// 连接a_Position变量与分配给它的缓冲对象
106+
gl.enableVertexAttribArray(a_Position)
107+
108+
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer)
109+
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
110+
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize')
111+
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0)
112+
gl.enableVertexAttribArray(a_PointSize)
113+
return n
114+
}
115+
116+
```
117+
效果图
118+
![效果图](./images/214631.png)
119+
120+
原理图
121+
![原理图](./images/214041.png)
122+
123+
### gl.vertexAttribPointer() 的步进和偏移参数
124+
125+
> 使用多个缓冲区对象向着色器传递多种数据,比较适合数据量不大的情况. 当程序中的复杂三维图形具有成千上万个顶点时,维护所有顶点的数据很困难.
126+
> WebGL允许我们把顶点的坐标和尺寸数据打包到同一个缓冲区对象中,并通过某种机制分别访问向缓冲区对象中不同种类的数据.
127+
> 可以将顶点的坐标和尺寸数据按照如下方式交错组织
128+
129+
```js
130+
var verticesSizes = new Float32Array([
131+
0.0, 0.5, 10.0,
132+
-0.5, -0.5, 20.0,
133+
0.5, -0.5, 30.0
134+
])
135+
```
136+
137+
如上,我们将集中 逐顶点 的数据(坐标和尺寸)交叉存储在一个数组中,并将数组写入一个缓冲区对象. WebGL就需要有差别地冲缓冲区中获取某种特定数据(坐标或尺寸),
138+
即使用`gl.vertexAttribPointer()`函数的第5个参数`stride`和第6个参数`offset`.
139+
140+
```js
141+
const VSHADER_SOURCE =
142+
'attribute vec4 a_Position;\n' +
143+
'attribute float a_PointSize;\n' +
144+
'void main() {\n' +
145+
'gl_Position = a_Position;\n' +
146+
'gl_PointSize = a_PointSize;\n' +
147+
'}\n'
148+
const FSHADER_SOURCE =
149+
' void main() {\n' +
150+
'gl_FragColor = vec4(1.0, 1.0, 0.0,1.0);\n' +
151+
'}\n'
152+
153+
function main() {
154+
var canvas = document.getElementById('webgl')
155+
var gl = getWebGLContext(canvas)
156+
if (!gl) {
157+
console.error('Failed to get the rendering context for WebGL')
158+
return;
159+
}
160+
161+
// 初始化着色器
162+
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
163+
console.error('Failed to initialize shaders.')
164+
return;
165+
}
166+
167+
// 设置顶点着色器
168+
var n = initVertexBuffers(gl);
169+
170+
if (n < 0) {
171+
console.error('Failed to set the positions of the vertices')
172+
return;
173+
}
174+
175+
// 获取attribut变量的存储位置
176+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
177+
178+
179+
if (a_Position < 0) {
180+
console.error('Failed to get the storage location of a_Position')
181+
return;
182+
}
183+
184+
// 设置canvas背景色
185+
gl.clearColor(0.0, 0.0, 0.0, 1.0)
186+
187+
// 清空canvas
188+
gl.clear(gl.COLOR_BUFFER_BIT);
189+
190+
// 绘制三个点
191+
gl.drawArrays(gl.POINTS, 0, n)
192+
193+
}
194+
195+
196+
function initVertexBuffers(gl) {
197+
var vertices = new Float32Array([ // [!code --]
198+
0.0, 0.5, -0.5,-0.5, 0.5,-0.5 // [!code --]
199+
]) // [!code --]
200+
var verticesSizes = new Float32Array([ // [!code ++]
201+
0.0, 0.5,10.0, -0.5,-0.5,20.0, 0.5,-0.5,30.0 // [!code ++]
202+
]) // [!code ++]
203+
var n =3 // 点的个数
204+
var sizes = new Float32Array([ // [!code --]
205+
10.0, 20.0, 30.0 // [!code --]
206+
]) // [!code --]
207+
// 创建缓冲区对象
208+
var vertexBuffer = gl.createBuffer();// [!code --]
209+
var sizeBuffer = gl.createBuffer(); // [!code --]
210+
var vertexSizeBuffer = gl.createBuffer(); // [!code ++]
211+
if (!vertexSizeBuffer) {
212+
console.error('Failed to create the buffer object')
213+
return -1;
214+
}
215+
216+
// 将缓冲区对象绑定到目标
217+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) // [!code --]
218+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexSizeBuffer) // [!code ++]
219+
220+
221+
// 向缓冲区对象中写入数据
222+
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); // [!code --]
223+
gl.bufferData(gl.ARRAY_BUFFER, verticesSizes, gl.STATIC_DRAW); // [!code ++]
224+
225+
var FSIZE = verticesSizes.BYTES_PER_ELEMENT //数组中每个元素所占的字节数 // [!code ++]
226+
227+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
228+
229+
230+
// 将缓冲区对象分配给a_Position变量
231+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0) // [!code --]
232+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 3, 0) // FSIZE * 3 即指定相邻两个顶点间的字节数,默认为0 // [!code ++]
233+
234+
235+
// 连接a_Position变量与分配给它的缓冲对象
236+
gl.enableVertexAttribArray(a_Position) // 开启分配
237+
238+
239+
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize'); // [!code ++]
240+
241+
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, FSIZE * 3, FSIZE * 2) // [!code ++]
242+
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer) // [!code --]
243+
gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW); // [!code --]
244+
var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize') // [!code --]
245+
gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0) // [!code --]
246+
gl.enableVertexAttribArray(a_PointSize)
247+
return n
248+
}
249+
250+
```
251+
252+
253+
### 修改颜色 (varying 变量)
254+
255+
片元着色器可以用来处理颜色之类的属性。 但是到目前为止,我们都只是在片元着色器中静态地设置颜色,还没有真正研究过片元着色器。虽然现在已经能够将顶点的颜色数据从 javascript 中传递给顶点着色器中的attribute变量,
256+
但是真正能够影响绘制颜色的gl_FragColor 却在片元着色器中。我们需要知道顶点着色器和片元着色器是如何交流的=,这样才能使传入顶点着色器的数据进入片元着色器。
257+
258+
![原理图](../images/vshaderAndFshader.png)
259+
260+
使用`uniform`变量,没法为每个顶点都准备一个值。 使用`varying`变量向片元着色器中传入数据,**varying变量的作用是从顶点着色器向片元着色器传输数据**
261+
262+
```js
263+
const VSHADER_SOURCE =
264+
'attribute vec4 a_Position;\n' +
265+
'attribute vec4 a_Color;\n' + // [!code ++]
266+
'varying vec4 v_Color;\n' + // [!code ++]
267+
'void main() {\n' +
268+
'gl_Position = a_Position;\n' +
269+
'gl_PointSize = 10.0;\n' +
270+
'v_Color = a_Color;\n' + // 将数据传给片元着色器 // [!code ++]
271+
'}\n';
272+
const FSHADER_SOURCE =
273+
'#ifdef GL_ES\n' + // [!code ++]
274+
'precision mediump float;\n' + //精度限定,中精度 // [!code ++]
275+
'#endif\n' + // [!code ++]
276+
'varying vec4 v_Color;\n' + // [!code ++]
277+
' void main() {\n' +
278+
'gl_FragColor = v_Color;\n' + // 从顶点着色器接收数据 // [!code ++]
279+
'gl_FragColor = vec4(1.0, 1.0, 0.0,1.0);\n' + // [!code --]
280+
'}\n'
281+
282+
function main() {
283+
var canvas = document.getElementById('webgl')
284+
var gl = getWebGLContext(canvas)
285+
if (!gl) {
286+
console.error('Failed to get the rendering context for WebGL')
287+
return;
288+
}
289+
290+
// 初始化着色器
291+
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
292+
console.error('Failed to initialize shaders.')
293+
return;
294+
}
295+
296+
// 设置顶点着色器
297+
var n = initVertexBuffers(gl);
298+
299+
if (n < 0) {
300+
console.error('Failed to set the positions of the vertices')
301+
return;
302+
}
303+
304+
// 获取attribut变量的存储位置
305+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position')
306+
307+
308+
if (a_Position < 0) {
309+
console.error('Failed to get the storage location of a_Position')
310+
return;
311+
}
312+
313+
// 设置canvas背景色
314+
gl.clearColor(0.0, 0.0, 0.0, 1.0)
315+
316+
// 清空canvas
317+
gl.clear(gl.COLOR_BUFFER_BIT);
318+
319+
// 绘制三个点
320+
gl.drawArrays(gl.POINTS, 0, n)
321+
322+
}
323+
324+
325+
function initVertexBuffers(gl) {
326+
var verticesSizes = new Float32Array([ // [!code --]
327+
0.0, 0.5,10.0, -0.5,-0.5,20.0, 0.5,-0.5,30.0 // [!code --]
328+
]) // [!code --]
329+
330+
var verticesColors = new Float32Array([ // [!code ++]
331+
// 顶点坐标和颜色 // [!code ++]
332+
0.0, 0.5, 1.0, 0.0, 0.0, // [!code ++]
333+
-0.5, -0.5, 0.0, 1.0, 0.0, // [!code ++]
334+
0.5, -0.5, 0.0, 0.0, 1.0 // [!code ++]
335+
]) // [!code ++]
336+
337+
var n =3 // 点的个数
338+
339+
// 创建缓冲区对象
340+
var vertexSizeBuffer = gl.createBuffer(); // [!code --]
341+
342+
var vertexColorBuffer = gl.createBuffer(); // [!code ++]
343+
if (!vertexColorBuffer) {
344+
console.error('Failed to create the buffer object')
345+
return -1;
346+
}
347+
348+
// 将缓冲区对象绑定到目标
349+
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer)
350+
351+
// 向缓冲区对象中写入数据
352+
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW)
353+
354+
var FSIZE = verticesColors.BYTES_PER_ELEMENT //数组中每个元素所占的字节数
355+
356+
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
357+
358+
359+
// 将缓冲区对象分配给a_Position变量
360+
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 5, 0)
361+
362+
// 连接a_Position变量与分配给它的缓冲对象
363+
gl.enableVertexAttribArray(a_Position) // 开启分配
364+
365+
366+
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
367+
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 5, FSIZE * 2)
368+
369+
gl.enableVertexAttribArray(a_Color)
370+
371+
372+
373+
return n
374+
}
375+
376+
```
377+
378+
**下面者三句 必须要 至于为什么要这个精度限定,还没找到答案, 但是没有这三局,初始化着色器会失败(这个问题找了半天)**
379+
```js
380+
'#ifdef GL_ES\n' +
381+
'precision mediump float;\n' + //精度限定,中精度
382+
'#endif\n'
383+
```

docs/WebGL/images/214041.png

257 KB
Loading

docs/WebGL/images/214631.png

2.38 KB
Loading

0 commit comments

Comments
 (0)