Cesium原理篇:6 Renderer模块(2: Texture)
Texture也是WebGL中重要的概念,使用起来也很简单。但有句话叫大道至简,如果真的想要用好纹理,里面的水其实也是很深的。下面我们来一探究竟。
下面是WebGL中创建一个纹理的最简过程:
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
// 创建纹理句柄
var texture = gl.createTexture();
// 填充纹理内容
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
// 设置纹理参数
//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
//gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
// 释放
gl.bindTexture(gl.TEXTURE_2D, null);
如果你觉得上面的这段代码简单易懂,不妨在看看WebGL中提供的gl.glTexImage2D的重载方法:
void gl.texImage2D(target, level, internalformat, width, height, border, format, type, ArrayBufferView? pixels);
void gl.texImage2D(target, level, internalformat, format, type, ImageData? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLImageElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLCanvasElement? pixels);
void gl.texImage2D(target, level, internalformat, format, type, HTMLVideoElement? pixels);
一个再简单的纹理调用,在实际中也会有变幻无穷的方式,而这就是实现功能和产品封装上的区别,Cesium中提供了Texture类,整体上考虑了主要的使用场景,在代码设计上简化了学习成本,当然在编码上也较为优雅,我们不妨看一下Cesium中创建纹理的伪代码:
function Texture(options) {
// 如下三个if判断,用来查看是否是深度纹理、深度模版纹理或浮点纹理
// 并判断当前浏览器是否支持,数据类型是否满足要求
if (pixelFormat === PixelFormat.DEPTH_COMPONENT) {
}
if (pixelFormat === PixelFormat.DEPTH_STENCIL) {
}
if (pixelDatatype === PixelDatatype.FLOAT) {
}
var preMultiplyAlpha = options.preMultiplyAlpha || pixelFormat === PixelFormat.RGB || pixelFormat === PixelFormat.LUMINANCE;
var flipY = defaultValue(options.flipY, true);
var gl = context._gl;
var textureTarget = gl.TEXTURE_2D;
var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(textureTarget, texture);
if (defined(source)) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);
// Y轴方向是否翻转
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
if (defined(source.arrayBufferView)) {
// 纹理数据是arraybuffer的形式下,调用此方法
gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, source.arrayBufferView);
} else if (defined(source.framebuffer)) {
// 纹理数据是纹理缓冲区中的数据时,调用此方法
if (source.framebuffer !== context.defaultFramebuffer) {
source.framebuffer._bind();
}
gl.copyTexImage2D(textureTarget, 0, internalFormat, source.xOffset, source.yOffset, width, height, 0);
if (source.framebuffer !== context.defaultFramebuffer) {
source.framebuffer._unBind();
}
} else {
// 纹理数据是其他类型: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement
gl.texImage2D(textureTarget, 0, internalFormat, pixelFormat, pixelDatatype, source);
}
} else {
// 纹理数据为空
gl.texImage2D(textureTarget, 0, internalFormat, width, height, 0, pixelFormat, pixelDatatype, null);
}
gl.bindTexture(textureTarget, null);
}
Cesium.Texture支持纹理贴图,还有深度和模版,以及浮点纹理等扩展性的用法,保证了Cesium可以支持深度值,模版等操作,满足一些复杂情况下的需求,同时,通过Texture.fromFramebuffer方式,可以支持FBO作为一张纹理,实现离屏渲染的效果。因此,在纹理数据创建上,Cesium还是比较完整的。
同时,Cesium.Sample类提供了数据的一些显示风格设置,比如TextureWrap,Filter的设置,在Texture类中有一个sampler的属性,用户在赋值时自动设置:
sampler : {
get : function() {
return this._sampler;
},
set : function(sampler) {
// ……
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, minificationFilter);
gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, magnificationFilter);
gl.texParameteri(target, gl.TEXTURE_WRAP_S, sampler.wrapS);
gl.texParameteri(target, gl.TEXTURE_WRAP_T, sampler.wrapT);
if (defined(this._textureFilterAnisotropic)) {
gl.texParameteri(target, this._textureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, sampler.maximumAnisotropy);
}
gl.bindTexture(target, null);
this._sampler = sampler;
}
},
另外,为了解决纹理闪烁的情况,Cesium中提供了MipMap的设置方式:
Texture.prototype.generateMipmap = function(hint) {
hint = defaultValue(hint, MipmapHint.DONT_CARE);
var gl = this._context._gl;
var target = this._textureTarget;
gl.hint(gl.GENERATE_MIPMAP_HINT, hint);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(target, this._texture);
gl.generateMipmap(target);
gl.bindTexture(target, null);
};
当然,这种方式比较方便,浏览器内部自己创建MipMap,相当于一个影像金字塔的过程,如果你出于效率和效果的优化,希望自己创建MipMap也是可以的,不过目前的Cesium.Texture还不支持这种情况。
个人认为,目前Texture实现的中规中矩,基本支持了各种纹理情况,能够满足后面模版缓存,深度缓存等高级用法,并对这一部分做了一个很好的封装,能够满足各类应用。但如果想要用好纹理,其实里面还有很多可以扩展的地方,比如支持压缩纹理,这对于显存的意义,特别是Cesium这种比较消耗显存的应用(特别是移动端),还是很有意义的。对纹理压缩技术感兴趣的,可以读一下这篇《为什么需要纹理压缩》,当然效率高也是有代价了,比如效果和兼容性,另外,随着对纹理创建的增加,个人认为增加一个纹理管理器TextureManager还是很有必要的,而且并不复杂。
Cesium原理篇:6 Renderer模块(2: Texture)的更多相关文章
- Cesium原理篇:7最长的一帧之Entity(下)
上一篇,我们介绍了当我们添加一个Entity时,通过Graphics封装其对应参数,通过EntityCollection.Add方法,将EntityCollection的Entity传递到DataSo ...
- Cesium原理篇:5最长的一帧之影像
如果把地球比做一个人,地形就相当于这个人的骨骼,而影像就相当于这个人的外表了.之前的几个系列,我们全面的介绍了Cesium的地形内容,详见: Cesium原理篇:1最长的一帧之渲染调度 Cesium原 ...
- Cesium原理篇:3最长的一帧之地形(2:高度图)
这一篇,接着上一篇,内容集中在高度图方式构建地球网格的细节方面. 此时,Globe对每一个切片(GlobeSurfaceTile)创建对应的TileTerrain类,用来维 ...
- Cesium原理篇:6 Renderer模块(1: Buffer)
刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分理解它,需要对DataSource,Primitive要有基础,而这要求对 ...
- Cesium原理篇:6 Renderer模块(1: Buffer)【转】
https://www.bbsmax.com/A/n2d9P1Q5Dv/ 刚刚结束完地球切片的渲染调度后,打算介绍一下目前大家都很关注的3D Tiles方面的内容,但发现要讲3D Tiles,或者充分 ...
- Cesium原理篇:6 Render模块(3: Shader)
在介绍Renderer的第一篇,我就提到WebGL1.0对应的是OpenGL ES2.0,也就是可编程渲染管线.之所以单独强调这一点,算是为本篇埋下一个伏笔.通过前两篇,我们介绍了VBO和Textur ...
- Cesium原理篇:6 Render模块(6: Instance实例化)
最近研究Cesium的实例化,尽管该技术需要在WebGL2.0,也就是OpenGL ES3.0才支持.调试源码的时候眼前一亮,发现VAO和glDrawBuffers都不是WebGL1.0的标准函数,都 ...
- Cesium原理篇:6 Render模块(6: Instance实例化)【转】
https://www.cnblogs.com/fuckgiser/p/6027520.html 最近研究Cesium的实例化,尽管该技术需要在WebGL2.0,也就是OpenGL ES3.0才支持. ...
- Cesium原理篇:6 Render模块(3: Shader)【转】
https://www.cnblogs.com/fuckgiser/p/5975274.html 在介绍Renderer的第一篇,我就提到WebGL1.0对应的是OpenGL ES2.0,也就是可编程 ...
随机推荐
- 线程处理模型 由于 SynchronizationContext 引起的死锁问题解决
由于GUI 应用程序 不能使用线程池的线程更新UI,只能使用 GUI 线程更新,所以在 await 前后需要保证是同一个 GUI 线程 ASP.NET 程序 的线程处理客户端请求的时候,需要假定客户端 ...
- oracle--导出、导入blob类型的字段
blob是oracle中的一个数据类型,保存的是压缩后的二进制形式的大数据. 数据迁移如果涉及到blob字段,都不好处理,因为无法用常规方法进行操作,如:使用select查看该字段,也无法用inser ...
- jQuery最基础最全面的选择器大览
一.基本选择器 1.标签选择器 (element):根据给定的标签名匹配元素 eg:$("h2")选取所有h2元素 --- 返回元素集合 2.类选择器 (.class):根 ...
- Unity学习疑问记录之协程
http://blog.csdn.net/huang9012/article/details/38492937 总结:1.协程相当于多线程但不是,(尽管它们看上去是这样的),它们运行在同一线程中,跟普 ...
- C#_闭包陷阱
如果匿名方法(Lambda表达式)引用了某个局部变量,编译器就会自动将该引用提升到该闭包对象中. 即将for循环中的变量i修改成了引用闭包对象的公共变量i.这样一来,即使代码执行后离开了原局部变量i的 ...
- PostgreSQL 杂志
pgmag 团队刚发布了头两期 PostgreSQL 杂志,还有中文版http://pgmag.org/download,推荐广大 PostgreSQL 数据库管理员及开发者阅读: Issue #01 ...
- smartComplete——轻量级的autoComplete插件,开源
项目后端觉得autoComplete响应略慢,于是花了两天时间写了这插件,基于jQuery 1.7+,仓库地址 https://github.com/VaJoy/smartComplete ,欢迎各种 ...
- 备忘录:hadoop技术一点积累
1.hbase的rowkey是按字典排序的,我看有的资料建议rowkey设计不应该是自增的,应该和这个字典排序相关吧 2.hbase的数据存储是按照region来的,region的设计前段时间在坐飞机 ...
- 让Ajax更简单
之前写了一篇 ASP.NET中一种超简单的Ajax解决方案 最近把他拿出来更新了下,把demo也搞的更详细了一点 加入了blqw.Json,所以支持更多类型参数和返回值 优化了对exception的处 ...
- 控制Linux下 mono 服务的启动停止
当Window下的服务部署到Linux的时候,我们一般用Mono.service 来启动停止.参数比较多,不太好用.于是有个这个Shell脚本. 用法:moa s1 start #启动 ...