发现自己越来越懒了。。。基础的我不写了,有很多博客都写了,连w3c都有,瞬间没有心思写下去了,并且也很忙;每天都在研究;别骂我。。。真心没心思;我会考虑写一些难度大点的,这样有动力点;代码如下:
看下面需要注意的是向量的计算,
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>第三人称</title><script src="glMatrix-0.9.6.min.js"></script><script src="../lib/my-webgl-utils.js"></script><script id="vs" type="x-shader/x-vertex">attribute vec3 a_Position;attribute vec4 a_Color;attribute vec2 a_TexCoord;uniform mat4 u_Proj;varying vec4 v_Color;varying vec2 v_texCoord;void main(){gl_Position = u_Proj * vec4(a_Position,1.0);v_Color = a_Color;v_texCoord = a_TexCoord;}</script><script id="fs" type="x-shader/x-fragment">precision mediump float;varying vec4 v_Color;varying vec2 v_texCoord;uniform sampler2D u_Texture;void main(void){gl_FragColor = texture2D(u_Texture,v_texCoord);}</script>
</head>
<body>
<canvas id="webgl" width="500px" height="500px"></canvas>
<script>var gl;var viewPortW;var viewPortH;var triangleBuffer = null;var textureHandle;//纹理对象var textureGround;var projectMat = mat4.create();//投影矩阵var viewMat = mat4.create();//视图矩阵var cameraEye = new Float32Array(3);//相机位置var cameraTrag = new Float32Array(3);//观看目标位置var cameraLookAt = new Float32Array(3);var cameraUp = new Float32Array(3);var fbo;var textureDynamic;var times = (new Date()).valueOf();var role = {};//角色对象role._position = new Float32Array(3);role._target = new Float32Array(3);role._speed = 5;//速度var varRotFBOX = 0;var varRotFBOY = 0;var mouseDown = false;var rButtonDown = false;var lastMouseX = 0;var lastMouseY = 0;var radius = 40;var loadTextureNum = 0;onload = function () {var canvas = document.getElementById("webgl");gl = canvas.getContext("webgl");viewPortW = canvas.clientWidth;viewPortH = canvas.clientHeight;gl.viewport(0, 0, canvas.clientWidth, viewPortH);if (!initShaders(gl, "vs", "fs")) {console.log('Failed to intialize shaders.');return;}initLocation();//初始化,获取着色器中的变量地址initCamera();initModelData();canvas.onmousedown = handleMouseDown;canvas.onmouseup = handleMouseUp;canvas.onmousemove = handleMouseMove;canvas.onmousewheel = handleMouseWheel;document.onkeydown = handleKeyDown;document.onkeyup = handleKeyup;tick();}function tick() {requestAnimFrame(tick);renderScene();}function renderScene() {renderToFBO();var elspsed = (new Date()).valueOf() - times;times = (new Date()).valueOf();updateTarget(elspsed);cameraTrag = role._position;updateCamera();//更新相机位置varRotFBOX += 1;//使用fbogl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.viewport(0, 0, viewPortW, viewPortH);//! 设置重绘背景的颜色gl.clearColor(0.0, 0.0, 0.0, 1.0);//! 执行绘制,即将背景清空成制定的颜色(clearColor)gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);gl.enable(gl.DEPTH_TEST);//! 指定绘制所使用的顶点数据 从 该缓冲区中获取gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);var mvp = mat4.create();var matTrans = mat4.create();var matModel = mat4.create();var matRotX = mat4.create();var matROtY = mat4.create();var matRot = mat4.create();var matTemp = mat4.create();mat4.identity(matRot);mat4.identity(matRotX);mat4.identity(matROtY);mat4.identity(matTrans);mat4.identity(matModel);mat4.identity(mvp);mat4.identity(matTemp);gl.activeTexture(gl.TEXTURE0);gl.bindTexture(gl.TEXTURE_2D, textureDynamic);gl.uniform1i(gl.uniformTexture, 0);mat4.translate(matTrans, [role._position[0], 0.0, role._position[2]]);//varRot += 1;mat4.rotate(matROtY, degToRad(varRotFBOY), [0.0, 1.0, 0.0]);mat4.rotate(matRotX, degToRad(varRotFBOX), [1.0, 0.0, 0.0]);mat4.multiply(matROtY, matRotX, matRot);mat4.multiply(matTrans, matRot, matModel);mat4.multiply(projectMat, viewMat, matTemp);mat4.multiply(matTemp, matTrans, mvp);gl.uniformMatrix4fv(gl.uniformProj, false, mvp);gl.enableVertexAttribArray(gl.a_Position);gl.enableVertexAttribArray(gl.a_TexCoord);gl.enableVertexAttribArray(gl.a_Color);gl.vertexAttribPointer(gl.a_Position, 3, gl.FLOAT, false, 4 * 9, 0);gl.vertexAttribPointer(gl.a_TexCoord, 2, gl.FLOAT, false, 4 * 9, 4 * 3);gl.vertexAttribPointer(gl.a_Color, 4, gl.FLOAT, false, 4 * 9, 4 * 5);gl.drawArrays(gl.TRIANGLES, 0, 36);mat4.multiply(projectMat, viewMat, mvp);gl.uniformMatrix4fv(gl.uniformProj, false, mvp);gl.bindTexture(gl.TEXTURE_2D, textureGround);gl.drawArrays(gl.TRIANGLES, 36, 6);}//计算相机位置function updateCamera() {//反向推导,知道目标位置,和相机与目标位置的距离,求相机位置//camerD 是 目标位置减去相机位置的向量,并归一化,没归一化前,其实就相当于camerD * radius//camerD归一化,类似于单位向量,乘以 长,就是它们相减得到的向量cameraEye[0] = cameraTrag[0] - cameraLookAt[0] * radius;cameraEye[1] = cameraTrag[1] - cameraLookAt[1] * radius;cameraEye[2] = cameraTrag[2] - cameraLookAt[2] * radius;//规格化up坐标var upDir = vec3.normalize(cameraUp);mat4.lookAt(cameraEye, cameraTrag, upDir, viewMat);}//更新目标function updateTarget(elapsed) {if (role._target[0] == role._position[0]&& role._target[1] == role._position[1]&& role._target[2] == role._position[2]) {return;}var offset = new Float32Array(3);var dir = new Float32Array(3);offset[0] = role._target[0] - role._position[0];offset[1] = role._target[1] - role._position[1];offset[2] = role._target[2] - role._position[2];vec3.normalize(offset, dir);var dist = vec3.length(offset);if (dist > role._speed * elapsed / 1000.0 * 2) {var dist = role._speed * elapsed / 1000.0;role._position[0] += dir[0] * dist;role._position[2] += dir[2] * dist;} else {role._position[0] = role._target[0];role._position[1] = role._target[1];role._position[2] = role._target[2];}}function renderToFBO() {//使用fbogl.bindFramebuffer(gl.FRAMEBUFFER, fbo);gl.viewport(0, 0, viewPortW, viewPortH);//设置重绘背景的颜色gl.clearColor(1.0, 1.0, 1.0, 1.0);//执行绘制,即将背景清空成制定的颜色gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);gl.enable(gl.DEPTH_TEST);//指定绘制使用的顶点数据gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);var mvp = mat4.create();//MVP矩阵var matTrans = mat4.create();//移动矩阵var matModel = mat4.create();//模型矩阵var matRotX = mat4.create();//X旋转矩阵var matRotY = mat4.create();//Y 旋转矩阵var matRot = mat4.create();//旋转矩阵//初始化成单位向量mat4.identity(matRot);mat4.identity(matRotX);mat4.identity(matRotY);mat4.identity(matTrans);mat4.identity(matModel);mat4.identity(mvp);gl.activeTexture(gl.TEXTURE0);//开启纹理gl.bindTexture(gl.TEXTURE_2D, textureHandle);gl.uniform1i(gl.uniformTexture, 0);mat4.translate(matTrans, [0, 0.0, -4]);mat4.rotate(matRotY, degToRad(varRotFBOY), [0.0, 1.0, 0.0]);mat4.rotate(matRotX, degToRad(varRotFBOX), [1.0, 0.0, 0.0]);mat4.multiply(matRotY, matRotX, matRot);mat4.multiply(matTrans, matRot, matModel);mat4.multiply(projectMat, matModel, mvp);//得到mvp 矩阵gl.uniformMatrix4fv(gl.uniformProj, false, mvp);gl.enableVertexAttribArray(gl.a_Position);gl.enableVertexAttribArray(gl.a_Color);gl.enableVertexAttribArray(gl.a_TexCoord);gl.vertexAttribPointer(gl.a_Position, 3, gl.FLOAT, false, 4 * 9, 0);gl.vertexAttribPointer(gl.a_TexCoord, 2, gl.FLOAT, false, 4 * 9, 4 * 3);gl.vertexAttribPointer(gl.a_Color, 4, gl.FLOAT, false, 4 * 9, 4 * 5);gl.drawArrays(gl.TRIANGLES, 0, 36);}function degToRad(degrees) {return degrees * Math.PI / 180;}function handleKeyup(event) {}function handleKeyDown(event) {}/*** 将屏幕坐标转化成世界坐标* @param screen* @returns {*}*/function screenToWorld(screen) {var v = new Float32Array(4);var world = new Float32Array(4);v[0] = screen[0];v[1] = screen[1];v[2] = screen[2];v[3] = 1.0;//w分量//转换成 0 - 1 的坐标v[0] = (v[0])/viewPortW;v[1] = (viewPortH - v[1])/viewPortH;//转换成 -1 到 1 之间的坐标v[0] = v[0] * 2.0 - 1.0;v[1] = v[1] * 2.0 - 1.0;v[2] = v[2] * 2.0 - 1.0;var mvp = mat4.create();var mvpInvert = mat4.create();//计算MVP矩阵mat4.multiply(projectMat,viewMat,mvp);//求mvp的逆矩阵inverseEx(mvp,mvpInvert);world[0] = v[0];world[1] = v[1];world[2] = v[2];world[3] = v[3];multiply(mvpInvert,v,world);//得到世界坐标if (world[3] == 0.0){return world;}world[0]    /=  world[3];world[1]    /=  world[3];world[2]    /=  world[3];return  world;}function multiply(mat,v,outv) {outv[0] =   mat[0] * v[0] + mat[1] * v[1] + mat[2] * v[2] + mat[3] * v[3];outv[1] = mat[4] * v[0] + mat[5] * v[1] + mat[6] * v[2] + mat[7] * v[3];outv[2] = mat[8] * v[0] + mat[9] * v[1] + mat[10] * v[2] + mat[11] * v[3];outv[3] = mat[12] * v[0] + mat[13] * v[1] + mat[14] * v[2] + mat[15] * v[3];}//逆矩阵function inverseEx(pData,resData) {var subFactor00 = pData[10] * pData[15] - pData[14] * pData[11];var subFactor01 = pData[9] * pData[15] - pData[13] * pData[11];var subFactor02 = pData[9] * pData[14] - pData[13] * pData[10];var subFactor03 = pData[8] * pData[15] - pData[12] * pData[11];var subFactor04 = pData[8] * pData[14] - pData[12] * pData[10];var subFactor05 = pData[8] * pData[13] - pData[12] * pData[9];var subFactor06 = pData[6] * pData[15] - pData[14] * pData[7];var subFactor07 = pData[5] * pData[15] - pData[13] * pData[7];var subFactor08 = pData[5] * pData[14] - pData[13] * pData[6];var subFactor09 = pData[4] * pData[15] - pData[12] * pData[7];var subFactor10 = pData[4] * pData[14] - pData[12] * pData[6];var subFactor11 = pData[5] * pData[15] - pData[13] * pData[7];var SubFactor12 = pData[4] * pData[13] - pData[12] * pData[5];var subFactor13 = pData[6] * pData[11] - pData[10] * pData[7];var subFactor14 = pData[5] * pData[11] - pData[9] * pData[7];var subFactor15 = pData[5] * pData[10] - pData[9] * pData[6];var subFactor16 = pData[4] * pData[11] - pData[8] * pData[7];var subFactor17 = pData[4] * pData[10] - pData[8] * pData[6];var subFactor18 = pData[4] * pData[9] - pData[8] * pData[5];resData[0]  = + pData[5] * subFactor00 - pData[6] * subFactor01 + pData[7] * subFactor02;resData[1]  = - pData[4] * subFactor00 + pData[6] * subFactor03 - pData[7] * subFactor04;resData[2]  = + pData[4] * subFactor01 - pData[5] * subFactor03 + pData[7] * subFactor05;resData[3]  = - pData[4] * subFactor02 + pData[5] * subFactor04 - pData[6] * subFactor05;resData[4]  = - pData[1] * subFactor00 + pData[2] * subFactor01 - pData[3] * subFactor02;resData[5]  = + pData[0] * subFactor00 - pData[2] * subFactor03 + pData[3] * subFactor04;resData[6]  = - pData[0] * subFactor01 + pData[1] * subFactor03 - pData[3] * subFactor05;resData[7]  = + pData[0] * subFactor02 - pData[1] * subFactor04 + pData[2] * subFactor05;resData[8]  = + pData[1] * subFactor06 - pData[2] * subFactor07 + pData[3] * subFactor08;resData[9]  = - pData[0] * subFactor06 + pData[2] * subFactor09 - pData[3] * subFactor10;resData[10]  = + pData[0] * subFactor11 - pData[1] * subFactor09 + pData[3] * SubFactor12;resData[11]  = - pData[0] * subFactor08 + pData[1] * subFactor10 - pData[2] * SubFactor12;resData[12]  = - pData[1] * subFactor13 + pData[2] * subFactor14 - pData[3] * subFactor15;resData[13]  = + pData[0] * subFactor13 - pData[2] * subFactor16 + pData[3] * subFactor17;resData[14]  = - pData[0] * subFactor14 + pData[1] * subFactor16 - pData[3] * subFactor18;resData[15]  = + pData[0] * subFactor15 - pData[1] * subFactor17 + pData[2] * subFactor18;var determinant =+ pData[0] * resData[0]+ pData[1] * resData[4]+ pData[2] * resData[8]+ pData[3] * resData[12];for( var i = 0 ;i < 16 ; ++ i)resData[i]  /=  determinant;}function handleMouseDown(event) {if (event.button == 0){//计算射线var minWorld = new Float32Array(3);var maxWorld = new Float32Array(3);var screen = new Float32Array(3);screen[0] = event.offsetX;screen[1] = event.offsetY;screen[2] = 0.0;var screen1 = new Float32Array(3);screen[0] = event.offsetX;screen[1] = event.offsetY;screen[2] = 1.0;var minWorld = screenToWorld(screen);var maxWorld = screenToWorld(screen1);//射线向量var dir = new Float32Array(3);dir[0] = maxWorld[0] - minWorld[0];dir[1] = maxWorld[1] - minWorld[1];dir[2] = maxWorld[2] - minWorld[2];vec3.normalize(dir);//计算交点://计算方式:因为地面的y=0;射线的起点y轴减去地面的y轴得到高,然后用射线的单位向量除以高,minWorld[1]/dir[1],得到速度(步长,)//射线的起点位置 加上 tm(步长,相当于时间,走了多长,)乘以 射线的单位向量,得到交点//计算时间var tm = Math.abs(minWorld[1]/dir[1]);var target = new Float32Array(3);target[0] = minWorld[0] + tm * dir[0];target[1] = minWorld[1] + tm * dir[1];target[2] = minWorld[2] + tm * dir[2];moveTo(target);}else {rButtonDown = true;lastMouseX = event.offsetX;console.log("rButtonDown = true;");}}function moveTo(targetPos) {role._target = targetPos;role._target[1] = 0;//没有高度}function handleMouseUp(event) {}function handleMouseMove(event) {}function handleMouseWheel(event) {}function initModelData() {var gSize = 100;//大小var gPos = -10;//高度var rept = 20;//重复var boxVertex = [//x     y     z     u    v      r    g    b    a-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0,1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0,1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0,1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0,-1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0,1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0,-1.0, -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0,1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0,1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0,-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,-1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0,1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0,-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0,1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0,1.0, 1.0, -1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0,-1.0, -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,1.0, -1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0,1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,-1.0, -1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0,1.0, -1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0,-1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0,1.0, -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0,1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0,1.0, -1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0,1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0,1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0,-1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0,-1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0,-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0,-gSize, gPos, -gSize, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0,gSize, gPos, -gSize, rept, 0.0, 1.0, 1.0, 1.0, 1.0,gSize, gPos, gSize, rept, rept, 1.0, 1.0, 1.0, 1.0,-gSize, gPos, -gSize, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0,gSize, gPos, gSize, rept, rept, 1.0, 1.0, 1.0, 1.0,-gSize, gPos, gSize, 0.0, rept, 1.0, 1.0, 1.0, 1.0,]triangleBuffer = gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(boxVertex), gl.STATIC_DRAW);textureHandle = initTextures("test.gif");textureGround = initTextures("1.jpg");fbo = createFOB(viewPortW, viewPortH);}//离屏渲染,创建帧缓冲区function createFOB(width, height) {var obj = gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER, obj);//创建深度缓冲区var depthObj = gl.createRenderbuffer();gl.bindRenderbuffer(gl.RENDERBUFFER, depthObj);gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, height);gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthObj);//把深度缓冲区绑定到帧缓冲区textureDynamic = createDynamicTexture(width, height);//动态纹理gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureDynamic, 0);gl.bindRenderbuffer(gl.RENDERBUFFER, null);gl.bindFramebuffer(gl.FRAMEBUFFER, null);gl.bindTexture(gl.TEXTURE_2D, null);return obj;}function createDynamicTexture(width, height) {var texture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D, texture);gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);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.CLAMP_TO_EDGE);return texture;}function initTextures(imageFile) {var texture;//创建一个纹理texture = gl.createTexture();//创建一个图片texture.image = new Image();//指定图片的路径texture.image.src = imageFile;texture.image.onload = function () {handleLoadedTexture(texture);}return texture;}function handleLoadedTexture(texture) {gl.bindTexture(gl.TEXTURE_2D, texture);gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);gl.bindTexture(gl.TEXTURE_2D, null);loadTextureNum++;}function initCamera() {cameraEye[0] = 28.017817;cameraEye[1] = 29.867514;cameraEye[2] = 29.429590;cameraTrag[0] = -0.84969789;cameraTrag[1] = 1;cameraTrag[2] = 0.56207591;cameraUp[0] = 0;cameraUp[1] = 1;cameraUp[2] = 0;role._position[0] = 0;role._position[1] = 0;role._position[2] = 0;role._target[0] = 0;role._target[1] = 1;role._target[2] = 2;calcDir();mat4.perspective(45, viewPortW / viewPortH, 0.1, 10000.0, projectMat);//设置投影矩阵mat4.lookAt(cameraEye, cameraTrag, cameraUp, viewMat);//设置视图矩阵}//求的lookAt方向 单位向量function calcDir() {//相机看向位置 减 去 眼睛位置,得到 一个向量, D坐标vec3.subtract(cameraTrag, cameraEye, cameraLookAt);var d = new Float32Array(3);d[0] = cameraTrag[0] - cameraEye[0];d[1] = cameraTrag[1] - cameraEye[1];d[2] = cameraTrag[2] - cameraEye[2];vec3.normalize(d, cameraLookAt);}function initLocation() {gl.uniformProj = gl.getUniformLocation(gl.program, "u_Proj");gl.uniformTexture = gl.getUniformLocation(gl.program, "u_Texture");gl.a_Position = gl.getAttribLocation(gl.program, "a_Position");gl.a_Color = gl.getAttribLocation(gl.program, "a_Color");gl.a_TexCoord = gl.getAttribLocation(gl.program, "a_TexCoord");if (!gl.uniformProj && !gl.uniformTexture) {console.log("err 001:获取地址变量错误!");}if (gl.a_Position < 0 || gl.a_TexCoord < 0|| gl.a_Color < 0) {console.log("err 002:获取地址变量错误!");}}window.requestAnimFrame = (function () {return window.requestAnimationFrame ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame ||window.oRequestAnimationFrame ||window.msRequestAnimationFrame ||function (callback, element) {window.setTimeout(callback, 10);};})();function inverseEx(pData,resData){var subFactor00 = pData[10] * pData[15] - pData[14] * pData[11];var subFactor01 = pData[9] * pData[15] - pData[13] * pData[11];var subFactor02 = pData[9] * pData[14] - pData[13] * pData[10];var subFactor03 = pData[8] * pData[15] - pData[12] * pData[11];var subFactor04 = pData[8] * pData[14] - pData[12] * pData[10];var subFactor05 = pData[8] * pData[13] - pData[12] * pData[9];var subFactor06 = pData[6] * pData[15] - pData[14] * pData[7];var subFactor07 = pData[5] * pData[15] - pData[13] * pData[7];var subFactor08 = pData[5] * pData[14] - pData[13] * pData[6];var subFactor09 = pData[4] * pData[15] - pData[12] * pData[7];var subFactor10 = pData[4] * pData[14] - pData[12] * pData[6];var subFactor11 = pData[5] * pData[15] - pData[13] * pData[7];var SubFactor12 = pData[4] * pData[13] - pData[12] * pData[5];var subFactor13 = pData[6] * pData[11] - pData[10] * pData[7];var subFactor14 = pData[5] * pData[11] - pData[9] * pData[7];var subFactor15 = pData[5] * pData[10] - pData[9] * pData[6];var subFactor16 = pData[4] * pData[11] - pData[8] * pData[7];var subFactor17 = pData[4] * pData[10] - pData[8] * pData[6];var subFactor18 = pData[4] * pData[9] - pData[8] * pData[5];resData[0]  = + pData[5] * subFactor00 - pData[6] * subFactor01 + pData[7] * subFactor02;resData[1]  = - pData[4] * subFactor00 + pData[6] * subFactor03 - pData[7] * subFactor04;resData[2]  = + pData[4] * subFactor01 - pData[5] * subFactor03 + pData[7] * subFactor05;resData[3]  = - pData[4] * subFactor02 + pData[5] * subFactor04 - pData[6] * subFactor05;resData[4]  = - pData[1] * subFactor00 + pData[2] * subFactor01 - pData[3] * subFactor02;resData[5]  = + pData[0] * subFactor00 - pData[2] * subFactor03 + pData[3] * subFactor04;resData[6]  = - pData[0] * subFactor01 + pData[1] * subFactor03 - pData[3] * subFactor05;resData[7]  = + pData[0] * subFactor02 - pData[1] * subFactor04 + pData[2] * subFactor05;resData[8]  = + pData[1] * subFactor06 - pData[2] * subFactor07 + pData[3] * subFactor08;resData[9]  = - pData[0] * subFactor06 + pData[2] * subFactor09 - pData[3] * subFactor10;resData[10]  = + pData[0] * subFactor11 - pData[1] * subFactor09 + pData[3] * SubFactor12;resData[11]  = - pData[0] * subFactor08 + pData[1] * subFactor10 - pData[2] * SubFactor12;resData[12]  = - pData[1] * subFactor13 + pData[2] * subFactor14 - pData[3] * subFactor15;resData[13]  = + pData[0] * subFactor13 - pData[2] * subFactor16 + pData[3] * subFactor17;resData[14]  = - pData[0] * subFactor14 + pData[1] * subFactor16 - pData[3] * subFactor18;resData[15]  = + pData[0] * subFactor15 - pData[1] * subFactor17 + pData[2] * subFactor18;var determinant =+ pData[0] * resData[0]+ pData[1] * resData[4]+ pData[2] * resData[8]+ pData[3] * resData[12];for( var i = 0 ;i < 16 ; ++ i)resData[i]  /=  determinant;}function multiply(mat,v,outv) {outv[0] =   mat[0] * v[0] + mat[1] * v[1] + mat[2] * v[2] + mat[3] * v[3];outv[1] = mat[4] * v[0] + mat[5] * v[1] + mat[6] * v[2] + mat[7] * v[3];outv[2] = mat[8] * v[0] + mat[9] * v[1] + mat[10] * v[2] + mat[11] * v[3];outv[3] = mat[12] * v[0] + mat[13] * v[1] + mat[14] * v[2] + mat[15] * v[3];}
</script>
</body>
</html>

webgl 第三人称相机相关推荐

  1. 使用three.js实现跟随模型的第一人称、第三人称相机控制

    最近在我原有的"室内场景demo"的基础上做了一个跟随模型的第三人称相机控制,以键盘wasd控制模型的行走,以鼠标控制模型的朝向. 在线预览地址​​​​​​​ CSDN下载地址ht ...

  2. Unity2020.3.19f1 简单的第三人称相机跟随

    参考书籍:Unity3D动作游戏开发实战 常规第三人称相机是指相机在玩家身后以一定距离看向玩家,相机位置可受到鼠标移动或者手柄摇杆操作的控制而左右上下旋转. using System.Collecti ...

  3. Unity第三人称射击游戏的相机控制

    (关于其他几种角色移动的控制在我之前的博客有写到) 首先我们需要先理解一下第三人称相机控制的原理: 我们要实现的效果就是:获取鼠标的移动输入,转化成角色以及相机的旋转,通过鼠标输入Input.GetA ...

  4. Unity学习日志_七行核心代码实现第三人称游戏的相机逻辑

    七行核心代码实现第三人称游戏的相机逻辑: 使用到的一些知识: 欧拉角 虚拟轴 四元数计算 向量计算 代码实现: 其中RoundMovement方法为核心方法(): using UnityEngine; ...

  5. Unity 3D第三人称视角、用途广泛限定角度(视角不能360度翻转)

    Unity第三人称相机视角控制 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心 ...

  6. 第三人称和第一人称互相切换【Low版】

    [SerializeField]     private Camera mainCamera, thirdPersonCamera; bool firstPersonViewOrThirdPerson ...

  7. Unity第三人称控制实现方式

    第三人称移动,主要两个部分,一是人物,二是相机. 先说人物,unity其实提供了一个CharacteController组件可以方便地用于控制人物移动,但是这个组件会与刚体冲突.如果使用Charact ...

  8. 暴风魔镜VR(第一人称和第三人称)

    今天讲讲魔镜漫游项目,先讲讲魔镜自带的两个漫游Demo,一个是第一人称的,另一个是第三人称的 使用也很简单,我们只要模仿就可以了 先说第一人称的 1. 删掉unity自带的相机 2. 换上魔镜的相机 ...

  9. 3D游戏小总结(第一人称、第三人称实现)

    一:简易第一人称视角控制 private Transform cameraTransform;//相机[SerializeField] private Transform characterTrans ...

最新文章

  1. 一个苹果手机移动电源也能让他拽得跟二五八万似的
  2. Debug pip: Could not build wheels for _ which use PEP 517 and cannot be installed directly - Easy So
  3. c++11多线程之packaged_task<>介绍与实例
  4. 脉冲波形的变换与产生
  5. php 查询 判断 语句,关于php的判断语句
  6. 利用反射获取类或者方法或者字段上的注解的值
  7. [转] C++中 const, volatile, mutable用法
  8. 系统学习机器学习之误差理论
  9. 移植UE4的Spline与SplineMesh组件到Unity5
  10. OpenCV中寻找轮廓函数cvFindContours的使用说明以及序列cvSeq的用法说明
  11. SpeechSynthesisUtterance 语音合成使用 文字语音播报
  12. 厘米和磅的转换程序python_在Python中如何将磅转换成公斤
  13. 教你如何正确提问的“九大准则”
  14. 有一种单身叫宁缺勿滥 -- 纪念百年神棍节
  15. 跳槽吗?4月7日18点6大细分领域4家优质名企招聘情报来了
  16. 阿里云主机安全组端口开放完整教程
  17. Java动态代理的原理
  18. (九)巴菲特与索罗斯的投资习惯:术业有专攻
  19. 电动机的故障听声音就可以判断
  20. 胸上肌到底要怎么练啊!

热门文章

  1. ISO/IEC 29134
  2. 合肥工业大学(宣城校区)2019年EDA课设原理图、PCB板与仿真图像
  3. Ubuntu下adb无法识别android设备的解决方法
  4. TP4333TPOWER应急灯同步充放移动电源IC解决方案
  5. Linux下tomcat重启
  6. Linux userdel 和 deluser 的区别
  7. 智能音箱硬件和软件介绍[上] 硬件结构解析[Soomal]
  8. 计算机网络前三章笔记
  9. [转]全图形PPT设计指南
  10. Android MVVM封装,MVVM: 这是一个android MVVM 框架,基于谷歌dataBinding技术实现