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.

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