-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebgl-magnifying.html
136 lines (125 loc) · 5.19 KB
/
webgl-magnifying.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>放大镜</title>
<script src="./js/initShader.js"></script>
<script src="./js/matrix.js"></script>
<style>
html,
body {
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
</style>
</head>
<body>
<canvas id="draw1" width="400" height="400" style="background: skyblue;">浏览器不支持canvas</canvas>
</body>
</html>
<script type="module">
const draw1 = document.getElementById('draw1');
const gl = draw1.getContext('webgl');
//attribute只传递顶点数量
const VERTEX_SHADER_SOURCE = `
attribute vec4 aPosition;
attribute vec4 aTex;
varying vec4 vPosition;
varying vec2 vTex;
void main(){
vTex=vec2(aTex.x,aTex.y);//opengl强类型语言,左右两边类型一致
vPosition=aPosition;
gl_Position=aPosition;
gl_PointSize=10.0;
}
`; //顶点
const FRAGMENT_SHADER_SOURCE = `
precision lowp float;
uniform sampler2D uSampler;//取样器
varying vec2 vTex;
uniform vec2 lookAt;//观察点
varying vec4 vPosition;
void main(){
vec2 uv=vTex;
float fOpacity =0.0;
//1.判断当前点和观察点的距离
float dis=distance(lookAt,vec2(vPosition));//distance函数的参数类型vec2,vec3或vec4类型的向量
if(dis>0.2){
fOpacity=0.05;
}else{
fOpacity=1.0;
vec2 diff =vPosition.xy-lookAt;
uv.x-=diff.x*0.2;//*后面是放大系数
uv.y+=diff.y*0.2;
}
vec4 color=texture2D(uSampler,vTex);
gl_FragColor=vec4(color.xyz*fOpacity,fOpacity);
}
`;//片元
const program = initShader(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);
const aPosition = gl.getAttribLocation(program, 'aPosition');//第二个参数是源码里attribute声明的变量名
const aTex = gl.getAttribLocation(program, 'aTex');
const uSampler = gl.getUniformLocation(program, 'uSampler');
const lookAt = gl.getUniformLocation(program, 'lookAt');
const points = new Float32Array([
-0.9, 0.9, 0.0, 1.0, 0.0, 1.0,
-0.9, -0.9, 0.0, 1.0, 0.0, 0.0,
0.9, 0.9, 0.0, 1.0, 1.0, 1.0,
0.9, -0.9, 0.0, 1.0, 1.0, 0.0,
]);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);
const BYTES = points.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(aPosition, 4, gl.FLOAT, false, BYTES * 6, 0);
gl.vertexAttribPointer(aTex, 2, gl.FLOAT, false, BYTES * 6, BYTES * 4);
void gl.enableVertexAttribArray(aPosition);
const img = new Image();
img.onload = function () {
//创建纹理对象
const texture = gl.createTexture();
//翻转图片Y轴
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
//开启一个纹理单元
gl.activeTexture(gl.TEXTURE0);//纹理编号
//绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);//(type,texture),type有两种gl.TEXTURE_2D,gl.TEXTURE_CUBE_MAP,texture纹理对象
//处理放大缩小逻辑
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);//(type,pname,param)type同上,pname四种,param两种
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);//gl.TEXTURE_MIN_FILTER缩小
//横向,纵向,平铺
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);//gl.TEXTURE_WRAP_S横向
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);//gl.TEXTURE_WRAP_T纵向
//配置纹理图像
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, img);//(type,level,internalformat,format,dataType,image),internalformat和format值一致
gl.uniform1i(uSampler, 0);//0为纹理编号
}
img.src = './img/sky.jpg';//1200*675
function draw() {
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
requestAnimationFrame(draw);
}
draw();
document.onmousemove = (e) => {
const x = e.clientX;
const y = e.clientY;
const { top, left } = e.target.getBoundingClientRect();
const domX = x - left;//点击点距离画布左侧的距离
const domY = y - top;
//计算坐标使其范围(-1,1)
//X先减画布宽度一半,再除以画布宽度一半
//画布高度一半减Y,再除以画布高度一半
const halfW = draw1.offsetWidth / 2;
const halfH = draw1.offsetHeight / 2;
const clickX = (domX - halfW) / halfW;
const clickY = (halfH - domY) / halfH;
gl.uniform2fv(lookAt, [clickX, clickY]);
}
</script>