Sahnemize farklı optik özelliklere sahip nesneler eklemek istiyoruz: Bazıları mat olsun, bazıları cilalı metal gibi parlasın, bazıları ise cam gibi ışığı kırsın!
Bunun için nesnelerimizi materyal sınıflarından soyutlayacağız.
material.h Soyut Sınıfı
Bir materyal iki temel soruya cevap vermelidir:
1. Gelen ışın yüzeye çarptığında saçılacak mı (yeni bir ışın üretilecek mi)?
2. Saçılırsa ışığın rengi ne kadar zayıflayacak (attenuation / soğurulma)?
| material.h |
|---|
| #ifndef MATERIAL_H
#define MATERIAL_H
#include "rtweekend.h"
class hit_record;
class material {
public:
virtual ~material() = default;
virtual bool scatter(
const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered
) const {
return false;
}
};
#endif
|
Lambertian (Mat) Materyali
Önceki bölümdeki mat davranışı material sınıfından türetelim:
| material.h (Lambertian Sınıfı) |
|---|
| class lambertian : public material {
public:
lambertian(const color& albedo) : albedo(albedo) {}
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
const override {
auto scatter_direction = rec.normal + random_unit_vector();
// Eğer rastgele vektör tam tersi yöndeyse normal sıfırlanabilir
if (scatter_direction.near_zero())
scatter_direction = rec.normal;
scattered = ray(rec.p, scatter_direction);
attenuation = albedo;
return true;
}
private:
color albedo;
};
|
Pürüzsüz, ayna gibi bir metal için gelen ışık yüzey normaline göre simetrik olarak yansır:

Gelen vektör \(\mathbf{v}\) ve birim normal \(\mathbf{n}\) olduğunda, yansıyan vektör formülü:
\[\mathbf{r} = \mathbf{v} - 2(\mathbf{v} \cdot \mathbf{n})\mathbf{n}\]
vec3.h dosyamıza bu reflect fonksiyonunu ekleyelim:
| vec3.h (Yansıma Fonksiyonu) |
|---|
| inline vec3 reflect(const vec3& v, const vec3& n) {
return v - 2 * dot(v, n) * n;
}
|
Bulanık Yansıma (Fuzzy Reflection / Pürüzlülük)
Gerçek dünyada her metal mükemmel bir ayna değildir. Zımparalanmış veya fırçalanmış metaller ışığı hafifçe bulanık yansıtır.
Bunu modellemek için yansıyan ışının ucuna küçük bir rastgele küre ekler ve bu kürenin yarıçapını fuzz parametresi (\([0.0, 1.0]\)) ile kontrol ederiz:

| material.h (Metal Sınıfı) |
|---|
| class metal : public material {
public:
metal(const color& albedo, double fuzz)
: albedo(albedo), fuzz(fuzz < 1 ? fuzz : 1) {}
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation, ray& scattered)
const override {
vec3 reflected = reflect(r_in.direction(), rec.normal);
reflected = unit_vector(reflected) + (fuzz * random_unit_vector());
scattered = ray(rec.p, reflected);
attenuation = albedo;
return (dot(scattered.direction(), rec.normal) > 0);
}
private:
color albedo;
double fuzz;
};
|
Sahnemize biri altın rengi parlayan, diğeri ise hafif bulanık gümüş metal iki küre yerleştirelim:
| main.cc |
|---|
| auto material_ground = make_shared<lambertian>(color(0.8, 0.8, 0.0));
auto material_center = make_shared<lambertian>(color(0.1, 0.2, 0.5));
auto material_left = make_shared<metal>(color(0.8, 0.8, 0.8), 0.3); // Gümüş (hafif bulanık)
auto material_right = make_shared<metal>(color(0.8, 0.6, 0.2), 1.0); // Altın (mat pürüzlü)
world.add(make_shared<sphere>(point3( 0.0, -100.5, -1.0), 100.0, material_ground));
world.add(make_shared<sphere>(point3( 0.0, 0.0, -1.2), 0.5, material_center));
world.add(make_shared<sphere>(point3(-1.0, 0.0, -1.0), 0.5, material_left));
world.add(make_shared<sphere>(point3( 1.0, 0.0, -1.0), 0.5, material_right));
|
Render sonucumuz:

Kürelerin üzerinde birbirlerinin, zeminin ve gökyüzünün kusursuz yansımalarını görebilirsiniz! Sırada optik fiziğin en büyüleyici konusu var: Cam ve Kırılma (Dielectrics)!