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

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #include "Scene.h"
  2. #include "util.h"
  3. #include "Camera.h"
  4. #include "Ray.h"
  5. #include "Material.h"
  6. #include "Object.h"
  7. #include "Vector3.h"
  8. #include "Sphere.h"
  9. #pragma comment(lib, "winmm.lib")
  10. static int sTotalPixelCount = 0;
  11. static int sViewportWidth = 0, sViewportHeight = 0;
  12. static Camera* sCamera = nullptr;
  13. Sphere sphere(Vector3(0.0f, 0.5f, 0.0f), 0.5f);
  14. static Object* sRootObject = nullptr;
  15. static Material* lambert = nullptr;
  16. static int sSampleCount = 128;
  17. static int sMaxBounceTime = 30;
  18. void AddObject(Object* object) {
  19. if (sRootObject == nullptr) {
  20. sRootObject = object;
  21. }
  22. else {
  23. sRootObject->Append(object);
  24. }
  25. }
  26. void Init(int width, int height)
  27. {
  28. sTotalPixelCount = width * height;
  29. sViewportWidth = width;
  30. sViewportHeight = height;
  31. sCamera = new Camera(45.0f, float(width) / float(height));
  32. sCamera->LookAt(Vector3(3.0f, 1.0f, 3.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f));
  33. Material* earth_material = new LamberMaterial(Vector3(0.5f, 0.3f, 0.1f));
  34. Material* metal_material = new MetalMaterial(Vector3(0.9f,0.9f,0.9f));
  35. AddObject(new Object(new Sphere(Vector3(0.0f, -1000.0f, 0.0), 1000.0f), earth_material));
  36. AddObject(new Object(new Sphere(Vector3(-1.0f, 0.5f, 0.3), 0.5f), metal_material));
  37. lambert = new LamberMaterial(Vector3(0.1f, 0.4f, 0.7f));
  38. AddObject(new Object(&sphere, lambert));
  39. }
  40. float GetEscaptedTime() {
  41. static unsigned long sTimeSinceComputerStart = 0;
  42. static unsigned long sLastFrameTime = 0;
  43. sTimeSinceComputerStart = timeGetTime();
  44. unsigned long frame_time = sLastFrameTime == 0 ? 0 : sTimeSinceComputerStart - sLastFrameTime;
  45. sLastFrameTime = sTimeSinceComputerStart;
  46. return float(frame_time) / 1000.0f;
  47. }
  48. Vector3 GetEnviromentColor(const Ray& input_ray) {
  49. Vector3 bottom_color(1.0f, 1.0f, 1.0f);
  50. Vector3 top_color(0.5f, 0.7f, 1.0f);
  51. float factor = 0.5f * input_ray.mDirection.y + 0.5f;
  52. return factor * top_color + (1.0f - factor) * bottom_color;
  53. }
  54. Vector3 RenderOneSample(const Ray& input_ray, int bounce_time) {
  55. HitPoint hit_point;
  56. float max_distance = 1000.0f;
  57. Object* current_object = sRootObject;
  58. Object* hitted_object = nullptr;
  59. while (current_object != nullptr) {
  60. if (current_object->HitTest(input_ray, 0.01f, max_distance, hit_point)) {
  61. max_distance = hit_point.mDistance;
  62. hitted_object = current_object;
  63. }
  64. current_object = current_object->Next<Object>();
  65. }
  66. if (hitted_object != nullptr) {
  67. if(bounce_time < sMaxBounceTime){
  68. Ray scatter_ray;
  69. if (hit_point.mMaterial->Scatter(input_ray, hit_point, scatter_ray)) {
  70. return RenderOneSample(scatter_ray, bounce_time + 1);
  71. }
  72. }
  73. }
  74. return GetEnviromentColor(input_ray) * input_ray.mLightAttenuation;
  75. }
  76. void RenderOnePixel(int pixel_index) {
  77. int x = pixel_index % sViewportWidth;
  78. int y = pixel_index / sViewportWidth;
  79. Vector3 color;
  80. for (int i = 0; i < sSampleCount; i++) {
  81. float offset_u = srandf()*0.5;
  82. float offset_v = srandf()*0.5;
  83. float u = (float(x) + offset_u) / sViewportWidth;
  84. float v = (float(y) + offset_v) / sViewportHeight;
  85. Ray ray = sCamera->GetRay(u, v);
  86. Vector3 current_color = RenderOneSample(ray,0);
  87. color = color + current_color;
  88. }
  89. color /= sSampleCount;
  90. AByte r = AByte(color.x * 255.0f);
  91. AByte g = AByte(color.y * 255.0f);
  92. AByte b = AByte(color.z * 255.0f);
  93. SetColor(x, y, r, g, b, 255);
  94. }
  95. void Render()
  96. {
  97. static int sCurrentRenderPixel = 0;
  98. float current_render_time = 0.0f;
  99. while (sCurrentRenderPixel < sTotalPixelCount) {
  100. RenderOnePixel(sCurrentRenderPixel);
  101. sCurrentRenderPixel++;
  102. current_render_time += GetEscaptedTime();
  103. if (current_render_time > 0.016f) {
  104. break;
  105. }
  106. }
  107. }