das ist mein raytracer, implementiere bitte folgende funktion: Das "Material" der Objektoberfläche mit ambienten, diffusem und reflektiven Farbanteil.

hier mein code: raytracer.cc #include "math.h" #include "geometry.h" #include "raytracer.h" #include <iostream> #include <cstdio>
#include <cstdlib> #include <cmath> #include <fstream> #include <random>

// Ein "Bildschirm", der das Setzen eines Pixels kapselt // Der Bildschirm hat eine Auflösung (Breite x Höhe) // Kann zur Ausgabe einer PPM-Datei verwendet werden oder // mit SDL2 implementiert werden. void create_image(int image_width, int image_height, const Camera& camera){ std::cout << "P3\n" << image_width << ' ' << image_height << "\n255\n";

for (int j = 0; j < image_height; j++) { std::clog << "\rScanlines remaining: " << (image_height - j) << ' ' << std::flush; for (int i = 0; i < image_width; i++) { Vector<float, 3> pixel_center = camera.pixel00_loc + (static_cast<float>(i) * camera.pixel_delta_u) + (static_cast<float>(j) * camera.pixel_delta_v); Vector3df ray_direction = pixel_center - camera.camera_center; Ray3df r{camera.camera_center, ray_direction};

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

} std::clog << "\rDone. \n"; }

// Eine "Kamera", die von einem Augenpunkt aus in eine Richtung senkrecht auf ein Rechteck (das Bild) zeigt. // Für das Rechteck muss die Auflösung oder alternativ die Pixelbreite und -höhe bekannt sein. // Für ein Pixel mit Bildkoordinate kann ein Sehstrahl erzeugt werden. void Camera::create_camera(int image_width, int image_height){

float focal_length = 1.0f; float viewport_height = 2.0f; float viewport_width = viewport_height * (double(image_width)/image_height); this->camera_center = Vector3df{0.0f, 0.0f, 0.0f};

// Calculate the vectors across the horizontal and down the vertical viewport edges. this->viewport_u = Vector3df{viewport_width, 0.0f, 0.0f}; this->viewport_v = Vector3df{0.0f, -viewport_height, 0.0f};

// Calculate the horizontal and vertical delta vectors from pixel to pixel. this->pixel_delta_u = viewport_u / static_cast<float>(image_width); this->pixel_delta_v = viewport_v / static_cast<float>(image_height);

// Calculate the location of the upper left pixel. this->viewport_upper_left = camera_center - Vector3df{0, 0, focal_length} - viewport_u/2 - viewport_v/2; this->pixel00_loc = viewport_upper_left + 0.5f * (pixel_delta_u + pixel_delta_v);

}

// Für die "Farbe" benötigt man nicht unbedingt eine eigene Datenstruktur. // Sie kann als Vector3df implementiert werden mit Farbanteil von 0 bis 1. // Vor Setzen eines Pixels auf eine bestimmte Farbe (z.B. 8-Bit-Farbtiefe), // kann der Farbanteil mit 255 multipliziert und der Nachkommaanteil verworfen werden. void write_color(std::ostream& out, const Vector3df& pixel_color) { auto r = pixel_color[0]; auto g = pixel_color[1]; auto b = pixel_color[2];

// Translate the [0,1] component values to the byte range [0,255]. int rbyte = int(255.999 * r); int gbyte = int(255.999 * g); int bbyte = int(255.999 * b);

// Write out the pixel color components. out << rbyte << ' ' << gbyte << ' ' << bbyte << '\n'; }

// Ein "Objekt", z.B. eine Kugel oder ein Dreieck, und dem zugehörigen Material der Oberfläche. // Im Prinzip ein Wrapper-Objekt, das mindestens Material und geometrisches Objekt zusammenfasst. // Kugel und Dreieck finden Sie in geometry.h/tcc color hit_sphere(const Ray3df& r) { Sphere3df sphere(Vector3df{0.0f, 0.0f, -1.0f}, 0.5f); Intersection_Context<float, 3> context; if (sphere.intersects(r, context)) { Vector3df normal_color = 0.5f * (context.normal + Vector3df{1.0f, 1.0f, 1.0f}); return normal_color; }

Vector3df unit_direction = unit_vector(r.direction); float a = 0.5f * (unit_direction[1] + 1.0f); return (1.0f - a) * color{1.0f, 1.0f, 1.0f} + a * color{0.5f, 0.7f, 1.0f}; }

int main() { int image_width = 400; float aspect_ratio = 16.0f / 9.0f; int image_height = static_cast<int>(image_width / aspect_ratio); image_height = (image_height < 1) ? 1 : image_height;

// Kamera erstellen Camera camera{}; camera.create_camera(image_width, image_height);

// Ausgabe in Datei umleiten std::ofstream outfile("result.ppm"); if (!outfile) { std::cerr << "Fehler beim Öffnen der Datei!" << std::endl; return 1; }

// Temporär cout umleiten std::streambuf* cout_backup = std::cout.rdbuf(); std::cout.rdbuf(outfile.rdbuf());

// Bild erstellen create_image(image_width, image_height, camera);

// cout wiederherstellen std::cout.rdbuf(cout_backup); outfile.close();

std::cout << "Bild wurde gespeichert!" << std::endl;

return 0; }

raytracer.h
#ifndef RAYTRACER_H
#define RAYTRACER_H


#include "math.h"
#include "geometry.h"
#include <iostream>
#include <fstream>
#include <limits>
#include <cmath>
#include <memory>
#include <vector>



using vec = Vector<float, 3u>;
using color = Vector<float, 3u>;
using ray = Ray<float, 3u>;

class Camera {
public: 
    Vector<float, 3> camera_center;
    Vector<float, 3> viewport_u;
    Vector<float, 3> viewport_v;
    Vector<float, 3> pixel_delta_u;
    Vector<float, 3> pixel_delta_v;
    Vector<float, 3> viewport_upper_left;
    Vector<float, 3> pixel00_loc;

    Camera() = default;
    void create_camera(int image_width, int image_height);
};

// ## NEW ##



void create_image(int image_width, int image_height, const Camera&camera);

void write_color(std::ostream& out, const color& pixel_color);

color ray_color(const Ray3df& r);

Vector<float, 3> hit_sphere(const Ray3df& r);


#endif