算法
递增的三元子序列
给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。
数学表达式如下:
如果存在这样的 i, j, k, 且满足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。
var increasingTriplet = function(nums) {
if(nums.length < 3) return false;
var first = Number.MAX_SAFE_INTEGER;
var second = Number.MAX_SAFE_INTEGER;
for(let i=0; i<nums.length; i++){
if (nums[i] > second) {
return true
} else if (nums[i] < first) {
first = nums[i];
} else if(nums[i] > first && nums[i] < second){
second = nums[i]
}
}
return false;
};
纹理
向模型上贴的图片我们称之为纹理,将纹理贴到模型的过程我们成为纹理映射。
纹理映射
- 准备好映射到集合图形上的纹理图像
- 为几何图形配置纹理映射方式
- 加载纹理图像,对其进行一些配置,以在 WebGL 中使用它
- 在片元着色器中将相应的纹素从纹理中抽取出来,并将纹素的颜色赋给片元
纹理坐标
纹理坐标是纹理图像上的坐标,通过纹理坐标可以在纹理图像上获取纹素颜色。WebGL 中的纹理坐标系统是二维的。为了和常见的二维坐标系分开,使用 s 和 t 作为坐标轴
initVertexBuffers(gl){
var verticesTexCoords = new Float32Array(
[
// -0.5, 0.5, 0.0, 1.0,
// -0.5, -0.5, 0.0, 0.0,
// 0.5, 0.5, 1.0, 1.0,
// 0.5, -0.5, 1.0, 0.0,
-0.5, 0.5, -0.3, 1.7,
-0.5, -0.5, -0.3, -0.2,
0.5, 0.5, 1.7, 1.7,
0.5, -0.5, 1.7, -0.2
]
);
var n=4;//顶点数目
//创建缓冲区对象
var vertexTexCoordBuffer = gl.createBuffer();
if(!vertexTexCoordBuffer){
console.log("Failed to create thie buffer object");
return -1;
}
//将缓冲区对象保存到目标上
gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
//向缓存对象写入数据
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if(a_Position < 0){
console.log("Failed to get the storage location of a_Position");
return -1;
}
//将缓冲区对象分配给a_Postion变量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE*4, 0);
//连接a_Postion变量与分配给它的缓冲区对象
gl.enableVertexAttribArray(a_Position);
//将纹理坐标分配给a_TexCoord并开启它
var a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
if(a_TexCoord < 0){
console.log("Failed to get the storage location of a_TexCoord");
return -1;
}
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE*4, FSIZE*2);
gl.enableVertexAttribArray(a_TexCoord);
return n;
},
initTextures(gl, n){
var texture = gl.createTexture(); //创建纹理对象
if(!texture){
console.log('Failed to create the texture object');
return false;
}
//获取u_Sampler的存储位置
var u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler');
if (!u_Sampler) {
console.log('Failed to get the storage location of u_Sampler');
return false;
}
var image = new Image();//创建一个image对象
if (!image) {
console.log('Failed to create the image object');
return false;
}
//注册图像加载时间的响应函数
image.onload = function () {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);//对纹理图像进行y轴反转
//开启0号纹理单元
gl.activeTexture(gl.TEXTURE0);
//向target绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);
//配置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);
//配置纹理图像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);
//将0号纹理传递给着色器
gl.uniform1i(u_Sampler, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, n);//绘制矩形
};
//浏览器开始加载图像
image.src = img
return true;
}
var VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
gl_Position = a_Position;
v_TexCoord = a_TexCoord;
}
`;
var FSHADER_SOURCE = `
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main() {
gl_FragColor = texture2D(u_Sampler, v_TexCoord);
}
`;
var gl = canvas.getContext('webgl');
initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)
this.gl = gl;
var n = this.initVertexBuffers(gl)
gl.clearColor(0.0, 0.0, 0.0, 1.0);
this.initTextures(gl, n);
- 顶点着色器中接收顶点的纹理坐标,光栅化后传递给片元着色器
- 片元着色器根据片元的纹理坐标,从纹理图像中抽取出纹素颜色,赋给当前片元。
- 设置顶点的纹理坐标
- 准备待加载的纹理图像,令浏览器读取它
- 监听纹理图像的加载事件,一旦加载完成,就在 WebGL 系统中使用纹理
使用纹理之前需要先创建纹理,gl.createTexture(),通过gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);对纹理进行 Y 轴转换,因为纹理坐标系和 webGL 坐标系 Y 轴是相反的,通过gl.activeTexture(gl.TEXTURE0);激活纹理单元(纹理单元一般有 8 个,一般都是通过对 8 个纹理单元进行处理),绑定纹理对象gl.bindTexture(gl.TEXTURE_2D, texture);,纹理对象不能单独处理,只能通过将纹理对象绑定到缓冲区对象上才能处理
纹理参数处理,纹理参数包括TEXTURE_MIN_FILTER(纹理放大)、TEXTURE_MAG_FILTER(纹理缩小)、TEXTURE_WRAP_S(纹理水平填充)、TEXTURE_WRAP_T(纹理垂直填充)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);