Ptex源码学习笔记-1
Ptex是Walt Disney Animation Studios开发的纹理映射工具。在看一个叫appleseed的渲染器时看到他支持这种纹理,所以就查看一下,发现比较轻量,所以就想趁此机会学习下。
Ptex开源代码主要包含该格式的定义、IO、缓存和一些常见filter。头文件Ptexture.h定义了纹理的数据结构和所有操作的API,类定义都是抽象类,ctor和dtor都不是public,生成对象需要通过其他接口来获取实例,或者调用静态函数进行操作,释放对象不能直接调用dtor,统一由release函数delete或返回缓存,大多数对象可以跨线程共用,所以需要ref count,release时大多只是减ref。另外定义了一个用来管理对象的指针类PtexPtr,可以封装所有对象,并在超出作用域后自动release。
主要数据结构:
- struct Res,定义纹理的分辨率,按像素的log2存储,长度为8位int,其ctor可以用16位int作为参数,分高低8位储存uv,最小单元(texel)分辨率为1*1(ulog2 = vlog2 = 0),支持tile划分。
- FaceInfo,定义面信息,主要包括面的分辨率、相邻面和相邻边(对应相邻面的边ID),相邻面为32位int数组,一个面有4个相邻面,-1表示该相邻面为空,相邻边为8位uint,每个长度为2位,合并为8位保存,相邻面的遍历按边的ID从底部逆时针进行,边的左右顶底在该头文件的enum定义中(三角形没定义),如果相邻面是细分面(有多个面在当前面的同一边),则以逆时针遍历第一个遇到的面为整个相邻面的ID。
读取header信息:
纹理信息保存在PtexTexture对象中,该对象不能由自己生成,只能通过静态open函数(PtextReader)或PtexCache接口生成。首先,锁mutex,将ptex文件以二进制形式打开(不转译回车和换行字符)并设置buffer,然后读取header,保存有各种校验信息和大小数目参数,以此对读取的文件进行校验,然后读取extended header,header中可以定义extended header的大小,struct ExtHeader的大小为40字节,所以在读取时应该以最小的为准,然后计算各个数据的起始位置,调用读取函数,包括:
- 读取面信息。读取过程分三步,首先从压缩的文件中读取FaceInfo,每次读取header中定义的faceinfosize或着16384字节(faceinfosize > BlockSize)为一个block,然后生成rfaceid(先按面在内存中的储存顺序分配id,然后以面的uv分辨率最小的那个作为依据降序排列面的顺序,该顺序就是rfaceid,面为常量则分辨率当作1),并建立rfaceid和faceid的映射关系,最后更新已使用的内存数。
- 读取面的常量像素值。读取过程分三步,第一和三步同上,第二步为alpha通道的预乘处理,先判断alpha通道的位置来确定需要预乘的通道,然后根据不同的像素存储类型归一化alpha值,最后将归一化的alpha值与需要预乘的通道的像素值相乘。
- 读取层次信息。读取过程分三步,第一和三步同上,第二步为层次定位,依次储存每一层次的开始位置。
- 读取编辑数据。读取过程分三步,首先确定编辑位置,然后根据编辑的类型读取,分为面数据和元数据两类,先读取对应的编辑header,然后保存编辑内容,编辑面数据还需要读取面的常数像素值,最后更新内存使用记录。
获取纹理数据:
大部分数据可以通过简单返回获得,下面主要看几个比较复杂的数据:
- 获取元数据。元数据分meta data和large meta data两类,其大小分别定义在header和extheader中。两者的获取类似,都是建立kv映射,key为string表示名字,value为entry存储元数据,entry内保存了数据位置作为key,直接从内存将所需数据拷贝到指定位置,区别在于lmd的entry没有保存解压后的数据,而是数据的位置,只有在载入并引用后才能访问,有一个flag标识lmd。
- 获取一个面的纹理数据。有四种获取方式,获取最高分辨率的纹理、获取指定分辨率的纹理、获取硬盘上保存的最高分辨率的纹理、获取硬盘上保存的指定分辨率的纹理。前两种是把数据拷贝到指定buffer里,后两种是返回facedata的指针,在获取指定分辨率的纹理时,如果mipmap有对应的分辨率就直接从mipmap获取,否则就用最近的分辨率生存新的纹理。第一种:首先获取面的分辨率,然后调用第二种函数。第二种:使用PtexPtr管理对象,调用第四种函数获取facedata指针,如果是常数,则直接用该像素充填buffer;如果不是常数且分tile,则按tile(v major遍历)充填buffer,如果tile为常数,则直接用该像素充填tile的第一行,然后用第一行充填其他行,如果tile不是常数,则根据stride大小决定拷贝方式,如果stride等于行长度,则直接整体拷贝相应数据到tile,否则按行拷贝,如果不是常数且不分tile,则根据stride大小决定拷贝方式。第三种:获取level 0后根据level获取facedata,如果level没有被读取过,则初始化level,如果face没有和level建立关系,则根据face data header的编码方式初始化指定facedata并保存。第四种:主要处理mipmap,如果设置的分辨率不需要reduction则直接获取level 0的facedata,如果是对称reduction,则用u方向的reduction作为levelid直接查找facedata,如果不能查到,则需要动态reduction,首先在cache里查,如果没有则生存新的reduction,根据reduction的方向(u或v)来reduce,生存后存入reduction cache并返回facedata。
- 获取一个面的纹理的一个texel数据。有两种获取方式,获取最高分辨率纹理的texel、获取指定分辨率纹理的texel。两种方式基本类似,首先获取实际通道数,然后获取facedata,然后就可以得到像素值,然后根据第一通道位置来设置像素保存的偏移量,最后保存,如果像素值不是float,则转成float保存。二者的区别在获取facedata,第二种需要根据reduction来确定mipmap的level获取相应facedata。
Ptex源码学习笔记-1的更多相关文章
- Ptex源码学习笔记-2
写入纹理数据: 主要分为五种写入方式:新建纹理.编辑已有纹理.编辑ExtHeader中的指定项.写入元数据和写入指定面的纹理数据.写入过程中数据存在一个临时文件中,在close时才会把临时文件的内容拷 ...
- Underscore.js 源码学习笔记(下)
上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...
- Underscore.js 源码学习笔记(上)
版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}()); 这样的东西,我们应该知道这是一个 IIFE(立即执行 ...
- AXI_LITE源码学习笔记
AXI_LITE源码学习笔记 1. axi_awready信号的产生 准备接收写地址信号 // Implement axi_awready generation // axi_awready is a ...
- Hadoop源码学习笔记(6)——从ls命令一路解剖
Hadoop源码学习笔记(6) ——从ls命令一路解剖 Hadoop几个模块的程序我们大致有了点了解,现在我们得细看一下这个程序是如何处理命令的. 我们就从原头开始,然后一步步追查. 我们先选中ls命 ...
- Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构
Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...
- Hadoop源码学习笔记(4) ——Socket到RPC调用
Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要 ...
- Hadoop源码学习笔记(3) ——初览DataNode及学习线程
Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...
- Hadoop源码学习笔记(2) ——进入main函数打印包信息
Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...
随机推荐
- JS获取form表单所有属性值
// 得到一个表单里的全部信息function getFormQueryString() { var frmID=document.forms[0]; var i,queryString=" ...
- 关于Python的数据分析工具
Python - 核心编程环境NumPy/SciPy - 用于快速.高效的数组和矩阵运算IPython - 用于Python的可视化交互开发matplotlib - 用于数据的图形可视化pandas ...
- 常用的.Net 知识点
1.Replace C#:(using System.Text.RegularExpressions;) string txt = Regex.Replace(txtLog.Text.ToString ...
- mac系统下Ruby环境安装
在我们编写代码过程中,会用到一系列的第三方开源类库,我们可以选择手动去一个个添加需要的库,但这非常麻烦.因此我们可以使用CocoaPods来帮助我们自动添加.使用CocoaPods需要先安装Ruby环 ...
- js事件(一)之事件流
1.事件流定义 事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流. 事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事 ...
- WKWebView _WebFilterIsActive returning: NO
写这篇文是因为在UIWebView加载页面的时候有时候会返回: filterBlacklist = ( ); filterWhitelist = ( ); restrictWeb = 1; useCo ...
- adb常用命令
adb命令的主要用途 1. 运行android设备的shell(命令行). 2.管理模拟器或android设备的映射端口. 3. 安装和卸载应用程序. 4.计算机和android设备之间的上传 ...
- 10个顶级的CSS UI开源框架
随着CSS3和HTML5的流行,我们的WEB页面不仅需要更人性化的设计理念,而且需要更酷的页面特效和用户体验.作为开发者,我们需要了解一些宝贵的CSS UI开源框架资源,它们可以帮助我们更快更好地实现 ...
- 《SSM框架搭建》二.mybatis3,spring4整合
感谢学习文章来自http://www.cnblogs.com/xdp-gacl/p/4271627.html,spring3修改为spring4.还有提示驱动过期的问题,是由于使用了mysql-con ...
- php下载网络图片到服务器
/** * 下载二维码到服务器 * @param string $url 图片路径 * @param string $filestring 要保存的文件名 */ private function ...