You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
3.6 KiB
115 lines
3.6 KiB
#include "Scene.h"
|
|
#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")
|
|
static int sTotalPixelCount = 0;
|
|
static int sViewportWidth = 0, sViewportHeight = 0;
|
|
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;
|
|
void AddObject(Object* object) {
|
|
if (sRootObject == nullptr) {
|
|
sRootObject = object;
|
|
}
|
|
else {
|
|
sRootObject->Append(object);
|
|
}
|
|
}
|
|
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(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));
|
|
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));
|
|
AddObject(new Object(&sphere, lambert));
|
|
}
|
|
|
|
float GetEscaptedTime() {
|
|
static unsigned long sTimeSinceComputerStart = 0;
|
|
static unsigned long sLastFrameTime = 0;
|
|
sTimeSinceComputerStart = timeGetTime();
|
|
unsigned long frame_time = sLastFrameTime == 0 ? 0 : sTimeSinceComputerStart - sLastFrameTime;
|
|
sLastFrameTime = sTimeSinceComputerStart;
|
|
|
|
return float(frame_time) / 1000.0f;
|
|
}
|
|
|
|
Vector3 GetEnviromentColor(const Ray& input_ray) {
|
|
Vector3 bottom_color(1.0f, 1.0f, 1.0f);
|
|
Vector3 top_color(0.5f, 0.7f, 1.0f);
|
|
float factor = 0.5f * input_ray.mDirection.y + 0.5f;
|
|
return factor * top_color + (1.0f - factor) * bottom_color;
|
|
}
|
|
|
|
Vector3 RenderOneSample(const Ray& input_ray, int bounce_time) {
|
|
HitPoint hit_point;
|
|
float max_distance = 1000.0f;
|
|
Object* current_object = sRootObject;
|
|
Object* hitted_object = nullptr;
|
|
|
|
while (current_object != nullptr) {
|
|
if (current_object->HitTest(input_ray, 0.01f, max_distance, hit_point)) {
|
|
max_distance = hit_point.mDistance;
|
|
hitted_object = current_object;
|
|
}
|
|
current_object = current_object->Next<Object>();
|
|
}
|
|
if (hitted_object != nullptr) {
|
|
if(bounce_time < sMaxBounceTime){
|
|
Ray scatter_ray;
|
|
if (hit_point.mMaterial->Scatter(input_ray, hit_point, scatter_ray)) {
|
|
return RenderOneSample(scatter_ray, bounce_time + 1);
|
|
}
|
|
}
|
|
}
|
|
return GetEnviromentColor(input_ray) * input_ray.mLightAttenuation;
|
|
}
|
|
|
|
void RenderOnePixel(int pixel_index) {
|
|
int x = pixel_index % sViewportWidth;
|
|
int y = pixel_index / sViewportWidth;
|
|
|
|
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 = RenderOneSample(ray,0);
|
|
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()
|
|
{
|
|
static int sCurrentRenderPixel = 0;
|
|
float current_render_time = 0.0f;
|
|
while (sCurrentRenderPixel < sTotalPixelCount) {
|
|
RenderOnePixel(sCurrentRenderPixel);
|
|
sCurrentRenderPixel++;
|
|
current_render_time += GetEscaptedTime();
|
|
if (current_render_time > 0.016f) {
|
|
break;
|
|
}
|
|
}
|
|
}
|