<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
<style>
body {
margin: 0;
text-align: center;
}
#canvas {
display: block;
}
#div{
width:800px;
height:800px;
position: relative;
margin: 0 auto;
}
</style>
</head>
<body onload="main()" style="background-color: #0c80ba;">
<div id="div">
<canvas id="canvas" height="800" width="800"></canvas>
</div>
</body>
<script src="lib/webgl-utils.js"></script>
<script src="lib/webgl-debug.js"></script>
<script src="lib/cuon-utils.js"></script>
<script src="lib/cuon-matrix.js"></script>
<script>
/*第一部分顶点着色器接收顶点的纹理坐标,传递给片元着色器*/
var VSHADER_SOURCE = "" +
"attribute vec4 a_Position;\n" +//
"varying vec2 v_Position;\n" +
"void main(){\n" +
" gl_Position = a_Position;\n" +
" v_Position = vec2(a_Position);\n" +
"}\n";
var FSHADER_SOURCE = "" +
"precision mediump float;\n" +//
"uniform sampler2D u_Sampler;\n" +//
"varying vec2 v_Position;\n" +
"uniform vec2 u_point0;\n" +
"uniform vec2 u_point1;\n" +
"uniform vec2 u_point2;\n" +
"uniform vec2 u_point3;\n" +
"float calc(vec2 p1,vec2 p2,vec2 p3,vec2 p4,vec2 p0){\n" +
//如果不是平行的两条直线
" float p12Xlen = p2.x-p1.x;\n" +
" float p12Ylen = p2.y-p1.y;\n" +
" float p34Xlen = p4.x-p3.x;\n" +
" float p34Ylen = p4.y-p3.y;\n" +
" float a = p12Xlen*p34Ylen-p12Ylen*p34Xlen;\n" +
" float b = p1.x*p34Ylen+p3.y*p12Xlen-p0.y*p12Xlen-p3.x*p12Ylen+p0.y*p34Xlen-p1.y*p34Xlen+p0.x*(p12Ylen-p34Ylen);\n" +
" float c = p3.x*p0.y-p3.x*p1.y+p1.x*p3.y-p1.x*p0.y+p0.x*(p1.y-p3.y);\n" +
//两条线都垂直于x轴或者y轴的情况下
" if(a == 0.0){\n" +
" return -c/b;\n" +
" }\n" +
//两条线不平行的情况下
" float endA = (-b+sqrt(b*b-4.0*a*c))/(2.0*a);\n" +
" float endB = (-b-sqrt(b*b-4.0*a*c))/(2.0*a);\n" +
" if(endA > 0.0 && endA < 1.0){\n" +
" return endA;\n" +
" }\n" +
" if(endB > 0.0 && endB < 1.0){\n" +
" return endB;\n" +
" }\n" +
" else {\n" +
" return -c/b;\n" +
" }\n" +
"}\n" +
""+
//两个点的位置,第一个calc(v0,v2,v1,v3,p0) 第二个calc(v1,v0,v3,v2,p0)
"void main(){\n" +
" gl_FragColor = texture2D(u_Sampler,vec2(calc(u_point0,u_point2,u_point1,u_point3,v_Position),calc(u_point1,u_point0,u_point3,u_point2,v_Position)));\n" +//
"}\n";
//四个顶点的位置
var v0 = {x:-0.5,y:0.5};
var v1 = {x:-0.5,y:-0.5};
var v2 = {x:0.5,y:0.5};
var v3 = {x:0.5,y:-0.5};
//图片的地址设置
var imgSrc = "11.png";
//var imgSrc = "http://image.youfangke.com/upload/20170823/201708231503459923.png!w800";
var gl;
/*第二部分 main()方法 初始化着色器,设置顶点信息,调用配置纹理方法*/
function main() {
var canvas = document.getElementById("canvas");
gl = getWebGLContext(canvas,true);
if(!gl){
console.log("你的电脑不支持WebGL!");
return;
}
if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
console.log("初始化着色器失败!");
return;
}
//设置顶点的相关信息
var n = initVertexBuffers(gl);
if(n < 0){
console.log("无法获取到点的数据");
return;
}
//配置纹理
if(!initTextures(gl,n)){
console.log("无法配置纹理");
return;
}
}
/*第三部分 initVertexBuffers() 设置顶点坐标和纹理坐标 调用initTextures()进行下一步处理*/
function initVertexBuffers(gl) {
/*
* v0-------v2
* | |
* | |
* | |
* v1-------v3
*
* [v0.x,v0.y,v1.x,v1.y,v2.x,v2.y,v3.x,v3.y]
* config.Positions[0].Config 数组由八个数据组成,代表四个点的位置,距离中心点的偏移量
* */
var verticesSizes = new Float32Array([
//四个顶点的位置
v0.x,v0.y,
v1.x,v1.y,
v2.x,v2.y,
v3.x,v3.y
]);
initArrayBuffer(gl, verticesSizes, 2, gl.FLOAT, "a_Position");
//将四个顶点位置传入
var point0 = gl.getUniformLocation(gl.program, "u_point0");
var point1 = gl.getUniformLocation(gl.program, "u_point1");
var point2 = gl.getUniformLocation(gl.program, "u_point2");
var point3 = gl.getUniformLocation(gl.program, "u_point3");
if(point0 < 0){
alert("无法获取到存储的位置");
}
gl.uniform2f(point0,v0.x,v0.y);
gl.uniform2f(point1,v1.x,v1.y);
gl.uniform2f(point2,v2.x,v2.y);
gl.uniform2f(point3,v3.x,v3.y);
var indexSize = new Uint8Array([0,1,3,0,2,3]);
//将索引写入缓冲区对象
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indexSize, gl.STATIC_DRAW);
return indexSize.length;
}
//创建变量缓冲区
function initArrayBuffer(gl, data, num, type, attribute) {
//创建缓冲区对象
var buffer = gl.createBuffer();
if (!buffer) {
console.log("无法创建缓冲区对象");
return -1;
}
//绑定缓冲区对象并写入数据
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
//获取顶点位置变量位置
var a_attribue = gl.getAttribLocation(gl.program, attribute);
if (a_attribue < 0) {
console.log("无法获取顶点位置的存储变量");
return -1;
}
//对位置的顶点数据进行分配,并开启
gl.vertexAttribPointer(a_attribue, num, type, false, 0, 0);
gl.enableVertexAttribArray(a_attribue);
}
/*第四部分 initTextures() 创建纹理对象 并调用纹理绘制方法*/
function initTextures(gl,n) {
var texture = gl.createTexture();//创建纹理对象
if(!texture){
console.log("无法创建纹理对象");
return;
}
//获取u_Sampler的存储位置
var u_Sampler = gl.getUniformLocation(gl.program,"u_Sampler");
if(u_Sampler < 0){
console.log("无法获取变量的存储位置");
return;
}
//创建Image对象,并绑定加载完成事件
var image = new Image();
image.onload = function () {
loadTexture(gl,n,texture,u_Sampler,image);
//初始化交互事件
initMoveBtn();
};
image.src = imgSrc;
return true;
}
function initMoveBtn() {
var canvas = document.querySelector("#canvas");
var div = document.querySelector("#div");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
addBtn(v0);
addBtn(v1);
addBtn(v2);