A. RAY CASTING DAN RAY TRACING
Merupakan backward rendering. Membuat citra dari hasil pelacakan sinar dari piksel
/ pengamat ke obyek atau sumber cahaya bukan dari sumber cahaya ke obyek.
Merupakan operasi piksel per piksel
Digunakan untuk implementasi :
• Pencahayaan yang realistik
• Bayangan
• Refleksi
• Pembiasan
• Pencahayaan tidak langsung
1. RAY CASTING
Tahapan ray casting :
Dimulai dari piksel citra di bidang pandang
Minimal membuat / ada satu sinar untuk membuat warna pada piksel
Setiap sinar mempunyai 3 kemungkinan :
Sinar berpotongan dengan obyek
Sinar berpotongan dengan sumber cahaya
Sinar tidak berpotongan dan menuju tak hingga
Sinar berpotongan dengan obyek
Warna hasil interaksi cahaya dengan permukaan
Misalnya model Phong
Ada dua kemungkinan :
Sinar dipantulkan
Sinar dibiaskan
Sinar berpotongan dengan sumber cahaya
Warna sumber cahaya
Sinar tidak berpotongan dan menuju tak hingga
Warna latar belakang
2. RAY TRACING
Melacak sinar yang berpotongan dengan obyek atau sumber cahaya. Sinar yang
berpotongan dengan obyek dicek apakah perpotongan sinar dengan obyek terkena
cahaya?. Sinar / sinar bayangan dihitung dengan melacak titik permukaan ke sumber
cahaya.
Menghasilkan 2 kemungkinan :
Sinar bayangan berpotongan dengan obyek sebelum mencapai sumber
cahaya
Dianggap sebagai bayangan dari arah sumber cahaya tersebut
Sinar bayangan mencapai sumber cahaya
Dianggap sebagai interaksi cahaya dengan permukaan
Sinar bayangan mencapai sumber cahaya :
Mengenai secara langsung
Melalui permukaan cermin
Melalui permukaan transparan
a. RECURSIVE RAY TRACING
color c = trace(point p, vector d, int step)
{
color local, reflected, transmitted;
point q;
normal n;
if (step > max) return(background_color);
q = intersect(p, d, status);
if (status == light_source) return(light_source_color);
if (status == no_intersection) return(background_color);
n = normal(q);
r = reflect(q, n);
t = transmit(q, n);
local = phong(q, n, r);
reflected = trace(q, r, step+1);
transmitted = trace(q, t, step+1);
return(local + reflected + transmitted);
}
b. TITIK PERPOTONGAN
Bila persamaan permukaan obyek :
𝑓 (𝑥,𝑦,𝑧) = 𝑓 (𝐩) = 0
Dan persamaan sinar dari titik 𝒑0 dengan arah 𝐝 :
𝐩 (𝑡) = 𝐩0 + 𝑡𝐝
Maka titik potongnya diberikan oleh persamaan :
𝑓 𝐩0 + 𝑡𝐝 = 0
c. TITIK PERPOTONGAN DENGAN SPHERE
Persamaan sphere dengan titik pusat 𝐎 dengan radius 𝑟
(𝐩 – 𝐎) 2 − 𝑟2 = 0
Substitusikan dengan persamaan sinar
𝐩(𝑡) = 𝐩0 + 𝑡𝐕
Maka persamaan perpotongannya menjadi
𝐩0 + 𝑡𝐕 − 𝐎 2 − 𝑟2 = 0
𝐕 ∙ 𝐕 𝑡2 + 2 𝐩0 − 𝐎 𝐕𝑡 + 𝐩0 − 𝐎 2 − 𝑟2 = 0
d. REFLEKSI / REFRAKSI
e. VARIAN RAY TRACING
Untuk menghindari rekursif yang tidak berhenti maka dibuat batasan :
Membatasi jarak tempuh sinar
Misalkan lingkungan berupa sphere yang besar
Bila sinar lebih jauh dari lingkupan sphere maka dianggap
sebagai warna background (infinity)
Membatasi jumlah tingkat pelacakan sinar
Menentukan batas tingkat pelacakan sinar
Misal sinar yang dilacak hanya pada level 3 atau 3x refleksi /
refraksi
Menggunakan variabel energi
Menentukan nilai awal energi sinar
Mengurangi energi sejalan dengan sinar dikenai refleksi /
refraksi
Bila mencapai 0 maka dianggap sebagai warna background
f. PENCAHAYAAN TIDAK LANGSUNG
Global illumination : metode untuk memperkirakan pencahayaan
tidak langsung dari setiap arah
Gambar kiri : direct lighting
Gambar kanan : indirect lighting
g. ALIASING PADA RAY TRACING
Ray tracing tidak lepas dari aliasing
Karena bekerja pada piksel per piksel maka seperti deferred
rendering yaitu menggunakan MSAA / FXAA / TXAA
Bila sinar tidak berpotongan dengan obyek manapun di suatu
wilayah maka akan dicasting beberapa sinar tambahan ke wilayah
tersebut dan perlakuan sebaliknya bila sinar berpotongan dengan
banyak obyek di wilayah tersebut
Kompleksitas ray tracing sebanding dengan jumlah sinar yang
dilacak / ditrace
Ray tracing dapat diproses secara paralel di GPU
Dengan memanfaatkan shared memory untuk mengatasi
perpotongan sinar dengan yang lain
B. RANGKUMAN
Contoh Penerapan Program Ray Tracing
// lakukan ray tracing dengan obyek bola
Vec3f trace(
const Vec3f &rayorig,
const Vec3f &raydir,
const std::vector<Sphere> &spheres,
const int &depth)
{
float tnear = INFINITY;
const Sphere* sphere = NULL;
// hitung perpotongan cahaya ini dengan bola yang ada dilayar
for (unsigned i = 0; i < spheres.size(); ++i)
{
float t0 = INFINITY, t1 = INFINITY;
if (spheres[i].intersect(rayorig, raydir, t0, t1))
{
if (t0 < 0) t0 = t1;
if (t0 < tnear)
{
tnear = t0;
sphere = &spheres[i];
}
}
}
// jika tidak ada perpotongan maka kembalikan warna hitam atau warna background
if (!sphere) return Vec3f(2);
Vec3f surfaceColor = 0; // warna permukaan obyek yang berpotongan dengan sinar
Vec3f phit = rayorig + raydir * tnear; // titik perpotongan
Vec3f nhit = phit - sphere->center; // normal di titik perpotongan
nhit.normalize(); // menormalisasikan arah normal
// jika normal dan arah pandang tidak
berlawanan satu sama lain
// balikkan arah normal yang berarti arah
sekarang berada didalam bola
// membuat bagian dalam bola bernilai
benar.
float bias = 1e-4; // tambahkan bias pada titik dimana akan di telusuri
bool inside = false;
if (raydir.dot(nhit) > 0)
nhit = -nhit, inside = true;
if ((sphere->transparency > 0 || sphere->reflection > 0) && depth <
MAX_RAY_DEPTH)
{
float facingratio = -raydir.dot(nhit);
// ubah nilai mix untuk memberikan efek
float fresneleffect = mix(pow(1 - facingratio, 3), 1, 0.1);
// hitung arah refleksi sinar (tidak perlu dinormalisasi karena sudah
ternormalisasi di awal)
Vec3f refldir = raydir - nhit * 2 * raydir.dot(nhit);
refldir.normalize();
Vec3f reflection = trace(phit + nhit * bias, refldir, spheres, depth + 1);
Vec3f refraction = 0;
// jika bola nya transparan maka hitung sinar tembusnya
if (sphere->transparency)
{
float ior = 1.1, eta = (inside) ? ior : 1 / ior; // are we inside or
outside the surface?
float cosi = -nhit.dot(raydir);
float k = 1 - eta * eta * (1 - cosi * cosi);
Vec3f refrdir = raydir * eta + nhit * (eta * cosi - sqrt(k));
refrdir.normalize();
refraction = trace(phit - nhit * bias, refrdir, spheres, depth + 1);
}
// hasilnya merupakan campuran dari pantulan dan tembusan cahaya (jika
bolanya transparan)
surfaceColor = (reflection * fresneleffect + refraction
* (1 - fresneleffect) * sphere->transparency) *
sphere->surfaceColor;
}
else
{
// bila obyek diffuse tidak perlu dilakukan ray tracing
for (unsigned i = 0; i < spheres.size(); ++i)
{
if (spheres[i].emissionColor.x > 0)
{
// cahaya
Vec3f transmission = 1;
Vec3f lightDirection = spheres[i].center - phit;
lightDirection.normalize();
for (unsigned j = 0; j < spheres.size(); ++j)
{
if (i != j)
{
float t0, t1;
if (spheres[j].intersect(phit + nhit *
bias, lightDirection, t0, t1))
{
transmission = 0;
break;
}
}
}
surfaceColor += sphere->surfaceColor * transmission
* max(float(0), nhit.dot(lightDirection)) *
spheres[i].emissionColor;
}
}
}
return surfaceColor + sphere->emissionColor;
}
Merupakan backward rendering. Membuat citra dari hasil pelacakan sinar dari piksel
/ pengamat ke obyek atau sumber cahaya bukan dari sumber cahaya ke obyek.
Merupakan operasi piksel per piksel
Digunakan untuk implementasi :
• Pencahayaan yang realistik
• Bayangan
• Refleksi
• Pembiasan
• Pencahayaan tidak langsung
1. RAY CASTING
Tahapan ray casting :
Dimulai dari piksel citra di bidang pandang
Minimal membuat / ada satu sinar untuk membuat warna pada piksel
Setiap sinar mempunyai 3 kemungkinan :
Sinar berpotongan dengan obyek
Sinar berpotongan dengan sumber cahaya
Sinar tidak berpotongan dan menuju tak hingga
Sinar berpotongan dengan obyek
Warna hasil interaksi cahaya dengan permukaan
Misalnya model Phong
Ada dua kemungkinan :
Sinar dipantulkan
Sinar dibiaskan
Sinar berpotongan dengan sumber cahaya
Warna sumber cahaya
Sinar tidak berpotongan dan menuju tak hingga
Warna latar belakang
2. RAY TRACING
Melacak sinar yang berpotongan dengan obyek atau sumber cahaya. Sinar yang
berpotongan dengan obyek dicek apakah perpotongan sinar dengan obyek terkena
cahaya?. Sinar / sinar bayangan dihitung dengan melacak titik permukaan ke sumber
cahaya.
Menghasilkan 2 kemungkinan :
Sinar bayangan berpotongan dengan obyek sebelum mencapai sumber
cahaya
Dianggap sebagai bayangan dari arah sumber cahaya tersebut
Sinar bayangan mencapai sumber cahaya
Dianggap sebagai interaksi cahaya dengan permukaan
Sinar bayangan mencapai sumber cahaya :
Mengenai secara langsung
Melalui permukaan cermin
Melalui permukaan transparan
a. RECURSIVE RAY TRACING
color c = trace(point p, vector d, int step)
{
color local, reflected, transmitted;
point q;
normal n;
if (step > max) return(background_color);
q = intersect(p, d, status);
if (status == light_source) return(light_source_color);
if (status == no_intersection) return(background_color);
n = normal(q);
r = reflect(q, n);
t = transmit(q, n);
local = phong(q, n, r);
reflected = trace(q, r, step+1);
transmitted = trace(q, t, step+1);
return(local + reflected + transmitted);
}
b. TITIK PERPOTONGAN
Bila persamaan permukaan obyek :
𝑓 (𝑥,𝑦,𝑧) = 𝑓 (𝐩) = 0
Dan persamaan sinar dari titik 𝒑0 dengan arah 𝐝 :
𝐩 (𝑡) = 𝐩0 + 𝑡𝐝
Maka titik potongnya diberikan oleh persamaan :
𝑓 𝐩0 + 𝑡𝐝 = 0
c. TITIK PERPOTONGAN DENGAN SPHERE
Persamaan sphere dengan titik pusat 𝐎 dengan radius 𝑟
(𝐩 – 𝐎) 2 − 𝑟2 = 0
Substitusikan dengan persamaan sinar
𝐩(𝑡) = 𝐩0 + 𝑡𝐕
Maka persamaan perpotongannya menjadi
𝐩0 + 𝑡𝐕 − 𝐎 2 − 𝑟2 = 0
𝐕 ∙ 𝐕 𝑡2 + 2 𝐩0 − 𝐎 𝐕𝑡 + 𝐩0 − 𝐎 2 − 𝑟2 = 0
d. REFLEKSI / REFRAKSI
e. VARIAN RAY TRACING
Untuk menghindari rekursif yang tidak berhenti maka dibuat batasan :
Membatasi jarak tempuh sinar
Misalkan lingkungan berupa sphere yang besar
Bila sinar lebih jauh dari lingkupan sphere maka dianggap
sebagai warna background (infinity)
Membatasi jumlah tingkat pelacakan sinar
Menentukan batas tingkat pelacakan sinar
Misal sinar yang dilacak hanya pada level 3 atau 3x refleksi /
refraksi
Menggunakan variabel energi
Menentukan nilai awal energi sinar
Mengurangi energi sejalan dengan sinar dikenai refleksi /
refraksi
Bila mencapai 0 maka dianggap sebagai warna background
f. PENCAHAYAAN TIDAK LANGSUNG
Global illumination : metode untuk memperkirakan pencahayaan
tidak langsung dari setiap arah
Gambar kiri : direct lighting
Gambar kanan : indirect lighting
g. ALIASING PADA RAY TRACING
Ray tracing tidak lepas dari aliasing
Karena bekerja pada piksel per piksel maka seperti deferred
rendering yaitu menggunakan MSAA / FXAA / TXAA
Bila sinar tidak berpotongan dengan obyek manapun di suatu
wilayah maka akan dicasting beberapa sinar tambahan ke wilayah
tersebut dan perlakuan sebaliknya bila sinar berpotongan dengan
banyak obyek di wilayah tersebut
Kompleksitas ray tracing sebanding dengan jumlah sinar yang
dilacak / ditrace
Ray tracing dapat diproses secara paralel di GPU
Dengan memanfaatkan shared memory untuk mengatasi
perpotongan sinar dengan yang lain
B. RANGKUMAN
Contoh Penerapan Program Ray Tracing
// lakukan ray tracing dengan obyek bola
Vec3f trace(
const Vec3f &rayorig,
const Vec3f &raydir,
const std::vector<Sphere> &spheres,
const int &depth)
{
float tnear = INFINITY;
const Sphere* sphere = NULL;
// hitung perpotongan cahaya ini dengan bola yang ada dilayar
for (unsigned i = 0; i < spheres.size(); ++i)
{
float t0 = INFINITY, t1 = INFINITY;
if (spheres[i].intersect(rayorig, raydir, t0, t1))
{
if (t0 < 0) t0 = t1;
if (t0 < tnear)
{
tnear = t0;
sphere = &spheres[i];
}
}
}
// jika tidak ada perpotongan maka kembalikan warna hitam atau warna background
if (!sphere) return Vec3f(2);
Vec3f surfaceColor = 0; // warna permukaan obyek yang berpotongan dengan sinar
Vec3f phit = rayorig + raydir * tnear; // titik perpotongan
Vec3f nhit = phit - sphere->center; // normal di titik perpotongan
nhit.normalize(); // menormalisasikan arah normal
// jika normal dan arah pandang tidak
berlawanan satu sama lain
// balikkan arah normal yang berarti arah
sekarang berada didalam bola
// membuat bagian dalam bola bernilai
benar.
float bias = 1e-4; // tambahkan bias pada titik dimana akan di telusuri
bool inside = false;
if (raydir.dot(nhit) > 0)
nhit = -nhit, inside = true;
if ((sphere->transparency > 0 || sphere->reflection > 0) && depth <
MAX_RAY_DEPTH)
{
float facingratio = -raydir.dot(nhit);
// ubah nilai mix untuk memberikan efek
float fresneleffect = mix(pow(1 - facingratio, 3), 1, 0.1);
// hitung arah refleksi sinar (tidak perlu dinormalisasi karena sudah
ternormalisasi di awal)
Vec3f refldir = raydir - nhit * 2 * raydir.dot(nhit);
refldir.normalize();
Vec3f reflection = trace(phit + nhit * bias, refldir, spheres, depth + 1);
Vec3f refraction = 0;
// jika bola nya transparan maka hitung sinar tembusnya
if (sphere->transparency)
{
float ior = 1.1, eta = (inside) ? ior : 1 / ior; // are we inside or
outside the surface?
float cosi = -nhit.dot(raydir);
float k = 1 - eta * eta * (1 - cosi * cosi);
Vec3f refrdir = raydir * eta + nhit * (eta * cosi - sqrt(k));
refrdir.normalize();
refraction = trace(phit - nhit * bias, refrdir, spheres, depth + 1);
}
// hasilnya merupakan campuran dari pantulan dan tembusan cahaya (jika
bolanya transparan)
surfaceColor = (reflection * fresneleffect + refraction
* (1 - fresneleffect) * sphere->transparency) *
sphere->surfaceColor;
}
else
{
// bila obyek diffuse tidak perlu dilakukan ray tracing
for (unsigned i = 0; i < spheres.size(); ++i)
{
if (spheres[i].emissionColor.x > 0)
{
// cahaya
Vec3f transmission = 1;
Vec3f lightDirection = spheres[i].center - phit;
lightDirection.normalize();
for (unsigned j = 0; j < spheres.size(); ++j)
{
if (i != j)
{
float t0, t1;
if (spheres[j].intersect(phit + nhit *
bias, lightDirection, t0, t1))
{
transmission = 0;
break;
}
}
}
surfaceColor += sphere->surfaceColor * transmission
* max(float(0), nhit.dot(lightDirection)) *
spheres[i].emissionColor;
}
}
}
return surfaceColor + sphere->emissionColor;
}