1. // PickFace.js (c) 2012 matsuda and kanda
  2. // Vertex shader program
  3. var VSHADER_SOURCE =
  4. 'attribute vec4 a_Position;\n' +
  5. 'attribute vec4 a_Color;\n' +
  6. 'attribute float a_Face;\n' + // 表面的编号(1-6),不能使用int类型(当前顶点属于哪一个表面)【float类型】
  7. 'uniform mat4 u_MvpMatrix;\n' +
  8. 'uniform int u_PickedFace;\n' + // 被选中的表面编号【int类型】
  9. 'varying vec4 v_Color;\n' +
  10. 'void main() {\n' +
  11. ' gl_Position = u_MvpMatrix * a_Position;\n' + //对顶点的位置进行模型视图投影变换
  12. ' int face = int(a_Face);\n' + // 转换为int类型(鼠标一点击就会把他编码成颜色值得a分量)
  13. ' vec3 color = (face == u_PickedFace) ? vec3(1.0) : a_Color.rgb;\n' + //vec3(1.0)所有的分量都为1,此时为白色;否则顶点颜色还是以前的颜色
  14. ' if(u_PickedFace == 0) {\n' + // 前三个分量RGB, 通过第四个分量来判断是点击的是哪一个顶面
  15. ' v_Color = vec4(color, a_Face/255.0);\n' + // 颜色的第4个分量使得图形的透明度不一样
  16. ' } else {\n' +
  17. ' v_Color = vec4(color, a_Color.a);\n' +
  18. ' }\n' +
  19. '}\n';
  20.  
  21. // Fragment shader program
  22. var FSHADER_SOURCE =
  23. '#ifdef GL_ES\n' +
  24. 'precision mediump float;\n' +
  25. '#endif\n' +
  26. 'varying vec4 v_Color;\n' +
  27. 'void main() {\n' +
  28. ' gl_FragColor = v_Color;\n' +
  29. '}\n';
  30.  
  31. //旋转的速度
  32. var ANGLE_STEP = 20.0; // Rotation angle (degrees/second)
  33.  
  34. function main() {
  35. // 获取canvas
  36. var canvas = document.getElementById('webgl');
  37.  
  38. // 获取上下文信息
  39. var gl = getWebGLContext(canvas);
  40. if (!gl) {
  41. console.log('Failed to get the rendering context for WebGL');
  42. return;
  43. }
  44.  
  45. // 初始化着色器
  46. if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
  47. console.log('Failed to intialize shaders.');
  48. return;
  49. }
  50.  
  51. // 设置顶点的信息
  52. var n = initVertexBuffers(gl);
  53. if (n < 0) {
  54. console.log('Failed to set the vertex information');
  55. return;
  56. }
  57.  
  58. // 用白色清空背景色,启动深度测试
  59. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  60. gl.enable(gl.DEPTH_TEST);
  61.  
  62. // 获取模型视图投影矩阵的存储地址,获取点击面的位置
  63. var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
  64. var u_PickedFace = gl.getUniformLocation(gl.program, 'u_PickedFace');
  65. if (!u_MvpMatrix || !u_PickedFace) {
  66. console.log('Failed to get the storage location of uniform variable');
  67. return;
  68. }
  69.  
  70. // 计算模型视图投影矩阵
  71. var viewProjMatrix = new Matrix4();
  72. viewProjMatrix.setPerspective(30.0, canvas.width / canvas.height, 1.0, 100.0);
  73. viewProjMatrix.lookAt(0.0, 0.0, 7.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
  74.  
  75. // 初始化被选中的表面(刚开始没有那个面被选中,还是以前的颜色)
  76. gl.uniform1i(u_PickedFace, -1);
  77.  
  78. var currentAngle = 0.0; // Current rotation angle
  79. // Register the event handler
  80. canvas.onmousedown = function (ev) { // Mouse is pressed
  81. var x = ev.clientX, y = ev.clientY;
  82. var rect = ev.target.getBoundingClientRect();
  83. if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom) {
  84. // 获取鼠标当前点击的位置,转换为canvas元素中的坐标
  85. var x_in_canvas = x - rect.left, y_in_canvas = rect.bottom - y;
  86.  
  87. //调用这个函数区检测里方法体的哪一个面被点击了(face这个分量此时存储的是第四个a分量, read(pixes[3]) );
  88. var face = checkFace(gl, n, x_in_canvas, y_in_canvas, currentAngle, u_PickedFace, viewProjMatrix, u_MvpMatrix);
  89. //console.log("The current face is"+face.toString());
  90. var num = parseFloat(face)/255.0; //这里除255等价于 <===> a/255, 得到的其实是一个唯一编号,就是把一个在缓冲区中改变了颜色的那个面的第四个分量
  91. console.log("当前点击的面为"+num.toString()+" "+face.toString());
  92.  
  93. //把当前选中的一面传给顶点着色器()
  94. gl.uniform1i(u_PickedFace, face); // Pass the surface number to u_PickedFace
  95.  
  96. //用选中的编号重新绘制立方体
  97. draw(gl, n, currentAngle, viewProjMatrix, u_MvpMatrix);
  98. }
  99. }
  100.  
  101. var tick = function () { // Start drawing
  102. currentAngle = animate(currentAngle);
  103. draw(gl, n, currentAngle, viewProjMatrix, u_MvpMatrix);
  104. requestAnimationFrame(tick, canvas);
  105. };
  106. tick();
  107. }
  108.  
  109. function initVertexBuffers(gl) {
  110. // Create a cube
  111. // v6----- v5
  112. // /| /|
  113. // v1------v0|
  114. // | | | |
  115. // | |v7---|-|v4
  116. // |/ |/
  117. // v2------v3
  118.  
  119. var vertices = new Float32Array([ // Vertex coordinates
  120. 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, // v0-v1-v2-v3 front
  121. 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, // v0-v3-v4-v5 right
  122. 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
  123. -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, // v1-v6-v7-v2 left
  124. -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, // v7-v4-v3-v2 down
  125. 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0 // v4-v7-v6-v5 back
  126. ]);
  127.  
  128. var colors = new Float32Array([ // Colors
  129. 0.32, 0.18, 0.56, 0.32, 0.18, 0.56, 0.32, 0.18, 0.56, 0.32, 0.18, 0.56, // v0-v1-v2-v3 front
  130. 0.5, 0.41, 0.69, 0.5, 0.41, 0.69, 0.5, 0.41, 0.69, 0.5, 0.41, 0.69, // v0-v3-v4-v5 right
  131. 0.78, 0.69, 0.84, 0.78, 0.69, 0.84, 0.78, 0.69, 0.84, 0.78, 0.69, 0.84, // v0-v5-v6-v1 up
  132. 0.0, 0.32, 0.61, 0.0, 0.32, 0.61, 0.0, 0.32, 0.61, 0.0, 0.32, 0.61, // v1-v6-v7-v2 left
  133. 0.27, 0.58, 0.82, 0.27, 0.58, 0.82, 0.27, 0.58, 0.82, 0.27, 0.58, 0.82, // v7-v4-v3-v2 down
  134. 0.73, 0.82, 0.93, 0.73, 0.82, 0.93, 0.73, 0.82, 0.93, 0.73, 0.82, 0.93, // v4-v7-v6-v5 back
  135. ]);
  136.  
  137. //把我的表面编号传进去
  138. var faces = new Uint8Array([ // Faces
  139. 1, 1, 1, 1, // v0-v1-v2-v3 front
  140. 2, 2, 2, 2, // v0-v3-v4-v5 right
  141. 3, 3, 3, 3, // v0-v5-v6-v1 up
  142. 4, 4, 4, 4, // v1-v6-v7-v2 left
  143. 5, 5, 5, 5, // v7-v4-v3-v2 down
  144. 6, 6, 6, 6, // v4-v7-v6-v5 back
  145. ]);
  146.  
  147. var indices = new Uint8Array([ // Indices of the vertices
  148. 0, 1, 2, 0, 2, 3, // front
  149. 4, 5, 6, 4, 6, 7, // right
  150. 8, 9, 10, 8, 10, 11, // up
  151. 12, 13, 14, 12, 14, 15, // left
  152. 16, 17, 18, 16, 18, 19, // down
  153. 20, 21, 22, 20, 22, 23 // back
  154. ]);
  155.  
  156. // Create a buffer object
  157. var indexBuffer = gl.createBuffer();
  158. if (!indexBuffer) {
  159. return -1;
  160. }
  161.  
  162. // Write vertex information to buffer object
  163. if (!initArrayBuffer(gl, vertices, gl.FLOAT, 3, 'a_Position')) return -1; // Coordinates Information
  164. if (!initArrayBuffer(gl, colors, gl.FLOAT, 3, 'a_Color')) return -1; // Color Information
  165. if (!initArrayBuffer(gl, faces, gl.UNSIGNED_BYTE, 1, 'a_Face')) return -1;// Surface Information
  166.  
  167. // Unbind the buffer object
  168. gl.bindBuffer(gl.ARRAY_BUFFER, null);
  169.  
  170. // Write the indices to the buffer object
  171. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  172. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
  173.  
  174. return indices.length;
  175. }
  176.  
  177. //检测哪一个面被选中了(【根据点中的位置返回表面编号】)
  178. function checkFace(gl, n, x, y, currentAngle, u_PickedFace, viewProjMatrix, u_MvpMatrix) {
  179. var pixels = new Uint8Array(4); // Array for storing the pixel value
  180.  
  181. //将表面编号写入到a分量(如果选中了)
  182. //鼠标一旦点击,就把u_PickedFace变量从-1变为0
  183. gl.uniform1i(u_PickedFace, 0); // Draw by writing surface number into alpha value
  184.  
  185. //此时每个表面的a值就取决于表面的编号(这一步绘制工作会在颜色缓冲区中执行,不会显示在屏幕上)
  186. draw(gl, n, currentAngle, viewProjMatrix, u_MvpMatrix);
  187.  
  188. // 读取(x, y)处的像素颜色. pixels[3] 存储了表面编号
  189. gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  190.  
  191. //var num = pixels[3].toString();
  192. //console.log("pixels[3] is "+num/255);
  193. for (var i=0; i<pixels.length; i++){
  194. console.log(pixels[i]);
  195. }
  196. //把a分量返回出去(pixels[3]此时存储了表面的编号)
  197. return pixels[3];
  198. }
  199.  
  200. var g_MvpMatrix = new Matrix4(); // Model view projection matrix
  201. function draw(gl, n, currentAngle, viewProjMatrix, u_MvpMatrix) {
  202. // Caliculate The model view projection matrix and pass it to u_MvpMatrix
  203. g_MvpMatrix.set(viewProjMatrix);
  204. g_MvpMatrix.rotate(currentAngle, 1.0, 0.0, 0.0); // Rotate appropriately
  205. g_MvpMatrix.rotate(currentAngle, 0.0, 1.0, 0.0);
  206. g_MvpMatrix.rotate(currentAngle, 0.0, 0.0, 1.0);
  207. gl.uniformMatrix4fv(u_MvpMatrix, false, g_MvpMatrix.elements);
  208.  
  209. gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Clear buffers
  210. gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0); // Draw
  211. }
  212.  
  213. var last = Date.now(); // Last time that this function was called
  214. function animate(angle) {
  215. var now = Date.now(); // Calculate the elapsed time
  216. var elapsed = now - last;
  217. last = now;
  218. // Update the current rotation angle (adjusted by the elapsed time)
  219. var newAngle = angle + (ANGLE_STEP * elapsed) / 1000.0;
  220. return newAngle % 360;
  221. }
  222.  
  223. function initArrayBuffer(gl, data, type, num, attribute) {
  224. // Create a buffer object
  225. var buffer = gl.createBuffer();
  226. if (!buffer) {
  227. console.log('Failed to create the buffer object');
  228. return false;
  229. }
  230. // Write date into the buffer object
  231. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  232. gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  233. // Assign the buffer object to the attribute variable
  234. var a_attribute = gl.getAttribLocation(gl.program, attribute);
  235. if (a_attribute < 0) {
  236. console.log('Failed to get the storage location of ' + attribute);
  237. return false;
  238. }
  239. gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
  240. // Enable the assignment to a_attribute variable
  241. gl.enableVertexAttribArray(a_attribute);
  242.  
  243. return true;
  244. }

WEBGL学习【十三】鼠标点击立方体改变颜色的原理与实现的更多相关文章

  1. radio和label关联问题,点击label改变颜色

    $(function () { $("#fangan :radio[name='price']").bind('click', function (event) { //$(thi ...

  2. css:鼠标点击出现有颜色的边框?如何解决

    今天遇到上图这样出现有颜色的边框 解决办法: css设置属性 outline:none;

  3. WebGL学习笔记(十三):拾取

    目前为止,我们还没有涉及到交互相关的内容,实际上,我们是需要知道我们点击的地方下面的第一个物体的信息,这个过程称为拾取. 简单拾取实现 我们可以通过颜色来获取是否成功点击,具体方式如下: 场景中有一个 ...

  4. Android 关于expandableListView childrenView 点击改变颜色

    1.点击后改变颜色并保持颜色改变状态: <?xml version="1.0" encoding="utf-8"?> <selector xm ...

  5. JavaScript001,鼠标点击改变文字或图片

    <h3>我的第一个Javascript</h3> <p id="demo1">1.点击按钮,改变内容!</p> <!-- 设置 ...

  6. vue列表渲染,以及鼠标点击改变样式的问题

    在实际项目中,我们进场会遇到鼠标点击该表某个DOM元素的样式,在原生的js或者jquery中,我们会比较熟练的实现这个需求,但是在vue中怎么实现呢? 直接操作DOM?NO!NO! 既然我们的项目使用 ...

  7. 基于css3新属性transform及原生js实现鼠标拖动3d立方体旋转

    基于css3新属性transform,实现3d立方体的旋转 通过原生JS,点击事件,鼠标按下.鼠标抬起和鼠标移动事件,实现3d立方体的拖动旋转,并将旋转角度实时的反应至界面上显示 实现原理:通过获取鼠 ...

  8. WEBGL学习笔记(七):实践练手1-飞行类小游戏之游戏控制

    接上一节,游戏控制首先要解决的就是碰撞检测了 这里用到了学习笔记(三)射线检测的内容了 以鸟为射线原点,向前.上.下分别发射3个射线,射线的长度较短大概为10~30. 根据上一节场景的建设,我把y轴设 ...

  9. 【Unity3D基础】让物体动起来①--UGUI鼠标点击移动

    背景 首先还是先声明自己是比较笨的一个人,总是找不到高效的学习方法,目前自己学习Unity3D的方式主要是两种,一种是直接看高质量的源码,另一种是光看不行还要自己动手,自己写一些有代表性的小程序,这也 ...

随机推荐

  1. linux下apache2更换目录

    修改apache2的默认文档目录(默认是在/var/www) 修改命令:sudo gedit /etc/apache2/sites-enabled/000-default 在文档中找到 Documen ...

  2. POJ 1265

    主要利用PICK定理与边点数上的GCD的关系求解. 三角形一条边上的所有整数点(包括顶点)可以首先将这条边移到(0, 0)->(x, y).这时,(x/gcd(x, y), y/gcd(x, y ...

  3. IP地址的规划和设计方法(三)

    九,内部网络专用IP地址规划与网络地址转换NAT方法 (1)内部网络的专用IP地址选择的根据 RFC1918在讨论内部网络的专用IP地址规划方法时任务.使用专用地址规划一个内部网络地址系统时.首选的方 ...

  4. html里显示中文乱码的解决的方法

    在HTML开头统一规范下编码格式: <meta http-equiv="Content-Type" content="text/html; charset=utf- ...

  5. 浅析hybrid模式下地支付宝钱包和微信

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VuY2hhbzEyNg==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  6. DNS负载均衡 Nginx 负载均衡的种类

    DNS负载均衡 当一个网站有足够多的用户的时候,假如每次请求的资源都位于同一台机器上面,那么这台机器随时可能会蹦掉.处理办法就是用DNS负载均衡技术,它的原理是在DNS服务器中为同一个主机名配置多个I ...

  7. Java面试-Struts2

    1  Struts2工作原理 一个请求在Struts2框架中的处理大概分为下面几个步骤: 1.client初始化一个指向Servlet容器(比如Tomcat)的请求: 2.这个请求经过一系列的过滤器( ...

  8. Windows 10家庭版也能共享打印机(中)解除Guest账户网络登录限制,实现局域网共享

    由于Windows系统默认是禁止Guest账户从网络登录的.我们须要解除这个限制.首先想到的是用组策略编辑器gpedit.msc. 可是Windows 10家庭版没有组策略编辑器,我们先尝试用U盘把W ...

  9. oc08--局部变量,全局变量,函数方法的区别

    // // main.m // 局部变量和全局变量以及成员变量的区别 #import <Foundation/Foundation.h> @interface Person : NSObj ...

  10. Java:笔记-1

    ylbtech-Java:笔记-1 1.返回顶部 1. /** * 简介请求 * @return */ @RequestMapping("/JJ") public String j ...