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的主函数后,发现形式差不多: ...
随机推荐
- 安利一个MVC的好东西,RazorGenerator.MsBuild,可以自动编译cshtml文件
在传统的asp.net webForm 开发里,在发布时,如果选择预编译,就会自动将所有的aspx 文件编译,在发布后的目录里,就看不到aspx的源代码了,同时因为是预编译的,所以每个页面打开速度都挺 ...
- RDD常用方法之subtract&intersection&cartesian
subtract Return an RDD with the elements from `this` that are not in `other` . def subtract(othe ...
- 让VS 2010在调试字符串时,支持Json数据格式友好显示
阅读本文如果对Microsoft.VisualStudio.DebuggerVisualizers的用法不熟悉的,可以参考这篇文章.http://www.cnblogs.com/devil0153/a ...
- django--模型元选项(八)
1.db_table Options.db_table该模型所用的数据表的名称:db_table = 'test'为节省你的时间,Django 会根据模型类的名称和包含它的应用的名称自动指定数据库表名 ...
- js截取url的参数(转自。。)
用JS获取地址栏参数的方法(超级简单) 方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!) function GetQueryString(name) { var reg ...
- Mysql 关键字及保留字
Table 10.2 Keywords and Reserved Words in MySQL 5.7 ACCESSIBLE (R) ACCOUNT[a] ACTION ADD (R) AFTER A ...
- ue4框架C++语法汇总文章
1.Run external .exe file TCHAR* url = TEXT("C:\\windows\\system32\\calc.exe"); FPlatformPr ...
- 关于GPL的一些知识
1.什么是GPL GPL许可协议(GNU General Public License):只要软件中包含有其他GPL协议的产品或代码,那么该软件就必须也采用GPL许可协议且开源及免费.具有以下特点: ...
- 用jquery解析JSON数据的方法以及字符串转换成json的3种方法
用jquery解析JSON数据的方法,作为jquery异步请求的传输对象,jquery请求后返回的结果是 json对象,这里考虑的都是服务器返回JSON形式的字符串的形式,对于利用JSONObject ...
- NoSQL学习——MongoDB
MongoDB作为一款文档数据库,支持分片存储,scale-out,集群自动切换,下面将粗略的配置步骤总结如下: 几个重要概念: 数据库:集合--记录--游标(查询时标记序号) sharding分片: ...