Ana içeriğe geç

Bölüm 6: Kamera Sınıfı ve Kod Düzeni

Kodlarımız büyüdükçe main.cc dosyamızın içine hem görüntü çözünürlüğü hesapları, hem ışın üretimi, hem de sahne render döngüsü sıkışmaya başladı.

İyi bir yazılım mimarisinde iki temel sorumluluk birbirinden ayrılmalıdır: 1. Sahneyi Kurmak (main.cc): Nesneleri, materyalleri ve ışıkları tanımlamak. 2. Sahneyi Görüntülemek (camera.h): Işınları göndermek, pikselleri örneklemek ve görseli üretmek.


camera.h Sınıfının Tasarımı

Kamera sınıfımız iki temel kamuya açık (public) metoda ve üyelere sahip olacaktır: - double aspect_ratio: En/boy oranı (örneğin 16:9). - int image_width: Piksel genişliği (örneğin 400). - void render(const hittable& world): Sahneyi render edip PPM çıktısını döken ana fonksiyon.

Aşağıdaki temiz yapıyı camera.h olarak kaydedelim:

camera.h
#ifndef CAMERA_H
#define CAMERA_H

#include "rtweekend.h"
#include "hittable.h"
#include "color.h"

#include <iostream>

class camera {
  public:
    double aspect_ratio = 1.0;  // Görüntü en/boy oranı
    int    image_width  = 100;  // Çıktı genişliği (piksel)

    void render(const hittable& world) {
        initialize();

        std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";

        for (int j = 0; j < image_height; j++) {
            std::clog << "\rKalan satır: " << (image_height - j) << ' ' << std::flush;
            for (int i = 0; i < image_width; i++) {
                auto pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v);
                auto ray_direction = pixel_center - center;
                ray r(center, ray_direction);

                color pixel_color = ray_color(r, world);
                write_color(std::cout, pixel_color);
            }
        }

        std::clog << "\rTamamlandı!                 \n";
    }

  private:
    int    image_height;   // Hesaplanan görsel yüksekliği
    point3 center;         // Kamera merkez konumu
    point3 pixel00_loc;    // (0,0) pikselinin 3B uzaydaki konumu
    vec3   pixel_delta_u;  // Sağdaki komşu piksele geçiş vektörü
    vec3   pixel_delta_v;  // Aşağıdaki komşu piksele geçiş vektörü

    void initialize() {
        image_height = int(image_width / aspect_ratio);
        image_height = (image_height < 1) ? 1 : image_height;

        center = point3(0, 0, 0);

        // Viewport Boyutları
        auto focal_length = 1.0;
        auto viewport_height = 2.0;
        auto viewport_width = viewport_height * (double(image_width)/image_height);

        // Viewport kenar vektörleri
        auto viewport_u = vec3(viewport_width, 0, 0);
        auto viewport_v = vec3(0, -viewport_height, 0);

        // Pikseller arası mesafeler
        pixel_delta_u = viewport_u / image_width;
        pixel_delta_v = viewport_v / image_height;

        // Sol üst pikselin 3B konumu
        auto viewport_upper_left = center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2;
        pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
    }

    color ray_color(const ray& r, const hittable& world) const {
        hit_record rec;

        if (world.hit(r, 0, infinity, rec)) {
            return 0.5 * (rec.normal + color(1,1,1));
        }

        vec3 unit_direction = unit_vector(r.direction());
        auto a = 0.5*(unit_direction.y() + 1.0);
        return (1.0-a)*color(1.0, 1.0, 1.0) + a*color(0.5, 0.7, 1.0);
    }
};

#endif

Sadeleşen main.cc

Bakın ana programımız ne kadar berrak ve minimalist bir hale geldi:

main.cc
#include "rtweekend.h"

#include "camera.h"
#include "hittable.h"
#include "hittable_list.h"
#include "sphere.h"

int main() {
    // Sahne Nesneleri
    hittable_list world;
    world.add(make_shared<sphere>(point3(0,0,-1), 0.5));
    world.add(make_shared<sphere>(point3(0,-100.5,-1), 100));

    // Kamera Ayarları
    camera cam;
    cam.aspect_ratio = 16.0 / 9.0;
    cam.image_width  = 400;

    // Render!
    cam.render(world);
}

Bu modüler yapı sayesinde ileride kameramıza alan derinliği, serbest hareket etme yeteneği veya örtüşme önleme eklerken main.cc kodumuza dokunmamız bile gerekmeyecek!