diff --git a/Camera.cpp b/Camera.cpp index 3fe35a6..b29257c 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -24,7 +24,7 @@ void Camera::LookAt(const Vector3& position, const Vector3& center, const Vector mUVector = right_direction; mVVector = up_direction; mUSpanVector = mNearPlaneWidth * mUVector; - mVSpanVector = mNearPlaneHeight * mUVector; + mVSpanVector = mNearPlaneHeight * mVVector; mCenter = center; mPosition = position; mUp = up; diff --git a/Ray.cpp b/Ray.cpp index 75e4024..e7c523c 100644 --- a/Ray.cpp +++ b/Ray.cpp @@ -8,6 +8,6 @@ void Ray::Set(const Vector3& origin, const Vector3& direction, const Vector3& at mDirection.Normalize(); mLightAttenuation = attenuation; } -Vector3 Ray::PointAt(float k) { +Vector3 Ray::PointAt(float k) const { return mOrigin + k * mDirection; } \ No newline at end of file diff --git a/Ray.h b/Ray.h index 48352f1..674e901 100644 --- a/Ray.h +++ b/Ray.h @@ -5,5 +5,5 @@ public: Vector3 mOrigin, mDirection, mLightAttenuation; 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); + Vector3 PointAt(float k) const; }; \ No newline at end of file diff --git a/Scene.cpp b/Scene.cpp index b24e167..e06c5b3 100644 --- a/Scene.cpp +++ b/Scene.cpp @@ -2,17 +2,20 @@ #include "util.h" #include "Camera.h" #include "Ray.h" +#include "Vector3.h" +#include "Sphere.h" #pragma comment(lib, "winmm.lib") 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); void Init(int width, int height) { sTotalPixelCount = width * height; sViewportWidth = width; sViewportHeight = height; sCamera = new Camera(45.0f, float(width) / float(height)); - sCamera->LookAt(Vector3(0.0f,0.0f,1.0f), Vector3(0.0f,0.0f,0.0f), Vector3(0.0f,1.0f,0.0f)); + sCamera->LookAt(Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 0.0f, -1.0f), Vector3(0.0f, 1.0f, 0.0f)); } float GetEscaptedTime() { @@ -31,13 +34,25 @@ void RenderOnePixel(int pixel_index) { float u = float(x) / sViewportWidth; float v = float(y) / sViewportHeight; Ray ray = sCamera->GetRay(u,v); - float rf = ray.mDirection.x > 0.0f ? ray.mDirection.x : -ray.mDirection.x; - float gf = ray.mDirection.y > 0.0f ? ray.mDirection.y : -ray.mDirection.y; - float bf = ray.mDirection.z > 0.0f ? ray.mDirection.z : -ray.mDirection.z; - 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); + 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 { + float rf = ray.mDirection.x > 0.0f ? ray.mDirection.x : -ray.mDirection.x; + float gf = ray.mDirection.y > 0.0f ? ray.mDirection.y : -ray.mDirection.y; + float bf = ray.mDirection.z > 0.0f ? ray.mDirection.z : -ray.mDirection.z; + 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); + } } void Render() diff --git a/Sphere.cpp b/Sphere.cpp new file mode 100644 index 0000000..5507489 --- /dev/null +++ b/Sphere.cpp @@ -0,0 +1,51 @@ +#include "Sphere.h" +#include"Ray.h" +#include + +Sphere::Sphere(const Vector3 & origin, float radius) { + mOrigin = origin; + mRadius = radius; +} + +void Sphere::set(const Vector3 & origin, float radius) +{ + mOrigin = origin; + mRadius = radius; +} + +bool Sphere::HitTest(const Ray& input_ray, float min_distance, float max_distance, HitPoint& hit_point) { + Vector3 sphere_center_to_ray = input_ray.mOrigin - mOrigin; + float a = Dot(input_ray.mDirection, input_ray.mDirection); + float b = 2.0f * Dot(sphere_center_to_ray, input_ray.mDirection); + float c = Dot(sphere_center_to_ray, sphere_center_to_ray) - mRadius * mRadius; + float determinant = b * b - 4.0f * a * c; + + bool isHited = false; + float distance = -1.0f; + if (determinant > 0.0f) { + distance = (-b - sqrtf(determinant))/ 2.0f; + if (distance > min_distance && distance < max_distance) { + isHited = true; + } + distance = (-b + sqrtf(determinant)) / 2.0f; + if (distance > min_distance && distance < max_distance) { + isHited = true; + } + } + else if (determinant == 0.0f) { + distance = -b / 2.0f; + if (distance > min_distance && distance < max_distance) { + isHited = true; + } + } + + if (isHited) { + hit_point.mPosition = input_ray.PointAt(distance); + Vector3 normal = hit_point.mPosition - mOrigin; + normal.Normalize(); + hit_point.mDistance = distance; + hit_point.mNormal = normal; + } + + return isHited; +} diff --git a/Sphere.h b/Sphere.h new file mode 100644 index 0000000..16f938e --- /dev/null +++ b/Sphere.h @@ -0,0 +1,10 @@ +#pragma once +#include "Vector3.h" +class Sphere : public Geometry { +public: + Vector3 mOrigin; + float mRadius; + 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); +}; diff --git a/Vector3.h b/Vector3.h index e687c8f..cca27cb 100644 --- a/Vector3.h +++ b/Vector3.h @@ -37,4 +37,15 @@ public: }; Vector3 operator*(float f, const Vector3& v); float Dot(const Vector3& l, const Vector3& r); -Vector3 Cross(const Vector3& l, const Vector3& r); \ No newline at end of file +Vector3 Cross(const Vector3& l, const Vector3& r); +class Material; +struct HitPoint { + Vector3 mPosition; + Vector3 mNormal; + float mDistance; + Material* mMaterial; +}; +class Ray; +class Geometry { + virtual bool HitTest(const Ray& input_ray, float min_distance, float max_distance, HitPoint& hit_point) = 0; +}; \ No newline at end of file diff --git a/raytracing.vcxproj b/raytracing.vcxproj index ed07c41..a5e4c56 100644 --- a/raytracing.vcxproj +++ b/raytracing.vcxproj @@ -130,6 +130,7 @@ + @@ -137,6 +138,7 @@ + diff --git a/raytracing.vcxproj.filters b/raytracing.vcxproj.filters index 8dedff8..07d1d8c 100644 --- a/raytracing.vcxproj.filters +++ b/raytracing.vcxproj.filters @@ -33,6 +33,9 @@ 源文件 + + 源文件 + @@ -50,5 +53,8 @@ 源文件 + + 源文件 + \ No newline at end of file