Wednesday, December 11, 2013

Deferred Rendering

Хуучин блог дээрээ энэ талаар оруулж байсан юм байна. Давтаад яахав энд хуулаад тавьчихъя. Учир нь deffered rendering аргыг sponza цувралын нэг хэсэг болгон хэрэгжүүлж үзэх гэж байгаамаа.


Deferred render нь CryEngine, Frostbyte аас өгсүүлээд за тэгээд ямар л орчин үеийн тоглоомын хөдөлгүүрүүд байна тэд нарт бүгд дээр нь хэрэглэгдэж байгаа рэндэрлэлтийн арга юм. 


Deferred shading буюу deferred рэндэрлэлтийн гол үйл ажиллагаа нь байрлал нормал гэх мэтийн геометрийн тооцооллыг гэрлийн тооцооллоос салгаж тусад нь боловсруулахад оршино. Тэгэхээр энэ тооцооллыг үндсэн хоёр ширхэг pass-уудаар дамжуулан хийлгэнэ. Pass гэж юу вэ гэж гайхаж байж болох юм тэгвэл энэ нь болохоор график pipeline ажиллаад framebuffer-лүү өгөгдлүүд бичигдэж дуусах хүртлэх рэндэрлэх үйл ажиллагааг хэлдэг. 

Эхний pass-аар бид forward render-т хэрэглэгддэгчлэн гэрлийн тооцооллыг fragment shader дээр тооцооллуулахын оронд энгийн vertex shader програмыг л ажиллуулна тэгээд G-Buffer гэж нэрлэгдэх buffer-лүү өгөгдлүүдээ хадгална. G-Buffer гэдэг нь ердөө л framebuffer дотор bind хийсэн текстуруудийн цуглуулгуудыг хэлдэг өөрөөр хэлбэл ялгаатай рэндэрлэгдэх мэдээллүүдийн төлөвийг агуулах 2D текстурууд байна гэсэн үг англиар үүнийг Multiple Render Target буюу товчоор MRT гэдэг. Тэхээр саяны эхний pass-ийн үйл ажиллагаар, pipeline ий ажиллах дарааллал ёсоор vertex-үүдийг primite-үүд болгож бүлэглээд тэдгээрийн хооронд дөхөлт хийгдэн rasterize хийгдсэн fragment утгууд fragment shader-аар дамжин G-Buffer т хадгалагдах юм. Энэ үе шатыг Geometry Pass гэж нэрлэдэг бөгөөд scene дотор culling хийгдээд рэндэрлэгдэхэд бэлэн болж орж ирсэн бүх объектүүд энэ pass дотор боловсруулагдана. Geometry pass ажиллаад G-Buffer дотор өгөгдлөө бичиж дуусах үед гэрлийн тооцооллыг хийх шаардлагатай пикселүүд л G-Buffer доторхи өөр өөрсдийн текстурууд дотроо хадгалагдан үлдэнэ. 

Хоёрдугаар pass буюу гэрлийн тооцоолол хийх үе шатыг англиар Lighting Pass гэдэг. Энэ үе шатанд G-Buffer доторхи geometry pass-аар тооцоолж бий болгосон текстур доторхи пикселүүдийн мэдээллүүдийг ашиглаж гэрлийн тооцооллыг хийнэ. 

G-Buffer-ийн layout буюу түүний бүтэц
  • Texture 1 : view-space дахь байрлал болон depth мэдээлэлтэй тексел
  • Texture 2 : view-space дахь normal мэдээлэл бүхий тексел
  • Texture 3 : Albedo буюу зөвхөн текстур буулгалтаар үүссэн diffuse тексел
  • Texture 4 : Гадаргууны оптик шинж чанартай хамааралтай өнгө болон гэрлийн хүчний мэдээллүүдийг агуулах пикселүүд
  • Texture 5 : self-illumination буюу light-map-аар үүсгэгдсэн өнгөний мэдээллүүд


Уламжлалт хэрэглэгддэг аргыг Forward Render гэдэг. Forward болон Deffered хоёр аргыг хооронд нь харьцуулж үзье.

Forward render - single pass
  • scene дотор байгаа бүх объектүүдээр давтаад
    • объектрүү тусаж байгаа бүх гэрлийг хайж олно
    • тэр олдсон гэрэл бүрийг material-тай хамт нэг shader програм ашиглаж рэндэрлэнэ
  • shader програмуудын комбинац нь ихсэж ирнэ
    • material бүрт зориулагдсан shader болон гэрлийн тохиргоонуудыг комбинац хийнэ гэсэн үг
  • бүх сүүдэр буулгалтуудын утгуудыг host програмын санах ой дотор хадгалах хэрэгтэй болно
  • хий дэмий зүйл дээр shader програм ажиллуулж нөөц үрэгдэх магадлалтай
    • харагдахгүй гадаргуу дээр shader нь ажиллана / давхарлаж зурна
    • гэрэл тусгахгүй байгаа гурвалжингуудад бас нөлөөлдөг
Forward Render - multi-pass буюу олон дахин рэндэрлэх
  • Гэрэл бүрээр нь давтана
    • тэгээд мөн объект бүрээр давтана
    • гэрлийн тооцооллыг хийж frame buffer лүү хадгална
  • material бүрт мөн гэрлийн төрөл бүрт зориулагдсан shader програм бичих хэрэгтэй байдаг.
  • дэмий ажиллах shader тооцоолол
    • харагдахгүй гадаргуу дээр shader нь ажиллана / давхарлаж зурна
    • гэрэл тусгахгүй байгаа гурвалжингуудад бас нөлөөлнө
    • Маш олон давтагдсан зүйлийг хийнэ
      • Бүтэн vertex shader, texture filter гэх мэт

Deffered Rendering
  • Объект бүрээр нь давтаад
    • объектийн гадаргууны мэдээллүүдийг тооцооллоод G-Buffer дотор рэндэрлэнэ
  • Гэрэл бүрээр давтана
    • G-Buffer ийг ашиглаж гэрлийн тооцооллийг хийнэ
    • үр дүнг frame buffer-т хадгална
  • Энгийн shader програмууд ашиглагдана
  • Гэрлийн тооцоололд орж байгаа пикселүүд нэмэгдээд ирэх үед ажиллахдаа маш сайн өөрөөр хэлбэл scale сайн хийгдэнэ гэсэн үг
  • Гэхдээ transparent объектийг рэндэрлэж чадахгүй сул талтай. Үүнийг transparent объект рэндэрлэх шаардлага гарах үед нь forward render хийж ажиллуулдаг нэг pass нэмэх байдлаар шийдэж болно.
  • motion blur, depth of field(tilt shilt), SSAO, FXAA .... сүүлийн үеийн post processing эффектүүд тооцооллуудыг хийхэд эвтэйхэн болгож өгдөг.
Тэгэхээр deferred render нь scene-ийн complexity ихсээд ирэх үед өөрөөр хэлбэл олон объектүүдийг олон гэрлийн хамтаар рэндэрлэх үед GPU тооцоолол сул дэмий үрж ашиглахгүй байх давуу талтай байхнээ.
Үндсэн ажиллагаа нь геометрийн тооцоолол болон гэрлийн тооцоолол хоёрыг салгаж хийхэд оршдог. G-Buffer гэдгийг баахан 2D текстуруудын цуглуулга гэж ойлгож болно. Текстур бүрт ялгаатай рэндэрлэлтийн утгууд хадгалагдана. Үүнийг OpenGL-д MRT буюу Multiple Render Target гэж нэрийддэг. 


Давуу болон сул талууд

Deferred rendering ашиглахын давуу тал

  • scene-д их олон зүйл рэндэрлэх шаардлагатай болоод ирэх үед давуу тал нь ажиглагдана. Жишээ нь forward рэндэрлэлт ашиглах үед гацаж эхэлж байхад deferred рэндэрлэлтэд яг тэр scene тун тогтвортой ажиллана гэсэн үг.
  • shader програмаар үүсэх үр дүн нь зөвхөн дэлгэцэнд харуулах шаардлагатай пикселүүдийг л тооцоолж үүсгэдэг. Өөрөөр хэлбэл юмны цаана байгаа объектийн гадаргууг тооцооллож нөөц үрэхгүй гэсэн үг. 
  • Их цөөхөн shader програм ашиглагдана
  • post-processing буюу рэндэрлэсэн графикийг илүү бодитой үнэмшилтэй болгох эффект хийхэд шаардлагатай алгоритмуудыг хэрэгжүүлэхэд нэн амар болгодог. Эффект оруулна гэдэг нь рэндэрлэгдчихсэн байгаа frame буюу нэг кадрийг нэмэлтээр тооцоолон өөр нэгэн кадр гаргаж авахыг хэлдэг. realtime графикт голчлон ашиглагддаг эффектүүдээс дурдвал : depth of the field (tilt shilt), motion blur, anti-aliasing, ambient occlusion, fake dusty lens flare гэх мэт
  • Маш олон гэрлийн тооцооллыг хийхэд хоромын зуур хугацаа шаардлагатай өөрөөр хэлбэл энэ тохиолдолд их хурдан ажиллах давуу талтай. 
Deferred рэндэрлэлтийн сул талууд
  • Маш их санах ой шаардлагатай
  • Bandwidth. Санах ойгоос график карт хооронд өгөгдөл эх хавтангийн north болон south bridge-үүдийн хооронд bus гэж нэрлэгдэх шугамаар дамжин хуулагддаг. bus-ийн өгөгдөл нэвтрүүлэх зурвасынх нь өргөнийг bandwidth гэдэг. deferred рэндэрлэлтэнд их хэмжээний өгөгдлийг энэ зурвасаар байнга нэвтрүүлж байх ёстой байдаг өөрөөр хэлбэл гадаргуун material шинжийг агуулах өгөгдлүүдийг график карт дээрхи G-Buffer хадгалж эхлэхэд маш их санах ойг зарцуулагддаг. 
  • Transparency. буюу нэвтрэлттэй харагддаг шинж бүхий объектийг G-Buffer ашиглаад рэндэрлэх боломжгүй яагаад гэвэл G-Buffer ийн пиксел бүрт зөвхөн ганц утга л хадгалж болно.
  • Antialiasing.