Browse Source

渲染一个球

master
ubuntu20 4 years ago
parent
commit
2e95261b12
  1. 2
      Camera.cpp
  2. 2
      Ray.cpp
  3. 2
      Ray.h
  4. 31
      Scene.cpp
  5. 51
      Sphere.cpp
  6. 10
      Sphere.h
  7. 13
      Vector3.h
  8. 2
      raytracing.vcxproj
  9. 6
      raytracing.vcxproj.filters

2
Camera.cpp

@ -24,7 +24,7 @@ void Camera::LookAt(const Vector3& position, const Vector3& center, const Vector
mUVector = right_direction; mUVector = right_direction;
mVVector = up_direction; mVVector = up_direction;
mUSpanVector = mNearPlaneWidth * mUVector; mUSpanVector = mNearPlaneWidth * mUVector;
mVSpanVector = mNearPlaneHeight * mUVector;
mVSpanVector = mNearPlaneHeight * mVVector;
mCenter = center; mCenter = center;
mPosition = position; mPosition = position;
mUp = up; mUp = up;

2
Ray.cpp

@ -8,6 +8,6 @@ void Ray::Set(const Vector3& origin, const Vector3& direction, const Vector3& at
mDirection.Normalize(); mDirection.Normalize();
mLightAttenuation = attenuation; mLightAttenuation = attenuation;
} }
Vector3 Ray::PointAt(float k) {
Vector3 Ray::PointAt(float k) const {
return mOrigin + k * mDirection; return mOrigin + k * mDirection;
} }

2
Ray.h

@ -5,5 +5,5 @@ public:
Vector3 mOrigin, mDirection, mLightAttenuation; Vector3 mOrigin, mDirection, mLightAttenuation;
Ray(const Vector3& origin, const Vector3& direction, const Vector3& attenuation); Ray(const Vector3& origin, const Vector3& direction, const Vector3& attenuation);
void Set(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;
}; };

31
Scene.cpp

@ -2,17 +2,20 @@
#include "util.h" #include "util.h"
#include "Camera.h" #include "Camera.h"
#include "Ray.h" #include "Ray.h"
#include "Vector3.h"
#include "Sphere.h"
#pragma comment(lib, "winmm.lib") #pragma comment(lib, "winmm.lib")
static int sTotalPixelCount = 0; static int sTotalPixelCount = 0;
static int sViewportWidth = 0, sViewportHeight = 0; static int sViewportWidth = 0, sViewportHeight = 0;
static Camera* sCamera = nullptr; static Camera* sCamera = nullptr;
Sphere sphere(Vector3(0.0f, 0.0f, -5.0f), 0.5f);
void Init(int width, int height) void Init(int width, int height)
{ {
sTotalPixelCount = width * height; sTotalPixelCount = width * height;
sViewportWidth = width; sViewportWidth = width;
sViewportHeight = height; sViewportHeight = height;
sCamera = new Camera(45.0f, float(width) / float(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() { float GetEscaptedTime() {
@ -31,13 +34,25 @@ void RenderOnePixel(int pixel_index) {
float u = float(x) / sViewportWidth; float u = float(x) / sViewportWidth;
float v = float(y) / sViewportHeight; float v = float(y) / sViewportHeight;
Ray ray = sCamera->GetRay(u,v); 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() void Render()

51
Sphere.cpp

@ -0,0 +1,51 @@
#include "Sphere.h"
#include"Ray.h"
#include<math.h>
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;
}

10
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);
};

13
Vector3.h

@ -37,4 +37,15 @@ public:
}; };
Vector3 operator*(float f, const Vector3& v); Vector3 operator*(float f, const Vector3& v);
float Dot(const Vector3& l, const Vector3& r); float Dot(const Vector3& l, const Vector3& r);
Vector3 Cross(const Vector3& l, const Vector3& r);
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;
};

2
raytracing.vcxproj

@ -130,6 +130,7 @@
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Ray.cpp" /> <ClCompile Include="Ray.cpp" />
<ClCompile Include="Scene.cpp" /> <ClCompile Include="Scene.cpp" />
<ClCompile Include="Sphere.cpp" />
<ClCompile Include="util.cpp" /> <ClCompile Include="util.cpp" />
<ClCompile Include="Vector3.cpp" /> <ClCompile Include="Vector3.cpp" />
</ItemGroup> </ItemGroup>
@ -137,6 +138,7 @@
<ClInclude Include="Camera.h" /> <ClInclude Include="Camera.h" />
<ClInclude Include="Ray.h" /> <ClInclude Include="Ray.h" />
<ClInclude Include="Scene.h" /> <ClInclude Include="Scene.h" />
<ClInclude Include="Sphere.h" />
<ClInclude Include="util.h" /> <ClInclude Include="util.h" />
<ClInclude Include="Vector3.h" /> <ClInclude Include="Vector3.h" />
</ItemGroup> </ItemGroup>

6
raytracing.vcxproj.filters

@ -33,6 +33,9 @@
<ClCompile Include="Camera.cpp"> <ClCompile Include="Camera.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Sphere.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Scene.h"> <ClInclude Include="Scene.h">
@ -50,5 +53,8 @@
<ClInclude Include="Camera.h"> <ClInclude Include="Camera.h">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Sphere.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>
Loading…
Cancel
Save