From dd272f0b65b820b0f3cf4832983dfe3343b93542 Mon Sep 17 00:00:00 2001 From: ubuntu20 Date: Wed, 4 Nov 2020 10:26:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E9=87=8D=E9=87=87=E6=A0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Material.cpp | 10 ++++++ Material.h | 13 ++++++++ Object.cpp | 25 +++++++++++++++ Object.h | 11 +++++++ Ray.h | 1 + Scene.cpp | 63 ++++++++++++++++++++++++++------------ Vector3.cpp | 8 +++++ Vector3.h | 4 ++- raytracing.vcxproj | 4 +++ raytracing.vcxproj.filters | 12 ++++++++ util.cpp | 10 ++++++ util.h | 4 ++- 12 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 Material.cpp create mode 100644 Material.h create mode 100644 Object.cpp create mode 100644 Object.h diff --git a/Material.cpp b/Material.cpp new file mode 100644 index 0000000..c5f1c27 --- /dev/null +++ b/Material.cpp @@ -0,0 +1,10 @@ +#include "Material.h" +#include "Ray.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); + return true; +} diff --git a/Material.h b/Material.h new file mode 100644 index 0000000..a0a2472 --- /dev/null +++ b/Material.h @@ -0,0 +1,13 @@ +#pragma once +#include "Vector3.h" +class Ray; +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; } + bool Scatter(const Ray& input_ray, const HitPoint& hit_point, Ray& out_ray); +}; \ No newline at end of file diff --git a/Object.cpp b/Object.cpp new file mode 100644 index 0000000..673740c --- /dev/null +++ b/Object.cpp @@ -0,0 +1,25 @@ +#include "Object.h" +#include "Material.h" +#include "Ray.h" +#include + +Object::Object(Geometry * g, Material * m) +{ + mGeometry = g; + mMaterial = m; +} + +void Object::Set(Geometry * g, Material * m) +{ + mGeometry = g; + mMaterial = m; +} + +bool Object::HitTest(const Ray & input_ray, float min_distance, float max_distance, HitPoint & hit_point) +{ + if (mGeometry->HitTest(input_ray, min_distance, max_distance, hit_point)) { + hit_point.mMaterial = mMaterial; + return true; + } + return false; +} diff --git a/Object.h b/Object.h new file mode 100644 index 0000000..f3cd7c8 --- /dev/null +++ b/Object.h @@ -0,0 +1,11 @@ +#pragma once +#include "Vector3.h" +class Material; +class Object { +public: + Geometry *mGeometry; + Material *mMaterial; + Object(Geometry* g, Material* m); + void Set(Geometry* g, Material* m); + bool HitTest(const Ray& input_ray, float min_distance, float max_distance, HitPoint& hit_point); +}; \ No newline at end of file diff --git a/Ray.h b/Ray.h index 674e901..ca97106 100644 --- a/Ray.h +++ b/Ray.h @@ -3,6 +3,7 @@ class Ray { public: Vector3 mOrigin, mDirection, mLightAttenuation; + Ray() {}; Ray(const Vector3& origin, const Vector3& direction, const Vector3& attenuation); void Set(const Vector3& origin, const Vector3& direction, const Vector3& attenuation); Vector3 PointAt(float k) const; diff --git a/Scene.cpp b/Scene.cpp index 8fe7527..f749aba 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -2,6 +2,8 @@ #include "util.h" #include "Camera.h" #include "Ray.h" +#include "Material.h" +#include "Object.h" #include "Vector3.h" #include "Sphere.h" #pragma comment(lib, "winmm.lib") @@ -9,6 +11,17 @@ static int sTotalPixelCount = 0; static int sViewportWidth = 0, sViewportHeight = 0; static Camera* sCamera = nullptr; Sphere sphere(Vector3(0.0f, 0.0f, -5.0f), 0.5f); +static Object* sRootObject = nullptr; +static Material* lambert = nullptr; +static int sSampleCount = 64; +void AddObject(Object* object) { + if (sRootObject == nullptr) { + sRootObject = object; + } + else { + //TODO + } +} void Init(int width, int height) { sTotalPixelCount = width * height; @@ -16,6 +29,8 @@ void Init(int width, int height) sViewportHeight = height; sCamera = new Camera(45.0f, float(width) / float(height)); sCamera->LookAt(Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, -1.0f), Vector3(0.0f, 1.0f, 0.0f)); + lambert = new LamberMaterial(Vector3(0.1f, 0.4f, 0.7f)); + AddObject(new Object(&sphere, lambert)); } float GetEscaptedTime() { @@ -35,29 +50,37 @@ Vector3 GetEnviromentColor(const Ray& input_ray) { return factor * top_color + (1.0f - factor) * bottom_color; } +Vector3 GetColor(const Ray& input_ray) { + HitPoint hit_point; + if (sRootObject->HitTest(input_ray, 0.01f, 100.0f, hit_point)) { + Ray scatter_ray; + if (hit_point.mMaterial->Scatter(input_ray, hit_point, scatter_ray)) { + return GetColor(scatter_ray); + } + } + + return GetEnviromentColor(input_ray); +} + void RenderOnePixel(int pixel_index) { int x = pixel_index % sViewportWidth; int y = pixel_index / sViewportWidth; - float u = float(x) / sViewportWidth; - float v = float(y) / sViewportHeight; - Ray ray = sCamera->GetRay(u,v); - HitPoint hit_point; - if (sphere.HitTest(ray, 0.0f, 100.0f, hit_point)) { - float rf = hit_point.mNormal.x * 0.5f + 0.5f; - float gf = hit_point.mNormal.y * 0.5f + 0.5f; - float bf = hit_point.mNormal.z * 0.5f + 0.5f; - AByte r = AByte(rf * 255.0f); - AByte g = AByte(gf * 255.0f); - AByte b = AByte(bf * 255.0f); - SetColor(x, y, r, g, b, 255); - } - else { - Vector3 color = GetEnviromentColor(ray); - AByte r = AByte(color.x * 255.0f); - AByte g = AByte(color.y * 255.0f); - AByte b = AByte(color.z * 255.0f); - SetColor(x, y, r, g, b, 255); + + Vector3 color; + for (int i = 0; i < sSampleCount; i++) { + float offset_u = srandf()*0.5; + float offset_v = srandf()*0.5; + float u = (float(x) + offset_u) / sViewportWidth; + float v = (float(y) + offset_v) / sViewportHeight; + Ray ray = sCamera->GetRay(u, v); + Vector3 current_color = GetColor(ray); + color = color + current_color; } + color /= sSampleCount; + AByte r = AByte(color.x * 255.0f); + AByte g = AByte(color.y * 255.0f); + AByte b = AByte(color.z * 255.0f); + SetColor(x, y, r, g, b, 255); } void Render() @@ -67,7 +90,7 @@ void Render() while (sCurrentRenderPixel < sTotalPixelCount) { RenderOnePixel(sCurrentRenderPixel); sCurrentRenderPixel++; - current_render_time = GetEscaptedTime(); + current_render_time += GetEscaptedTime(); if (current_render_time > 0.016f) { break; } diff --git a/Vector3.cpp b/Vector3.cpp index a48a4a0..5d791a9 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -1,5 +1,6 @@ #include "Vector3.h" #include +#include "util.h" Vector3 Vector3::operator+(const Vector3 & v) const { @@ -69,3 +70,10 @@ Vector3 Cross(const Vector3 & l, const Vector3 & r) { return Vector3(l.y*r.z - l.z*r.y, l.z*r.x - l.x*r.z, l.x*r.y - l.y*r.x); } + +Vector3 UnitRandomVector3InSphere() +{ + Vector3 random_vector(srandf(), srandf(), srandf()); + random_vector.Normalize(); + return random_vector; +} diff --git a/Vector3.h b/Vector3.h index cca27cb..301334c 100644 --- a/Vector3.h +++ b/Vector3.h @@ -47,5 +47,7 @@ struct HitPoint { }; class Ray; class Geometry { +public: virtual bool HitTest(const Ray& input_ray, float min_distance, float max_distance, HitPoint& hit_point) = 0; -}; \ No newline at end of file +}; +Vector3 UnitRandomVector3InSphere(); \ No newline at end of file diff --git a/raytracing.vcxproj b/raytracing.vcxproj index a5e4c56..d8976d7 100644 --- a/raytracing.vcxproj +++ b/raytracing.vcxproj @@ -128,6 +128,8 @@ + + @@ -136,6 +138,8 @@ + + diff --git a/raytracing.vcxproj.filters b/raytracing.vcxproj.filters index 07d1d8c..5501549 100644 --- a/raytracing.vcxproj.filters +++ b/raytracing.vcxproj.filters @@ -36,6 +36,12 @@ 源文件 + + 源文件 + + + 源文件 + @@ -56,5 +62,11 @@ 源文件 + + 源文件 + + + 源文件 + \ No newline at end of file diff --git a/util.cpp b/util.cpp index 57f1892..080927a 100644 --- a/util.cpp +++ b/util.cpp @@ -31,3 +31,13 @@ void ASwapBuffers(HDC dc) { BitBlt(dc, 0, 0, sRenderableBuffer->mWidth, sRenderableBuffer->mHeight, sRenderableBuffer->mDC, 0,0, SRCCOPY); } + +float randf() +{ + return float(rand()) / float(RAND_MAX); +} + +float srandf() +{ + return randf() * 2.0f - 1.0f; +} diff --git a/util.h b/util.h index 0c737ee..177227d 100644 --- a/util.h +++ b/util.h @@ -15,4 +15,6 @@ struct RenderableBuffer { void InitRenderableBuffer(HDC dc, int width, int height); void SetColor(int x, int y, AByte r, AByte g, AByte b, AByte a); -void ASwapBuffers(HDC dc); \ No newline at end of file +void ASwapBuffers(HDC dc); +float randf(); +float srandf(); \ No newline at end of file