Q116:PBRT-V3场景描述文件.pbrt格式解析
對(duì)于PBRT-V3場(chǎng)景文件.pbrt格式,小編自己根據(jù)自己的理解總結(jié)如下:
1,“#”后面的內(nèi)容為注釋
舉例1:
#sphere.pbrt #first we set up the eye2,每一行的第一個(gè)詞為“關(guān)鍵字”,在api.cpp中對(duì)應(yīng)著處理函數(shù)。
舉例2:
#first we set up the eye LookAt 1 1 10 0 0 -1 0 1 0 #ex ey ez lx ly lz ux uy uz#the camera Camera "perspective" "float fov" [30]#name the file Film "image" "string filename" ["sphere.exr"]"integer xresolution" [200] "integer yresolution" [200]Integrator "whitted"#begin describing scene WorldBegin#light source AttributeBeginCoordSysTransform "camera"LightSource "distant" "point from" [0 0 0] "point to" [0 0 1]"color L" [3 3 3] AttributeEnd在api.cpp中:
關(guān)鍵字“LookAt”對(duì)應(yīng)的處理函數(shù)是pbrtLookAt(); 
 關(guān)鍵字“Camera”對(duì)應(yīng)的處理函數(shù)是pbrtCamera(); 
 關(guān)鍵字“Film”對(duì)應(yīng)的處理函數(shù)是pbrtFilm(); 
 關(guān)鍵字“Integrator”對(duì)應(yīng)的處理函數(shù)是pbrtIntegrator(); 
 關(guān)鍵字“WorldBegin”對(duì)應(yīng)的處理函數(shù)是pbrtWorldBegin(); 
 關(guān)鍵字“AttributeBegin”對(duì)應(yīng)的處理函數(shù)是pbrtAttributeBegin(); 
 關(guān)鍵字“CoordSysTransform”對(duì)應(yīng)的處理函數(shù)是pbrtCoordSysTransform(); 
 關(guān)鍵字“LightSource”對(duì)應(yīng)的處理函數(shù)是pbrtLightSource(); 
 關(guān)鍵字“AttributeEnd”對(duì)應(yīng)的處理函數(shù)是pbrtAttributeEnd();
關(guān)鍵字還有:Translate,Rotate,Scale,Material,Shape等等。
3,AttributeBegin和AttributeEnd是成對(duì)順序出現(xiàn),最臨近的一對(duì)包含的內(nèi)容可是為一個(gè)block。
舉例3:
AttributeBeginTranslate 0 -1 0Rotate 35 0 1 0#define a sphereAttributeBeginTranslate -1 .75 -1.5Rotate -90 1 0 0Material "matte" "color Kd" [0.1 0.9 0.1]Shape "sphere" "float radius" [.75] AttributeEnd#define a coneAttributeBeginTranslate 0 0 2.5Rotate -90 1 0 0#this describes the material propertiesMaterial "matte" "color Kd" [0.9 0.1 0.1]#this is the shapeShape "cone" "float radius" [.75] "float height" [2]AttributeEndAttributeEnd如上有三對(duì)AttributeBegin/AttributeEnd,剛好也有三組仿射變換Translate/Rotate。
第二組Translate/Rotate只作用于第二對(duì)AttributeBegin/AttributeEnd包住的sphere; 
 第三組Translate/Rotate只作用于第三對(duì)AttributeBegin/AttributeEnd包住的cone; 
 由于第一對(duì)AttributeBegin/AttributeEnd包住的是sphere和cone,所以,第一組Translate/Rotate對(duì)sphere和cone都起作用。
4,對(duì)關(guān)鍵字后參數(shù)的解析
4.1 關(guān)鍵字后直接跟參數(shù)值,直接解析,處理函數(shù)形參中順序?qū)?yīng)這些參數(shù)。
舉例4:
LookAt 1 1 10 0 0 -1 0 1 0 #ex ey ez lx ly lz ux uy uz處理函數(shù)原型:
void pbrtLookAt(Float ex, Float ey, Float ez, Float lx, Float ly, Float lz, Float ux, Float uy, Float uz);舉例5:
Translate 0 -1 0Rotate 35 0 1 0處理函數(shù)原型:
void pbrtTranslate(Float dx, Float dy, Float dz); void pbrtRotate(Float angle, Float ax, Float ay, Float az);4.2 關(guān)鍵字后跟:類(lèi)型+屬性,其中“屬性”的格式是:“屬性類(lèi)型 屬性名稱”[該名稱屬性對(duì)應(yīng)的值]
“屬性”的格式類(lèi)似于:
float num = 3.0;即:類(lèi)型+變量+賦值
舉例6:
Film "image" "string filename" ["sphere.exr"]"integer xresolution" [200] "integer yresolution" [200]解析: 
 關(guān)鍵字是Film; 
 這個(gè)Film的類(lèi)型是image; 
 這個(gè)image類(lèi)型的Film有三個(gè)屬性:
屬性一:有個(gè)string類(lèi)型的屬性叫做filename,這個(gè)filename的值是“sphere.exr” 
 屬性二:有個(gè)integer類(lèi)型的屬性叫做xresolution,這個(gè)xresolution的值為200 
 屬性三:有個(gè)integer類(lèi)型的屬性叫做yresolution,這個(gè)yresolution的值為200
處理函數(shù)原型:
void pbrtFilm(const std::string &type, const ParamSet ¶ms);舉例7:
LightSource "distant" "point from" [0 0 0] "point to" [0 0 1]"color L" [3 3 3]解析: 
 關(guān)鍵字是LightSource; 
 這個(gè)LightSource的類(lèi)型是distant; 
 這個(gè)distant類(lèi)型的LightSource有三個(gè)屬性:
屬性一:有個(gè)point類(lèi)型的屬性叫做from,這個(gè)from的值為[0 0 0] 
 屬性二:有個(gè)point類(lèi)型的屬性叫做to,這個(gè)to的值為[0 0 1] 
 屬性三:有個(gè)color類(lèi)型的屬性叫做L,這個(gè)L的值為[3 3 3]
處理函數(shù)原型:
void pbrtLightSource(const std::string &name, const ParamSet ¶ms);舉例8:
Material "uber" "color Kd" [0.1 0.1 0.9] "color Kr" [0.9 0.9 0.9] "color Ks" [0.1 0.1 0.1] "float roughness" [0.9] "float index" [1.34]解析: 
 關(guān)鍵字是Material; 
 這個(gè)Material的類(lèi)型是uber; 
 這個(gè)uber類(lèi)型的Material有五個(gè)屬性:
屬性一:有個(gè)color類(lèi)型的屬性叫做Kd,這個(gè)Kd的值為[0.1 0.1 0.9] 
 屬性二:有個(gè)color類(lèi)型的屬性叫做Kr,這個(gè)Kr的值為[0.9 0.9 0.9] 
 屬性三:有個(gè)color類(lèi)型的屬性叫做Ks,這個(gè)Ks的值為[0.1 0.1 0.1] 
 屬性四:有個(gè)float類(lèi)型的屬性叫做roughness,這個(gè)roughness的值為0.9 
 屬性五:有個(gè)float類(lèi)型的屬性叫做index,這個(gè)index的值為1.34
處理函數(shù)原型:
void pbrtMaterial(const std::string &name, const ParamSet ¶ms);4.3 關(guān)鍵字后跟:類(lèi)型+X+X+……+屬性
這種情況和4.2比較類(lèi)似,只是在“類(lèi)型”、“屬性”之間加了若干其他信息。
舉例9:
Texture "grid" "color" "imagemap" "string filename" ["textures/lines.png"]處理函數(shù)原型:
void pbrtTexture(const std::string &name, const std::string &type,const std::string &texname, const ParamSet ¶ms);其實(shí),所有情況都可以歸到“X+X+X+屬性”。 
 只是, 
 有的只有X+X+X; 
 有的X多; 
 有的X少;
不管是哪種情況,最終都是取決于“處理函數(shù)原型”。
———————————————-
“.pbrt格式解析”完畢!!!!! 
 接下來(lái)的內(nèi)容是“程序?qū)?pbrt文件的處理過(guò)程”
———————————————-
參考:Q111:PBRT-V3系統(tǒng)概述
5,程序中解析的過(guò)程
PBRT-V3是用第三方程序flex、bison來(lái)解析場(chǎng)景描述文件的。
接下來(lái),小編以解析LightSource為例說(shuō)明一下從開(kāi)始解析到存儲(chǔ)數(shù)據(jù)的過(guò)程。
舉例10:
LightSource "distant" "point from" [0 0 0] "point to" [0 0 1]"color L" [3 3 3]在pbrtparse.y中有:
| LIGHTSOURCE STRING paramlist {pbrt::ParamSet params;pbrt::InitParamSet(params, pbrt::SpectrumType::Illuminant);pbrt::pbrtLightSource($2, params);pbrt::FreeArgs(); }這個(gè)是告訴flex、bison在讀到關(guān)鍵字“LightSource”時(shí)要做的事情。
先看這句:
pbrt::pbrtLightSource($2, params);這句是最終調(diào)用處理函數(shù)pbrtLightSource(),給該函數(shù)傳了兩個(gè)參數(shù): 
 $2,存放的是LightSource的類(lèi)型名,此處即為“distant”; 
 params,存放的是這個(gè)distant類(lèi)型的LightSource的所有屬性。
5.1 初始化params
存放屬性的params是一個(gè)ParamSet對(duì)象。ParamSet是在src/core/paramset.h中定義的。
class ParamSet {public:// ParamSet Public MethodsParamSet() {}void AddFloat(const std::string &, std::unique_ptr<Float[]> v,int nValues = 1);void AddInt(const std::string &, std::unique_ptr<int[]> v, int nValues);void AddBool(const std::string &, std::unique_ptr<bool[]> v, int nValues);void AddPoint2f(const std::string &, std::unique_ptr<Point2f[]> v,int nValues);void AddVector2f(const std::string &, std::unique_ptr<Vector2f[]> v,int nValues);void AddPoint3f(const std::string &, std::unique_ptr<Point3f[]> v,int nValues);void AddVector3f(const std::string &, std::unique_ptr<Vector3f[]> v,int nValues);void AddNormal3f(const std::string &, std::unique_ptr<Normal3f[]> v,int nValues);void AddString(const std::string &, std::unique_ptr<std::string[]> v,int nValues);void AddTexture(const std::string &, const std::string &);void AddRGBSpectrum(const std::string &, std::unique_ptr<Float[]> v,int nValues);void AddXYZSpectrum(const std::string &, std::unique_ptr<Float[]> v,int nValues);void AddBlackbodySpectrum(const std::string &, std::unique_ptr<Float[]> v,int nValues);void AddSampledSpectrumFiles(const std::string &, const char **,int nValues);void AddSampledSpectrum(const std::string &, std::unique_ptr<Float[]> v,int nValues);bool EraseInt(const std::string &);bool EraseBool(const std::string &);bool EraseFloat(const std::string &);bool ErasePoint2f(const std::string &);bool EraseVector2f(const std::string &);bool ErasePoint3f(const std::string &);bool EraseVector3f(const std::string &);bool EraseNormal3f(const std::string &);bool EraseSpectrum(const std::string &);bool EraseString(const std::string &);bool EraseTexture(const std::string &);Float FindOneFloat(const std::string &, Float d) const;int FindOneInt(const std::string &, int d) const;bool FindOneBool(const std::string &, bool d) const;Point2f FindOnePoint2f(const std::string &, const Point2f &d) const;Vector2f FindOneVector2f(const std::string &, const Vector2f &d) const;Point3f FindOnePoint3f(const std::string &, const Point3f &d) const;Vector3f FindOneVector3f(const std::string &, const Vector3f &d) const;Normal3f FindOneNormal3f(const std::string &, const Normal3f &d) const;Spectrum FindOneSpectrum(const std::string &, const Spectrum &d) const;std::string FindOneString(const std::string &, const std::string &d) const;std::string FindOneFilename(const std::string &,const std::string &d) const;std::string FindTexture(const std::string &) const;const Float *FindFloat(const std::string &, int *n) const;const int *FindInt(const std::string &, int *nValues) const;const bool *FindBool(const std::string &, int *nValues) const;const Point2f *FindPoint2f(const std::string &, int *nValues) const;const Vector2f *FindVector2f(const std::string &, int *nValues) const;const Point3f *FindPoint3f(const std::string &, int *nValues) const;const Vector3f *FindVector3f(const std::string &, int *nValues) const;const Normal3f *FindNormal3f(const std::string &, int *nValues) const;const Spectrum *FindSpectrum(const std::string &, int *nValues) const;const std::string *FindString(const std::string &, int *nValues) const;void ReportUnused() const;void Clear();std::string ToString() const;void Print(int indent) const;private:// ParamSet Private Datastd::vector<std::shared_ptr<ParamSetItem<bool>>> bools;std::vector<std::shared_ptr<ParamSetItem<int>>> ints;std::vector<std::shared_ptr<ParamSetItem<Float>>> floats;std::vector<std::shared_ptr<ParamSetItem<Point2f>>> point2fs;std::vector<std::shared_ptr<ParamSetItem<Vector2f>>> vector2fs;std::vector<std::shared_ptr<ParamSetItem<Point3f>>> point3fs;std::vector<std::shared_ptr<ParamSetItem<Vector3f>>> vector3fs;std::vector<std::shared_ptr<ParamSetItem<Normal3f>>> normals;std::vector<std::shared_ptr<ParamSetItem<Spectrum>>> spectra;std::vector<std::shared_ptr<ParamSetItem<std::string>>> strings;std::vector<std::shared_ptr<ParamSetItem<std::string>>> textures;static std::map<std::string, Spectrum> cachedSpectra; };ParamSet的定義看起來(lái)蠻復(fù)雜的,其實(shí)就干四件事(有點(diǎn)類(lèi)似于數(shù)據(jù)庫(kù)及對(duì)數(shù)據(jù)的CRUD):
> 其一:定義了存放各種屬性類(lèi)型數(shù)據(jù)的容器;比如:bools, ints, floats, spectra, strings等等。 > 其二:對(duì)各類(lèi)容器進(jìn)行添加數(shù)據(jù); > 其三:對(duì)各類(lèi)容器進(jìn)行刪除數(shù)據(jù); > 其四:在各類(lèi)容器查找數(shù)據(jù);(這里注意一下,是根據(jù)“屬性名稱”進(jìn)行查找的)接下來(lái),看看具體是怎么為params填充數(shù)據(jù)的,調(diào)用的是這個(gè)函數(shù):
pbrt::InitParamSet(params, pbrt::SpectrumType::Illuminant);在partparse.y中有這么一段code,“定義”了所有“屬性類(lèi)型”:
TRY_DECODING_TYPE("float", PARAM_TYPE_FLOAT)else TRY_DECODING_TYPE("integer", PARAM_TYPE_INT)else TRY_DECODING_TYPE("bool", PARAM_TYPE_BOOL)else TRY_DECODING_TYPE("point2", PARAM_TYPE_POINT2)else TRY_DECODING_TYPE("vector2", PARAM_TYPE_VECTOR2)else TRY_DECODING_TYPE("point3", PARAM_TYPE_POINT3)else TRY_DECODING_TYPE("vector3", PARAM_TYPE_VECTOR3)else TRY_DECODING_TYPE("point", PARAM_TYPE_POINT3)else TRY_DECODING_TYPE("vector", PARAM_TYPE_VECTOR3)else TRY_DECODING_TYPE("normal", PARAM_TYPE_NORMAL)else TRY_DECODING_TYPE("string", PARAM_TYPE_STRING)else TRY_DECODING_TYPE("texture", PARAM_TYPE_TEXTURE)else TRY_DECODING_TYPE("color", PARAM_TYPE_RGB)else TRY_DECODING_TYPE("rgb", PARAM_TYPE_RGB)else TRY_DECODING_TYPE("xyz", PARAM_TYPE_XYZ)else TRY_DECODING_TYPE("blackbody", PARAM_TYPE_BLACKBODY)else TRY_DECODING_TYPE("spectrum", PARAM_TYPE_SPECTRUM)然后,在InitParamSet()中會(huì)根據(jù)屬性類(lèi)型調(diào)用ParamSet對(duì)應(yīng)的成員函數(shù)來(lái)給params填充數(shù)據(jù)。
對(duì)于:
LightSource "distant" "point from" [0 0 0] "point to" [0 0 1]"color L" [3 3 3]就會(huì)調(diào)用到:
void AddPoint3f(const std::string &, std::unique_ptr<Point3f[]> v, int nValues);void AddRGBSpectrum(const std::string &, std::unique_ptr<Float[]> v, int nValues);具體實(shí)現(xiàn)在paramset.cpp中:
void ParamSet::AddPoint3f(const std::string &name,std::unique_ptr<Point3f[]> values, int nValues) {ErasePoint3f(name);ADD_PARAM_TYPE(Point3f, point3fs); } void ParamSet::AddRGBSpectrum(const std::string &name,std::unique_ptr<Float[]> values, int nValues) {EraseSpectrum(name);CHECK_EQ(nValues % 3, 0);nValues /= 3;std::unique_ptr<Spectrum[]> s(new Spectrum[nValues]);for (int i = 0; i < nValues; ++i) s[i] = Spectrum::FromRGB(&values[3 * i]);std::shared_ptr<ParamSetItem<Spectrum>> psi(new ParamSetItem<Spectrum>(name, std::move(s), nValues));spectra.push_back(psi); }5.2 pbrtLightSource()
pbrtLightSource將數(shù)據(jù)寫(xiě)入渲染內(nèi)存中。
void pbrtLightSource(const std::string &name, const ParamSet ¶ms) {VERIFY_WORLD("LightSource");WARN_IF_ANIMATED_TRANSFORM("LightSource");MediumInterface mi = graphicsState.CreateMediumInterface();std::shared_ptr<Light> lt = MakeLight(name, params, curTransform[0], mi);if (!lt)Error("LightSource: light type \"%s\" unknown.", name.c_str());elserenderOptions->lights.push_back(lt);if (PbrtOptions.cat || PbrtOptions.toPly) {printf("%*sLightSource \"%s\" ", catIndentCount, "", name.c_str());params.Print(catIndentCount);printf("\n");} }這個(gè)函數(shù)在src/core/api.cpp中。 
 完成將LightSource的數(shù)據(jù)寫(xiě)入renderOptions->lights中。
渲染相關(guān)的數(shù)據(jù)都是存在renderOptions中的。
renderOptions的類(lèi)是長(zhǎng)這個(gè)樣子:
struct RenderOptions {// RenderOptions Public MethodsIntegrator *MakeIntegrator() const;Scene *MakeScene();Camera *MakeCamera() const;// RenderOptions Public DataFloat transformStartTime = 0, transformEndTime = 1;std::string FilterName = "box";ParamSet FilterParams;std::string FilmName = "image";ParamSet FilmParams;std::string SamplerName = "halton";ParamSet SamplerParams;std::string AcceleratorName = "bvh";ParamSet AcceleratorParams;std::string IntegratorName = "path";ParamSet IntegratorParams;std::string CameraName = "perspective";ParamSet CameraParams;TransformSet CameraToWorld;std::map<std::string, std::shared_ptr<Medium>> namedMedia;std::vector<std::shared_ptr<Light>> lights;std::vector<std::shared_ptr<Primitive>> primitives;std::map<std::string, std::vector<std::shared_ptr<Primitive>>> instances;std::vector<std::shared_ptr<Primitive>> *currentInstance = nullptr;bool haveScatteringMedia = false; };簡(jiǎn)單說(shuō)來(lái), 
 程序外,描述場(chǎng)景的是.pbrt格式的文件; 
 程序內(nèi),描述場(chǎng)景的是RenderOptions對(duì)象;
另外,注意一下,對(duì)于LightSource,pbrtLightSource()直接調(diào)用了MakeLight()創(chuàng)建了LightSource對(duì)象。 
 所以,renderOptions->lights中保存的是LightSource對(duì)象的指針。
而像RenderOptions中的這些:
std::string FilterName = "box";ParamSet FilterParams;std::string FilmName = "image";ParamSet FilmParams;std::string SamplerName = "halton";ParamSet SamplerParams;std::string AcceleratorName = "bvh";ParamSet AcceleratorParams;std::string IntegratorName = "path";ParamSet IntegratorParams;std::string CameraName = "perspective";ParamSet CameraParams;TransformSet CameraToWorld;對(duì)應(yīng)的“pbrt關(guān)鍵字”函數(shù)中只是將相關(guān)屬性參數(shù)存入RenderOptions的對(duì)應(yīng)成員變量中。
注意到: 
 在RenderOptions類(lèi)定義的前面有幾個(gè)成員方法:
這個(gè)就是用來(lái)創(chuàng)建那些還沒(méi)有在對(duì)應(yīng)“pbrt關(guān)鍵字”函數(shù)中創(chuàng)建對(duì)象的類(lèi)的對(duì)象的。
6,pbrtWorldEnd()
最后處理關(guān)鍵字“WorldEnd”。 
 在pbrtWorldEnd()有非常重要的三行代碼:
1,MakeIntegrator() 
 2,MakeScene() 
 3,integrator->Render(*scene)
即: 
 創(chuàng)建積分器;創(chuàng)建場(chǎng)景;用積分器渲染場(chǎng)景;
重點(diǎn)提一下MakeScene()。
創(chuàng)建Scene對(duì)象。 
 之前小編一直搞不清RenderOption對(duì)象和Scene對(duì)象的關(guān)系: 
 RenderOption側(cè)重?cái)?shù)據(jù),直接和場(chǎng)景描述對(duì)應(yīng); 
 Scene是將RenderOption的數(shù)據(jù)再封裝了一下,同時(shí)加入了和渲染相關(guān)的方法。
貼出Scene的定義代碼:
// Scene Declarations class Scene {public:// Scene Public MethodsScene(std::shared_ptr<Primitive> aggregate,const std::vector<std::shared_ptr<Light>> &lights): lights(lights), aggregate(aggregate) {// Scene Constructor ImplementationworldBound = aggregate->WorldBound();for (const auto &light : lights) {light->Preprocess(*this);if (light->flags & (int)LightFlags::Infinite)infiniteLights.push_back(light);}}const Bounds3f &WorldBound() const { return worldBound; }bool Intersect(const Ray &ray, SurfaceInteraction *isect) const;bool IntersectP(const Ray &ray) const;bool IntersectTr(Ray ray, Sampler &sampler, SurfaceInteraction *isect,Spectrum *transmittance) const;// Scene Public Datastd::vector<std::shared_ptr<Light>> lights;// Store infinite light sources separately for cases where we only want// to loop over them.std::vector<std::shared_ptr<Light>> infiniteLights;private:// Scene Private Datastd::shared_ptr<Primitive> aggregate;Bounds3f worldBound; };場(chǎng)景描述文件解析結(jié)束時(shí)得到兩樣?xùn)|西: 
 一個(gè)積分器對(duì)象; 
 一個(gè)場(chǎng)景對(duì)象;
然后,開(kāi)始用“積分器對(duì)象”渲染“場(chǎng)景對(duì)象”。
總結(jié)
以上是生活随笔為你收集整理的Q116:PBRT-V3场景描述文件.pbrt格式解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: SQL Server修改表结构,不允许保
- 下一篇: matlab中符号函数sgn,matla
