Browse Source

多重采样

master
ubuntu20 4 years ago
parent
commit
dd272f0b65
  1. 10
      Material.cpp
  2. 13
      Material.h
  3. 25
      Object.cpp
  4. 11
      Object.h
  5. 1
      Ray.h
  6. 55
      Scene.cpp
  7. 8
      Vector3.cpp
  8. 2
      Vector3.h
  9. 4
      raytracing.vcxproj
  10. 12
      raytracing.vcxproj.filters
  11. 10
      util.cpp
  12. 2
      util.h

10
Material.cpp

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

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

25
Object.cpp

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

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

1
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;

55
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);
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;
}
else {
Vector3 color = GetEnviromentColor(ray);
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;
}

8
Vector3.cpp

@ -1,5 +1,6 @@
#include "Vector3.h"
#include <math.h>
#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;
}

2
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;
};
Vector3 UnitRandomVector3InSphere();

4
raytracing.vcxproj

@ -128,6 +128,8 @@
<ItemGroup>
<ClCompile Include="Camera.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Material.cpp" />
<ClCompile Include="Object.cpp" />
<ClCompile Include="Ray.cpp" />
<ClCompile Include="Scene.cpp" />
<ClCompile Include="Sphere.cpp" />
@ -136,6 +138,8 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Camera.h" />
<ClInclude Include="Material.h" />
<ClInclude Include="Object.h" />
<ClInclude Include="Ray.h" />
<ClInclude Include="Scene.h" />
<ClInclude Include="Sphere.h" />

12
raytracing.vcxproj.filters

@ -36,6 +36,12 @@
<ClCompile Include="Sphere.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Object.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Material.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Scene.h">
@ -56,5 +62,11 @@
<ClInclude Include="Sphere.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="Object.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="Material.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
</Project>

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

2
util.h

@ -16,3 +16,5 @@ 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);
float randf();
float srandf();
Loading…
Cancel
Save