Sunday, November 6, 2011

Renderman RSL-2.2

ХУВЬСАГЧ
             RSL болон бусад програмчлалын хэлэнд хувьсагчуудыг хэрхэн үүсгэх болон зарлах  үйлдэл нь хамгийн чухал анхаарах зүйл байдаг. Хувьсагч нь тодорхой нэртэй өгөгдлийг агуулагч юм. Хувьсагчийг RSL хэлэнд дараахи зарчмаар хэрэглэнэ.

    [class] type variableName; 
Uniform эсвэл varying гэх хоёр төрлийн класс зааж өгч болох бөгөөд заагаагүй тохиолдолд uniform утгыг автоматаар авна. Хувьсагчийн нэр нь дараахи дүрмийг л зөрчөөгүй бол ямар ч байж болно.
  ■ RSL-д тодорхойлогдсон түлхүүр үгтэй давхцахгүй байх
  ■  *, - , +, /. гэсэн тусгай тэмдэгтүүдийг агуулаагүй байх
  ■ Хувьсагчийн нэрэнд хоосон зай байх ёсгүй
  ■ Хувьсагчийн нэр нь ямар нэг тоогоор эхэлж болохгүй

Хувьсагчийг зарласан тохиолдолд түүнд утга оноох бололцоотой. Хувьсагч нь шинээр утга оноох эсвэл функцын гаралтын утгыг хувьсагчид оноох хүртэл өөрийн утгаа хадгалсаар байна. Хувьсагчид утга оноохдоо тэнцүүгийн ' = ' тэмдэг ашиглана.  
  ХувьсагчийнНэр = 25;Мөн хувьсагчийг зарлах болон утга оноох үйлдлийг нэг мөрөнд багтаан гүйцэтгэх боломжтой.
  varying float myvar = 25;
Хувьсагчид утга оноосны дараа шэйдр дотроо ямар ч цэгд хувьсагчийн утгыг хэрэглэж болно. Жишээ нь:
uniform float varA = 2;                      // 
varA хувьсагчийг зарлан утга оноож байна.
uniform float varB = 5;                      //  varB хувьсагчийг зарлан утга оноож байна.
uniform float varC = varA * varB;     //  varC хувьсагчийг зарлан 10 гэсэн утга оноож байна.
varB = varC - varA;                         //  varB-ийн хуучин утгыг даран 8 гэсэн шинэ утга оноож байна.

Data Classes

      RSL нь ижил (uniform) болон хувьсах (varying) гэсэн хоёр төрлийн өгөгдлийн классыг дэмждэг бөгөөд санах ойг ашиглах арга нь хоорондоо ялгаатай.  Энэ хоёр класс нь таны шэйдрийн хяналт удирдлага хэр үр дүнтэй болохыг илэрхийлнэ. Шэйдр зохион бүтээгчийн хувиар тэдгээрийн ажиллагааны сул болон давуутай талуудыг сайн мэдэж байх хэрэгтэй.
  Энэ хоёр классын ялгааг сайн ойлгохын тулд REYES алгоритмын дизайныг эргэн харах хэрэгтэй. Шэйдр нь Single Instruction Multiple Data (SIMD) машины зарчмаар ажилладаг. Функц нь бүх микро полигонууд руу нэг  удаа нэвтэрч үүргээ гүйцэтгэгдэх бөгөөд  микро полигон бүр дээр  дуудагдан ажиллах шаардлагагүй. Энэ схем нь тун оновчтой шийдэл бөгөөд зарим үйлдлүүдэд маш том боломжийг нээж өгдөг. Жишээ нь гэрэлтүүлэлтийн гогцоо юм. Дүрсэлж байгаа сараалжин хавтгай (grid) болгон дээр гэрэлтүүлэлтийн гогцоонд хэрэглэгдэх хувьсагчийн утга өөрчлөгдөхгүй адил байх учир ижил класс тохиромжтой.
      Өнгө (diffusion), ойсон гялаан гэрэл (specularity), нэмэлт өнгө (ambient) зэргийг тодорхойлдог гол гол параметрууд нь ижил классын хувьсагчаар зарлагддаг. Сараалжин хавтгай дотор утгаа өөрчилдөг бол хувьсах (varying) класст хамаарна. Энэ класс нь текстур эсвэл биетийн примитивийн утгууд зэрэг мэдээллийг хадгалахад өргөн хэрэглэгддэг. Хэрвээ хэрэглэгч нь классаа тодорхойлж өгөөгүй байвал ихэнхи хөрвүүлэгчид шэйдрийн параметруудыг ижил класс харин шэйдр дотор зарлагдсан хувьсагчдыг хувьсах классынх гэж үздэг. Эдгээр классын тухай сүүлд нэмж тайлбарлана.
                                    
Data Types

       RSL  нь өгөгдлийг хадгалах цөөн тооны төрлүүдтэй.Ялангуяа С хэлийг ашиглаж байсан хүмүүст анхааруулахад RSL-д зарим төрлүүд огт байдаггүй бөгөөд харин RSL нь өөр бусад хэлэнд ашиглагдаад байдаггүй  өгөгдлийн шинэ төрлийг.  тодорхойлсон байдаг. Учир нь RSL бол зөвхөн зурж дүрслэхэд зориулагдсан учраас өөрт хэрэгтэйг нь авч зайлшгүй ашиглагдах шинэ төрлийг нэмж оруулсан. 

Float
  Бутархай тоо өгөгдлийн төрөл нь RSL-д байх бүх тоон утгыг төлөөлнө. Бусад хэлэнд тоон утгыг төлөөлөх олон төрөл байдаг. Бүхэл тоог төлөөлөх integer болон өгөгдлийн урсгалыг хянах, унтраалга зэрэгт хэрэглэдэг булын (boolean) төрөл  RSL-д байдаггүй нь түүнийг хязгаарлагдмал мэт харагдуулавч эцсийн дүндээ маш хялбархан болгодог. Хэрэв та өөрийн шэйдрийн ажиллагааг маш хурдан болгох эсвэл бүхэл ба булын төрлийг ашиглахыг хүсвэл хувьсагч мөн параметруудыг uniform класс гэж зарлах хэрэгтэй.

String
    Тэмдэгт мөр хувьсагч нь текст хэлбэртэй өгөгдлийг хадгалахад зориулагдсан. Хамгийн өргөн хэрэглээ нь дискнээс зургийн байршил унших мөн хөрвүүлэгчид хэрэглэгчийн атрибут дамжуулах, мессэж дамжуулах зэрэг үйлдлүүд юм. RSL хэл нь энэ төрөлтэй ажиллахад тийм ч сайн зохицоогүй байдаг. Ялангуяа тэмдэгт мөрүүдийг харьцуулах үйлдлийг анхаарах хэрэгтэй.
    Тэмдэгт мөр нь uniform төрөл боловч (тухайн цэг /shading point/ болгон дээр дуудагдахгүй зөвхөн patch-д нэг л дуудагдана) яагаад сайн зохицохгүй байх шалтгаан нь patch болгонд дуудагдан ажиллах шаардлагатай болдог. Зөвхөн ганц модел гэхэд хэдэн зуу , хэдэн мянган patch-аас бүрддэг.  Тэмдэгт мөр нь хувьсагчид оноогоогүй бол заавал " " тэмдэгтийн хооронд байрлах шаардлагатай
//  Тэмдэгт мөр онооход зайлшгүй хашилтанд хийх шаардлагатай

string imageMap = "/home/maps/myimage.tx";
//  Тэмдэгт мөр хувьсагчаар дамжуулж утга оноож байна

color surfaceColor = texture(imageMap,s,t);
//  Утгыг шууд оноож байна

color surfaceColor = texture("/home/maps/myimage.tx",s,t);

Points, Vectors, and Normals
  Цэг , вектор , нормал нь хоорондоо тун төстэй илэрхийлэгддэг боловч маш том ялгаатай ойлголтууд. Цэг нь өгөгдсөн координатын системээр тодорхойлогдох 3 хэмжээст цэгийн байрлал юм. Түүнд ямар нэгэн чиглэл гэж байхгүй. Вектор бол 3 хэмжээст орон зайд чиглэлийг заах бөгөөд байрлал гэж байхгүй. Вектор нь чиглэл болон цацраг туяаг тодорхойлоход хэрэглэгддэг. Нормал нь вектортой тун төстэй боловч гадаргын тодорхой нэг хэсэг аль чиглэлд зааж байгааг тодорхойлох үүрэгтэй. Нормал нь байрлал ба чиглэлийг агуулдаг. Иймээс нормалыг вектор болон цэг рүү хувиргахад тун хялбар. Ийм хувиргалт хийхдээ тун хянуур хандах хэрэгтэй. Учир нь үржүүлэх, өсгөх гэх мэт үйлдлүүд нь нормал болон вектороос шалтгаалан өөр өөр үр дүн үзүүлдэг. Энэ гурван төрөл нь нэг хэмжээст гурван элементтэй массиваар тодорхойлогдоно. Энэ массивийн дурын элементүүд рүү тусгай функцын туслалцаатай хандаж болно. Доорхи жишээнд хэрхэн зарлахыг харууллаа.
//  Y тэнхлэгийн дагуу дээш зааж буй нормал

normal NN = (0,1,0);
//  Координатын эх дээр байрлах цэг

uniform point P = (0,0,0);
// Хоёр дахь цэгээс эхнийх рүү заасан вектор
vector newV = vector ((1,1,0) - (0.5,0.1,0)); 


Color
   Өнгө нь цэг , вектор , нормалтай адил гурван утгатай массив хэлбэртэй зарлагддаг. Өнгө нь өнгөний координатын систем ч гэж нэрлэгддэг хоорондоо ялгаатай өнгөний орон зайд илэрхийлэгдэнэ. Ерөнхийдөө RGB орон зайд  анхлан тодорхойлогддог. Өнгийг HSV рүү хувиргавал түүн дээр гүйцэтгэх зарим нэг операцууд хялбар болдог. Хэрвээ өнгөний орон зайг  зааж  өгөхөөр бол хашилтанд хийх хэрэгтэй. Учир нь өнгөний орон зай нь тэмдэгт мөр төрлийнх юм. Хэрвээ ганц бутархай тоон хувьсагч өнгөнд оноовол гурван элемент оноосон утгатай адил утгатай болно. Доорхи жишээг харцгаая.
//  Дундаж саарал
color color1 = color (0.5,0.5,0.5);
// hsv орон зайн цэвэр улаан
color color2 = color "hsv" (0,1,1);
//  цагаан өнгө, бүх гурван элемент 1 гэсэн утгатай болно.

color color3 = 1;
Color Space                                              Тайлбар
"rgb"                                                          red, green, blue (эхний утга)
"hsv"                                                          hue, saturation, value
"hsl"                                                           hue, saturation, lightness
"xyz",                                                         "XYZ" CIE coordinates
"YIQ"                                                         NTSC coordinates


Matrix 
 RSL нь шэйдр дотор агуулагдах координатын систем болон тэдгээрийн шилжилт хөдөлгөөнийг хянаж удирдах зориулалттай матриц төрлийн өгөгдлийг тодорхойлж өгсөн байдаг. Матриц нь 16 бутархай элементээс бүрдэх массив ба 4 3 4 гэсэн homogeneous шилжилтийн координаттай хамааралтай. Матриц дээр хийгдэх үйлдлүүд нь тийм төвөгтэй биш ч бага зэргийн математикийн мэдлэг , дадлага шаардана. Нomogeneous координатыг ашигласнаар эдгээр үйлдлүүд гайхалтай хялбархан болно. Хамгийн чухал зайлшгүй мэдэх ёстой үйлдлүүдийг дараа нь тусд нь авч үзнэ. Матриц хувьсагчид утга оноох тусгай дүрэм байдаг. Эдгээрийг жишээн дээр харцгаая.
// Тухайн координатын системд байрлах матриц
matrix m1 = (0,1,2,3, 4,5,6,7, 8,9,10,11, 12,13,14,15);
// Шэйдрийн орон зайд байрлах тодорхойлогч матриц

matrix ident = "shader" 1;
// Ерөнхий (world) орон зайд байрлах 0 матриц 

matrix zero = "world" 0; 
  Эхний жишээн дээр тухайн үед идэвхжсэн координатын системд харьяалагдах  тодорхой зорилгогүй матрицыг зарлаж байна. Дараагийн жишээнд диагоналын дагуу байрлах утгууд нь нэг байх тодорхойлогч матриц, гуравдахь жишээнд бүх элементүүд нь тэг байх матрицыг зарлаж утга оноосон байна.
Arrays
     RenderMan Shading Language нь үндсэн өгөгдлийн төрлүүдээс бүрдэх нэг хэмжээст массивыг дэмждэг. Нэг хэмжээст массив гэдэг нь массив дотор массив байхыг зөвшөөрөхгүй гэсэн үг. Их хэмжээтэй ижил төрлийн  өгөгдөл дээр нэгэн төрлийн үйлдлүүдийг гүйцэтгэх тохиолдолд массивийг өргөн ашигладаг. RSL-д тодорхойлогдсон массивын элементүүд бүгд ижил төрөл байх ёстой гэдэг нь тун чухал концепт юм. Бутархай төрлийн массив гэж тодорхойлсон л бол массивын бүх элементүүд бутархай байх ёстой.  Массив нь С хэлтэй адил зарлагдана. Массивыг зарлах бүдүүвч болон хэд хэдэн жишээг үзүүлье. 
  class type variablename[arraysize] = {element1,element2,..., elementN} 
  // 2 элементтэй тэмдэгт мөр төрлийн массив
  string textureMaps[2] = {"./texture1.tx","./texture2.tx"};
   // Алдаатай!  2 хэмжээст массив зарлаж болохгүй
   float myArrays[2][2] = {{0,1},{3,4}};

      Локал хувьсагчтай массивын урт нь тодорхой , урьдчилан зарлагдсан байх шаардлагатай. Шэйдрийг хөрвүүлэхийн өмнө compiler нь массив нь хэдэн элементтэй болохыг мэдэж байх ёстой. Массивын элемэнт рүү хандахдаа С-тэй адилхан зарчим баримтална. Дөрвөлжин хаалтан доторхи утга нь бутархай бол ойролцоох бүхэл тооруу шилжиж массивын элемэнтийн индекс болж ашиглагдана. Индекс нь нэгээс биш 0-ээс эхэлж тоологдоно.  С хэлтэй адил массив нь нийлмэл бүтэцтэй учир математикийн =, !=, эсвэл >= гэх мэт унари үйлдлүүдийг ашиглан матрицуудыг харьцуулах болон нэг массивыг нөгөөд оноох зэрэг үйлдлүүд хориотой. Гэвч  массивыг харьцуулах , хуулах , эрэмбэлэх зориулалттай RSL функц зохион ашиглаж болно.
  float myvalues[3] = {24,45,76};            // Массивт утга оноож байна
  float value1 = myvalues[0];                    //value 1 = 24
  constant float index = 2;
  float value2 = myvalues[index];             // value2 = 76
  float anotherArray = myvalues;             // Алдаа - Массивыг өөр массивт оноож болохгүй

No comments:

Post a Comment