加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Cesium学习笔记-WebGL篇01-绘制圆点、闪烁点

(2018-11-10 23:11:03)
标签:

cesium原理

webgl

webgl绘制圆点

webgl绘制闪烁点

分类: Cesium

在看了cesium源码好多天后,发现自己连三维的门都没碰到,以前觉得会调用三维引擎的接口就算三维开发了,现在想想真是感觉自己井底之蛙。看cesium源码这么些天实在看不下去,索性从webgl底层学习。我想花一部分时间先把webgl这块补起来,不求马上就掌握(掌握也不可能,三维博大精深,仅凭看几页教程就说掌握真是天方夜谭),只求再看cesium源码时能看得懂就算达到目的了。

废话不多说,webgl学习教程网上一大堆,我就找了大家推荐的谢光磊翻译《WebGL编程指南》,百度网盘:教程 提取密码:tb5p 示例源码提取密码:rzyh

由于WebGL知识太过繁杂,我就不从基础语法来记录我的学习过程了,我就挑几个典型应用来学习一下。今天我们来学习一下点的绘制方面一些高级用法吧。

1 绘制圆点

三维图形都是由基本的点、线、三角面三种类型的图元组成,今天我们就首先来接触下使用最频繁的图元点。点在opengl中点默认是一个正方形,webgl继承这一特点,我们想简单绘制一个圆点需要自己特殊处理。不过幸运的是webgl在片元着色器中提供了内置变量gl_PointCoord(点精灵),我们可以通过此变量来处理当前片元。

先上代码(所有源码可以参考:github地址):

var VSHADER_SOURCE =

    'attribute vec4 a_Position;\n' +

     'void main() {\n' +

     '  gl_Position = a_Position;\n' +

     '  gl_PointSize = 20.0;\n' +

     '}\n';

 

var FSHADER_SOURCE =

  'precision mediump float;\n' +

  'void main() {\n' +

  '  float d = distance(gl_PointCoord, vec2(0.5, 0.5));\n' + // 中心点(0.5, 0.5)

  '  if(d < 0.3) {\n' +  // 

  '    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +

  '  } else if(d < 0.5){\n' +

  '    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n' +

  '  } else { discard; }\n' +

  '}\n';

我们主要看片元着色器中这两个量:

gl_FragCoord:片元在窗口坐标

gl_PointCoord:片元在被绘制的点内的坐标(从0.01.0

一个点在窗口所占区域如图:

http://s10/mw690/006pZnPwzy7p5YcoUyd69&690

在这个顶点区域内,我们可以使用gl_PointCoord操作每个图精灵。

'  float d = distance(gl_PointCoord, vec2(0.5, 0.5));\n' + // 中心点(0.5, 0.5)

求出d就是距离中心的距离,大于0.5我们使用discard内置语句不绘出。

效果对比:

  http://s8/small/006pZnPwzy7p5YeNAoL27&690

http://s8/mw690/006pZnPwzy7p5YhjHfN37&690

其它一些内置变量

 1gl_Position: 用于vertex shader, 写顶点位置;被图元收集、裁剪等固定操作功能所使用;其内部声明是:highp vec4 gl_Position;

gl_PointSize: 用于vertex shader, 写光栅化后的点大小,像素个数;其内部声明是:mediump float gl_PointSize;

gl_FragColor: 用于Fragment shader,写fragment color;被后续的固定管线使用;mediump vec4 gl_FragColor;

gl_FragData: 用于Fragment shader,是个数组,写gl_FragData[n] data n;被后续的固定管线使用; mediump vec4 gl_FragData[gl_MaxDrawBuffers];

gl_FragColorgl_FragData是互斥的,不会同时写入;

gl_FragCoord: 用于Fragment shader,只读, Fragment相对于窗口的坐标位置 x,y,z,1/w; 这个是固定管线图元差值后产生的;z 是深度值; mediump vec4 gl_FragCoord;

gl_FrontFacing: 用于判断 fragment是否属于 front-facing primitive;只读;bool gl_FrontFacing;   

gl_PointCoord: 仅用于 point primitive; mediump vec2 gl_PointCoord;

2 闪烁点

我们有时候需要一些特殊效果,比如说累死报警效果的闪烁,同事点不断改变大小。思路很简单:不断改变点的大小,在上个例子中gl_PointSize值固定为20,我们可以时刻更新这个值就可以达到所需效果。

先上代码(完整代码:github地址):

var VSHADER_SOURCE =

    'attribute vec4 a_Position;\n' +

    'uniform float u_TimeIndex;\n' +

     'void main() {\n' +

     '  gl_Position = a_Position;\n' +

     '  gl_PointSize = 5.0+u_TimeIndex*0.5;\n' +//当前点大小

     '}\n';

 

var FSHADER_SOURCE =

  'precision mediump float;\n' +

  'void main() {\n' +

  '  float d = distance(gl_PointCoord, vec2(0.5, 0.5));\n' + 

  '  if(d < 0.3) {\n' +  

  '    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +

  '  } else if(d < 0.5){\n' +

  '    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n' +

  '  } else { discard; }\n' +

  '}\n';

我们通过'uniform float u_TimeIndex;将当前时刻索引值传入顶点着色器中,然后计算大小:
'  gl_PointSize = 5.0+u_TimeIndex*0.5;\n' +//
当前点大小。

外层逻辑控制:

//当前索引

    var currentIndex = 0.0;

    var tick = function () {

        currentIndex += 1.0;//刷新一次就改变索引一次

        if (currentIndex >= 60.0) {

            currentIndex = 0.0;

        }

        draw(gl, n, u_TimeIndex, currentIndex);

        requestAnimationFrame(tick, canvas);//网页刷新时调用

    };

tick();

我们使用requestAnimationFrame函数每次刷新就更新TimeIndex的值。

效果:

http://s5/small/006pZnPwzy7p5YumYsc34&690

示例源码:github地址

号外:我的学习公众号也开通,感兴趣的小伙伴们可以加关注giserYZ2SS

http://s3/small/006pZnPwzy7p6EYHeRYb2&690

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有