diff --git a/Material.cpp b/Material.cpp index dd140fa..71662ca 100644 --- a/Material.cpp +++ b/Material.cpp @@ -1,16 +1,17 @@ #include "Material.h" #include "Ray.h" +#include "Texture.h" #include bool LamberMaterial::Scatter(const Ray & input_ray, const HitPoint & hit_point, Ray & out_ray) { Vector3 random_vector = UnitRandomVector3InSphere(); Vector3 new_direction = hit_point.mNormal + random_vector; - out_ray.Set(hit_point.mPosition, new_direction, input_ray.mLightAttenuation*mDiffuse); + out_ray.Set(hit_point.mPosition, new_direction, input_ray.mLightAttenuation*mDiffuseTexture->Sample(hit_point.mU, hit_point.mV)); return true; } bool MetalMaterial::Scatter(const Ray & input_ray, const HitPoint & hit_point, Ray & out_ray) { Vector3 new_direction = Reflect(input_ray.mDirection, hit_point.mNormal); - out_ray.Set(hit_point.mPosition, new_direction, input_ray.mLightAttenuation*mDiffuse); + out_ray.Set(hit_point.mPosition, new_direction, input_ray.mLightAttenuation*mDiffuseTexture->Sample(hit_point.mU, hit_point.mV)); return true; } \ No newline at end of file diff --git a/Material.h b/Material.h index 44aa762..5513295 100644 --- a/Material.h +++ b/Material.h @@ -1,19 +1,20 @@ #pragma once #include "Vector3.h" class Ray; +class Texture2D; class Material { public: virtual bool Scatter(const Ray& input_ray, const HitPoint& hit_point, Ray& out_ray) = 0; }; class LamberMaterial : public Material { public: - Vector3 mDiffuse; - LamberMaterial(const Vector3 diffuse) { mDiffuse = diffuse; } + Texture2D *mDiffuseTexture; + LamberMaterial(Texture2D* diffuse) { mDiffuseTexture = diffuse; } bool Scatter(const Ray& input_ray, const HitPoint& hit_point, Ray& out_ray); }; class MetalMaterial : public Material { public: - Vector3 mDiffuse; - MetalMaterial(const Vector3 diffuse) { mDiffuse = diffuse; } + Texture2D *mDiffuseTexture; + MetalMaterial(Texture2D* diffuse) { mDiffuseTexture = diffuse; } bool Scatter(const Ray& input_ray, const HitPoint& hit_point, Ray& out_ray); }; \ No newline at end of file diff --git a/Scene.cpp b/Scene.cpp index b0951a7..d61616f 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -6,6 +6,7 @@ #include "Object.h" #include "Vector3.h" #include "Sphere.h" +#include "Texture.h" #pragma comment(lib, "winmm.lib") static int sTotalPixelCount = 0; static int sViewportWidth = 0, sViewportHeight = 0; @@ -13,8 +14,8 @@ static Camera* sCamera = nullptr; Sphere sphere(Vector3(0.0f, 0.5f, 0.0f), 0.5f); static Object* sRootObject = nullptr; static Material* lambert = nullptr; -static int sSampleCount = 6; -static int sMaxBounceTime = 30; +static int sSampleCount = 256; +static int sMaxBounceTime = 2; void AddObject(Object* object) { if (sRootObject == nullptr) { sRootObject = object; @@ -30,11 +31,18 @@ void Init(int width, int height) sViewportHeight = height; sCamera = new Camera(45.0f, float(width) / float(height)); sCamera->LookAt(Vector3(3.0f, 1.0f, 3.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f)); - Material* earth_material = new LamberMaterial(Vector3(0.5f, 0.3f, 0.1f)); - Material* metal_material = new MetalMaterial(Vector3(0.9f,0.9f,0.9f)); + Texture2D* solid_color1 = new TextureSolidColor(Vector3(0.1f, 0.4f, 0.7f)); + Texture2D* solid_color2 = new TextureSolidColor(Vector3(0.5f, 0.3f, 0.1f)); + Texture2D* solid_color3 = new TextureSolidColor(Vector3(0.9f, 0.9f, 0.9f)); + + Material* earth_material = new LamberMaterial(solid_color2); + Material* metal_material = new MetalMaterial(solid_color3); AddObject(new Object(new Sphere(Vector3(0.0f, -1000.0f, 0.0), 1000.0f), earth_material)); AddObject(new Object(new Sphere(Vector3(-1.0f, 0.5f, 0.3), 0.5f), metal_material)); - lambert = new LamberMaterial(Vector3(0.1f, 0.4f, 0.7f)); + + TextureRGB* rgb = new TextureRGB(); + rgb->Set("earth.bmp"); + lambert = new LamberMaterial(rgb); AddObject(new Object(&sphere, lambert)); } diff --git a/Sphere.cpp b/Sphere.cpp index bb01341..567b26e 100644 --- a/Sphere.cpp +++ b/Sphere.cpp @@ -47,7 +47,18 @@ bool Sphere::HitTest(const Ray& input_ray, float min_distance, float max_distanc normal.Normalize(); hit_point.mDistance = distance; hit_point.mNormal = normal; + CalculateTexcoord(hit_point.mPosition, hit_point.mU, hit_point.mV); } return isHited; } + +#define PI 3.1415926f +void Sphere::CalculateTexcoord(const Vector3& pos_on_sphere, float& u, float& v) { + float a = atan2f(pos_on_sphere.z, pos_on_sphere.x); + float b = asinf(pos_on_sphere.y); + a = a + PI; + u = a / (2.0f * PI); + b = b + PI / 2.0f; + v = b / PI; +} diff --git a/Sphere.h b/Sphere.h index 16f938e..d4fcc46 100644 --- a/Sphere.h +++ b/Sphere.h @@ -7,4 +7,5 @@ public: Sphere(const Vector3& origin, float radius); void set(const Vector3& origin, float radius); bool HitTest(const Ray& input_ray, float min_distance, float max_distance, HitPoint& hit_point); + void CalculateTexcoord(const Vector3& pos_on_sphere, float &u, float &v); }; diff --git a/Texture.cpp b/Texture.cpp index 8640092..a5ad936 100644 --- a/Texture.cpp +++ b/Texture.cpp @@ -26,7 +26,7 @@ void TextureRGB::Set(const char * image_path) Vector3 TextureRGB::Sample(float u, float v) { int x = int(u * mWidth); - int y = int(u * mHeight); + int y = int(v * mHeight); x = x < 0 ? 0 : x; y = y < 0 ? 0 : y; x = x > (mWidth - 1) ? (mWidth - 1) : x; @@ -37,3 +37,13 @@ Vector3 TextureRGB::Sample(float u, float v) float b = float(mRGBPixel[pixel_data_start_index + 2]) / 255.0f; return Vector3(r, g, b); } + +TextureSolidColor::TextureSolidColor(const Vector3 & color) +{ + mSolidColor = color; +} + +Vector3 TextureSolidColor::Sample(float u, float v) +{ + return mSolidColor; +} diff --git a/Texture.h b/Texture.h index 4a07ad6..1b70348 100644 --- a/Texture.h +++ b/Texture.h @@ -4,6 +4,12 @@ class Texture2D { public: virtual Vector3 Sample(float u, float v) = 0; }; +class TextureSolidColor : public Texture2D { +public: + Vector3 mSolidColor; + TextureSolidColor(const Vector3& color); + Vector3 Sample(float u, float v); +}; class TextureRGB : public Texture2D { public: unsigned char* mImageFileContent; diff --git a/Vector3.h b/Vector3.h index e537efc..e3ccd7b 100644 --- a/Vector3.h +++ b/Vector3.h @@ -43,6 +43,7 @@ class Material; struct HitPoint { Vector3 mPosition; Vector3 mNormal; + float mU, mV; float mDistance; Material* mMaterial; }; diff --git a/earth.bmp b/earth.bmp new file mode 100644 index 0000000..681bb7f Binary files /dev/null and b/earth.bmp differ