1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| #include "Renderer.h" #include "Walnut/Random.h"
namespace Utils { static uint32_t ConvertToRGBA(const glm::vec4& color) { uint8_t r = (uint8_t)(color.r * 255.0f); uint8_t g = (uint8_t)(color.g * 255.0f); uint8_t b = (uint8_t)(color.b * 255.0f); uint8_t a = (uint8_t)(color.a * 255.0f);
uint32_t result = (a << 24) (b << 16) (g << 8) r; return result; } }
void Renderer::Render() { for (uint32_t y = 0; y < m_FinalImage->GetHeight(); ++y) { for (uint32_t x = 0; x < m_FinalImage->GetWidth(); ++x) { glm::vec2 coord = { (float)x / m_FinalImage->GetWidth(), (float)y / m_FinalImage->GetHeight() }; coord = coord * 2.0f - 1.0f;
glm::vec4 color = PerPixel(coord); color = glm::clamp(color, glm::vec4(0.0f), glm::vec4(1.0f)); m_ImageData[x + y*m_FinalImage->GetWidth()] = Utils::ConvertToRGBA(color); } }
m_FinalImage->SetData(m_ImageData); }
void Renderer::OnResize(uint32_t width,uint32_t height) { if (m_FinalImage) { if (m_FinalImage->GetWidth() == width && m_FinalImage->GetHeight() == height) { return; } m_FinalImage->Resize(width, height); } else { m_FinalImage = std::make_shared<Walnut::Image>(width, height, Walnut::ImageFormat::RGBA); }
delete[] m_ImageData; m_ImageData = new uint32_t[width * height]; }
glm::vec4 Renderer::PerPixel(glm::vec2 coord) { uint8_t r = (uint8_t)(coord.x * 255.0f); uint8_t g = (uint8_t)(coord.y * 255.0f);
glm::vec3 rayOrigin(0.0f,0.0f,2.0f); glm::vec3 rayDirection(coord.x, coord.y, -1.0f); float radius = 0.5f;
float a = glm::dot(rayDirection, rayDirection); float b = 2.0f * glm::dot(rayOrigin, rayDirection); float c = glm::dot(rayOrigin, rayOrigin) - radius * radius;
float discriminant = b * b - 4.0f * a * c;
if (discriminant < 0.0f) return glm::vec4(0,0,0,1);
float t0 = (-b + glm::sqrt(discriminant)) / 2.0f * a; float closestT = (-b - glm::sqrt(discriminant)) / 2.0f * a;
glm::vec3 hitPoint = rayOrigin + rayDirection * closestT; glm::vec3 normal = glm::normalize(hitPoint);
glm::vec3 lightDir = glm::normalize(glm::vec3(-1, -1, -1));
float d = glm::max(glm::dot(normal, -lightDir), 0.0f);
glm::vec3 sphereColor(1, 0, 1); sphereColor *= d; return glm::vec4(sphereColor, 1.0f); }
|