it does something
This commit is contained in:
+4
-4
@@ -10,8 +10,8 @@ int main()
|
|||||||
Window window(1920, 1080);
|
Window window(1920, 1080);
|
||||||
scene.startRender(
|
scene.startRender(
|
||||||
Camera{
|
Camera{
|
||||||
.position = glm::vec3(0, 10, 10),
|
.position = glm::vec3(5, 5, 5),
|
||||||
.direction = glm::vec3(0, -1, -1),
|
.direction = glm::vec3(-1, -1, -1),
|
||||||
},
|
},
|
||||||
RenderParameter{
|
RenderParameter{
|
||||||
.width = 1920,
|
.width = 1920,
|
||||||
@@ -25,8 +25,8 @@ int main()
|
|||||||
{
|
{
|
||||||
scene.startRender(
|
scene.startRender(
|
||||||
Camera{
|
Camera{
|
||||||
.position = glm::vec3(0, 10, 10),
|
.position = glm::vec3(5, 5, 5),
|
||||||
.direction = glm::vec3(0, -1, -1),
|
.direction = glm::vec3(-1, -1, -1),
|
||||||
},
|
},
|
||||||
RenderParameter{
|
RenderParameter{
|
||||||
.width = 1920,
|
.width = 1920,
|
||||||
|
|||||||
+11
-12
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
{
|
{
|
||||||
bvh.addPointLight(PointLight{
|
bvh.addDirectionalLight(DirectionalLight{
|
||||||
.position = glm::vec3(2, 0, 2),
|
.direction = glm::normalize(glm::vec3(-0.4f, -0.2f, -0.6f)),
|
||||||
.color = glm::vec3(0, 1, 0),
|
.color = glm::vec3(1, 1, 1),
|
||||||
});
|
});
|
||||||
bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"),
|
bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"),
|
||||||
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||||
@@ -40,6 +40,8 @@ glm::vec3 rand01(glm::uvec3 x)
|
|||||||
return glm::vec3(x) * (1.0f / float(0xffffffffU));
|
return glm::vec3(x) * (1.0f / float(0xffffffffU));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_local glm::vec3 rnd01;
|
||||||
|
|
||||||
void Renderer::render(Camera camera, RenderParameter params)
|
void Renderer::render(Camera camera, RenderParameter params)
|
||||||
{
|
{
|
||||||
for (int samp = 0; samp < params.numSamples; ++samp)
|
for (int samp = 0; samp < params.numSamples; ++samp)
|
||||||
@@ -64,8 +66,8 @@ void Renderer::render(Camera camera, RenderParameter params)
|
|||||||
|
|
||||||
//-- sample sensor
|
//-- sample sensor
|
||||||
glm::uvec2 pix = glm::uvec2(w, h);
|
glm::uvec2 pix = glm::uvec2(w, h);
|
||||||
glm::vec3 rnd1 = rand01(glm::uvec3(pix, samp));
|
rnd01 = rand01(glm::uvec3(pix, samp));
|
||||||
glm::vec2 rnd2 = 2.0f * glm::vec2(rnd1); // vvv tent filter sample
|
glm::vec2 rnd2 = 2.0f * glm::vec2(rnd01); // vvv tent filter sample
|
||||||
glm::vec2 tent =
|
glm::vec2 tent =
|
||||||
glm::vec2(rnd2.x < 1 ? sqrt(rnd2.x) - 1 : 1 - sqrt(2 - rnd2.x), rnd2.y < 1 ? sqrt(rnd2.y) - 1 : 1 - sqrt(2 - rnd2.y));
|
glm::vec2(rnd2.x < 1 ? sqrt(rnd2.x) - 1 : 1 - sqrt(2 - rnd2.x), rnd2.y < 1 ? sqrt(rnd2.y) - 1 : 1 - sqrt(2 - rnd2.y));
|
||||||
glm::vec2 s =
|
glm::vec2 s =
|
||||||
@@ -82,20 +84,17 @@ void Renderer::render(Camera camera, RenderParameter params)
|
|||||||
glm::vec3 lensX = glm::cross(lensN, glm::vec3(0, 1, 0)); // the exact vector doesnt matter
|
glm::vec3 lensX = glm::cross(lensN, glm::vec3(0, 1, 0)); // the exact vector doesnt matter
|
||||||
glm::vec3 lensY = glm::cross(lensN, lensX);
|
glm::vec3 lensY = glm::cross(lensN, lensX);
|
||||||
|
|
||||||
glm::vec3 lensSample = lensP + rnd1.x * camera.A * lensX + rnd1.y * camera.A * lensY;
|
glm::vec3 lensSample = lensP + rnd01.x * camera.A * lensX + rnd01.y * camera.A * lensY;
|
||||||
|
|
||||||
glm::vec3 focalPoint = cam.origin + (camera.S_O + S_I) * cam.direction;
|
glm::vec3 focalPoint = cam.origin + (camera.S_O + S_I) * cam.direction;
|
||||||
float t = glm::dot(focalPoint - r.origin, lensN) / glm::dot(r.direction, lensN);
|
float t = glm::dot(focalPoint - r.origin, lensN) / glm::dot(r.direction, lensN);
|
||||||
glm::vec3 focus = r.origin + t * r.direction;
|
glm::vec3 focus = r.origin + t * r.direction;
|
||||||
r = Ray(lensSample, normalize(focus - lensSample)); // TODO: Fix lens
|
r = Ray(lensSample, normalize(focus - lensSample)); // TODO: Fix lens
|
||||||
|
|
||||||
auto intersection = bvh.traceRay(r);
|
Payload payload;
|
||||||
|
bvh.traceRay(r, payload, 1e-4, 1e20);
|
||||||
|
|
||||||
if (intersection.has_value())
|
accumulator[w + h * params.width] += payload.accumulatedRadiance / float(params.numSamples);
|
||||||
{
|
|
||||||
|
|
||||||
accumulator[w + h * params.width] = intersection->shadingInfo.albedo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
co_return;
|
co_return;
|
||||||
}(w, samp));
|
}(w, samp));
|
||||||
|
|||||||
+132
-28
@@ -1,5 +1,6 @@
|
|||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <numbers>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
void Scene::addModel(PModel model, glm::mat4 transform)
|
void Scene::addModel(PModel model, glm::mat4 transform)
|
||||||
@@ -36,7 +37,8 @@ void Scene::generate()
|
|||||||
for (uint32_t i = 0; i < model->indices.size(); ++i)
|
for (uint32_t i = 0; i < model->indices.size(); ++i)
|
||||||
{
|
{
|
||||||
indicesPool.push_back(model->indices[i]);
|
indicesPool.push_back(model->indices[i]);
|
||||||
edgesPool.push_back(model->edges[i]);
|
edgesPool.push_back(model->edges[i * 2 + 0]);
|
||||||
|
edgesPool.push_back(model->edges[i * 2 + 1]);
|
||||||
faceNormalsPool.push_back(model->faceNormals[i]);
|
faceNormalsPool.push_back(model->faceNormals[i]);
|
||||||
}
|
}
|
||||||
pendingNodes.push_back(std::make_unique<Node>(model->boundingBox, ref));
|
pendingNodes.push_back(std::make_unique<Node>(model->boundingBox, ref));
|
||||||
@@ -73,9 +75,11 @@ void Scene::generate()
|
|||||||
hierarchy = std::move(pendingNodes[0]);
|
hierarchy = std::move(pendingNodes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IntersectionInfo> Scene::traceRay(Ray ray) const
|
extern glm::vec3 rnd01;
|
||||||
|
|
||||||
|
void Scene::traceRay(Ray ray, Payload& payload, const float tmin, const float tmax) const noexcept
|
||||||
{
|
{
|
||||||
auto results = generateIntersections(hierarchy, ray);
|
auto results = generateIntersections(hierarchy, ray, tmin, tmax);
|
||||||
float closestT = std::numeric_limits<float>::max();
|
float closestT = std::numeric_limits<float>::max();
|
||||||
IntersectionInfo info;
|
IntersectionInfo info;
|
||||||
for (uint32_t i = 0; i < results.size(); ++i)
|
for (uint32_t i = 0; i < results.size(); ++i)
|
||||||
@@ -88,31 +92,85 @@ std::optional<IntersectionInfo> Scene::traceRay(Ray ray) const
|
|||||||
}
|
}
|
||||||
if (closestT < std::numeric_limits<float>::max())
|
if (closestT < std::numeric_limits<float>::max())
|
||||||
{
|
{
|
||||||
return info;
|
// russian roulette ray termination
|
||||||
|
float p = std::max(std::max(info.brdf.albedo.x, info.brdf.albedo.y), info.brdf.albedo.z);
|
||||||
|
if (payload.depth > 5)
|
||||||
|
{
|
||||||
|
if (rnd01.z >= p)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
payload.accumulatedMaterial /= p;
|
||||||
|
}
|
||||||
|
// emissive
|
||||||
|
payload.accumulatedRadiance += payload.accumulatedMaterial * info.brdf.emissive * payload.emissive;
|
||||||
|
payload.accumulatedMaterial *= info.brdf.albedo;
|
||||||
|
|
||||||
|
// direct lighting
|
||||||
|
for (const auto& d : directionalLights)
|
||||||
|
{
|
||||||
|
// if there is an intersection, the light is occluded so no lighting
|
||||||
|
if (!testIntersection(hierarchy, Ray(info.hitInfo.position, -d.direction), 1e-4, 1e20))
|
||||||
|
{
|
||||||
|
payload.accumulatedRadiance += info.brdf.evaluate(info.hitInfo, -ray.direction, d.direction, d.color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& p : pointLights)
|
||||||
|
{
|
||||||
|
glm::vec3 lightDir = p.position - info.hitInfo.position;
|
||||||
|
// if (!testIntersection(hierarchy, Ray(info.hitInfo.position, -lightDir), 1e-4, 1))
|
||||||
|
{
|
||||||
|
float d = glm::length(lightDir);
|
||||||
|
float illuminance = std::max(1 - d / p.attenuation, 0.0f);
|
||||||
|
|
||||||
|
payload.accumulatedRadiance += illuminance * info.brdf.evaluate(info.hitInfo, -ray.direction, lightDir, p.color);
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IntersectionInfo> Scene::generateIntersections(const PNode& currentNode, Ray ray) const
|
// TODO: Next Event Estimation for mesh lights
|
||||||
|
|
||||||
|
// indirect lighting
|
||||||
|
float r1 = 2 * std::numbers::pi * rnd01.x;
|
||||||
|
float r2 = rnd01.y;
|
||||||
|
float r2s = sqrt(r2);
|
||||||
|
glm::vec3 w = info.hitInfo.normalLight;
|
||||||
|
glm::vec3 u = glm::normalize(glm::cross(std::abs(w.x) > 0.1 ? glm::vec3(0, 1, 0) : glm::vec3(1, 0, 0), w));
|
||||||
|
glm::vec3 v = glm::cross(w, u);
|
||||||
|
ray = Ray(info.hitInfo.position, glm::normalize(u * cos(r1) * r2s + v * sin(r1) * r2s + w * sqrt(1 - r2)));
|
||||||
|
payload.emissive = 0;
|
||||||
|
payload.depth++;
|
||||||
|
traceRay(ray, payload, tmin, tmax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Scene::testIntersection(const PNode& currentNode, const Ray ray, const float tmin, float tmax) const noexcept
|
||||||
{
|
{
|
||||||
if (!currentNode->aabb.intersects(ray, 0, std::numeric_limits<float>::max()))
|
if (!currentNode->aabb.intersects(ray, tmin, tmax))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (currentNode->model.numIndices > 0)
|
||||||
|
{
|
||||||
|
return testModel(currentNode->model, ray, tmin, tmax);
|
||||||
|
}
|
||||||
|
auto leftResults = testIntersection(currentNode->left, ray, tmin, tmax);
|
||||||
|
auto rightResults = testIntersection(currentNode->right, ray, tmin, tmax);
|
||||||
|
|
||||||
|
return leftResults || rightResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IntersectionInfo> Scene::generateIntersections(const PNode& currentNode, const Ray ray, const float tmin,
|
||||||
|
float tmax) const noexcept
|
||||||
|
{
|
||||||
|
if (!currentNode->aabb.intersects(ray, tmin, tmax))
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
if (currentNode->model.numIndices > 0)
|
if (currentNode->model.numIndices > 0)
|
||||||
{
|
{
|
||||||
auto result = intersectModel(currentNode->model, ray);
|
return intersectModel(currentNode->model, ray, tmin, tmax);
|
||||||
if (result.has_value())
|
|
||||||
{
|
|
||||||
return {*result};
|
|
||||||
}
|
}
|
||||||
else
|
auto leftResults = generateIntersections(currentNode->left, ray, tmin, tmax);
|
||||||
{
|
auto rightResults = generateIntersections(currentNode->right, ray, tmin, tmax);
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto leftResults = generateIntersections(currentNode->left, ray);
|
|
||||||
auto rightResults = generateIntersections(currentNode->right, ray);
|
|
||||||
|
|
||||||
for (auto& it : rightResults)
|
for (auto& it : rightResults)
|
||||||
{
|
{
|
||||||
@@ -121,9 +179,8 @@ std::vector<IntersectionInfo> Scene::generateIntersections(const PNode& currentN
|
|||||||
return leftResults;
|
return leftResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<IntersectionInfo> Scene::intersectModel(const ModelReference& reference, const Ray ray) const
|
bool Scene::testModel(const ModelReference& reference, const Ray ray, const float tmin, float tmax) const noexcept
|
||||||
{
|
{
|
||||||
std::optional<IntersectionInfo> intersection = {};
|
|
||||||
float distance = 0;
|
float distance = 0;
|
||||||
|
|
||||||
for (size_t posIndex = 0, edgeIndex = 0, normalIndex = 0; posIndex < reference.numIndices; posIndex++, edgeIndex += 2, normalIndex++)
|
for (size_t posIndex = 0, edgeIndex = 0, normalIndex = 0; posIndex < reference.numIndices; posIndex++, edgeIndex += 2, normalIndex++)
|
||||||
@@ -163,29 +220,76 @@ std::optional<IntersectionInfo> Scene::intersectModel(const ModelReference& refe
|
|||||||
if (resultVector.z < 0 || resultVector.z > 1)
|
if (resultVector.z < 0 || resultVector.z > 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (resultVector.x < 1e-6)
|
if (resultVector.x < tmin || resultVector.x > tmax)
|
||||||
|
continue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::vector<IntersectionInfo> Scene::intersectModel(const ModelReference& reference, const Ray ray, const float tmin,
|
||||||
|
float tmax) const noexcept
|
||||||
|
{
|
||||||
|
std::vector<IntersectionInfo> intersection = {};
|
||||||
|
float distance = 0;
|
||||||
|
|
||||||
|
for (size_t posIndex = 0, edgeIndex = 0, normalIndex = 0; posIndex < reference.numIndices; posIndex++, edgeIndex += 2, normalIndex++)
|
||||||
|
{
|
||||||
|
const auto i0 = indicesPool[reference.indicesOffset + posIndex].x;
|
||||||
|
const auto i1 = indicesPool[reference.indicesOffset + posIndex].y;
|
||||||
|
const auto i2 = indicesPool[reference.indicesOffset + posIndex].z;
|
||||||
|
|
||||||
|
const auto& p0 = positionPool[reference.positionOffset + i0];
|
||||||
|
const auto& p1 = positionPool[reference.positionOffset + i1];
|
||||||
|
const auto& p2 = positionPool[reference.positionOffset + i2];
|
||||||
|
|
||||||
|
const auto& t0 = texCoordsPool[reference.positionOffset + i0];
|
||||||
|
const auto& t1 = texCoordsPool[reference.positionOffset + i1];
|
||||||
|
const auto& t2 = texCoordsPool[reference.positionOffset + i2];
|
||||||
|
|
||||||
|
const auto& e0 = edgesPool[reference.indicesOffset + edgeIndex];
|
||||||
|
const auto& e1 = edgesPool[reference.indicesOffset + edgeIndex + 1];
|
||||||
|
|
||||||
|
const auto& n = faceNormalsPool[reference.indicesOffset + normalIndex];
|
||||||
|
|
||||||
|
const auto s = ray.origin - p0;
|
||||||
|
const auto s1 = glm::cross(ray.direction, e1);
|
||||||
|
const auto s2 = glm::cross(s, e0);
|
||||||
|
|
||||||
|
const float fraction = 1.0f / glm::dot(s1, e0);
|
||||||
|
const auto resultVector = glm::vec3(glm::dot(s2, e1), glm::dot(s1, s), glm::dot(s2, ray.direction)) * fraction;
|
||||||
|
|
||||||
|
const float b3 = 1.0f - resultVector.y - resultVector.z;
|
||||||
|
|
||||||
|
const auto texCoords = t0 * resultVector.y + t1 * resultVector.z + t2 * b3;
|
||||||
|
|
||||||
|
if (b3 < 0 || b3 > 1)
|
||||||
|
continue;
|
||||||
|
if (resultVector.y < 0 || resultVector.y > 1)
|
||||||
|
continue;
|
||||||
|
if (resultVector.z < 0 || resultVector.z > 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!intersection.has_value() || resultVector.x < distance)
|
if (resultVector.x < tmin || resultVector.x > tmax)
|
||||||
{
|
continue;
|
||||||
intersection = IntersectionInfo{
|
|
||||||
|
intersection.push_back(IntersectionInfo{
|
||||||
.hitInfo =
|
.hitInfo =
|
||||||
{
|
{
|
||||||
.t = resultVector.x,
|
.t = resultVector.x,
|
||||||
.position = ray.origin + ray.direction * resultVector.x,
|
.position = ray.origin + ray.direction * resultVector.x,
|
||||||
.normal = n,
|
.normal = n,
|
||||||
|
.normalLight = n, // todo: flip based on something, idk what
|
||||||
.texCoords = texCoords,
|
.texCoords = texCoords,
|
||||||
},
|
},
|
||||||
.shadingInfo =
|
.brdf =
|
||||||
{
|
{
|
||||||
.albedo = glm::vec3(texCoords, 0.0f),
|
.albedo = glm::vec3(texCoords, 0.0f),
|
||||||
.emissive = glm::vec3(0.0f, 0.0f, 0.0f),
|
.emissive = glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
.type = MaterialType::DIFFUSE,
|
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
distance = resultVector.x;
|
distance = resultVector.x;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-10
@@ -15,27 +15,27 @@ struct ModelReference
|
|||||||
|
|
||||||
struct PointLight
|
struct PointLight
|
||||||
{
|
{
|
||||||
glm::vec3 position;
|
glm::vec3 position = glm::vec3(0, 0, 0);
|
||||||
glm::vec3 color;
|
glm::vec3 color = glm::vec3(1, 1, 1);
|
||||||
float attenuation;
|
float attenuation = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DirectionalLight
|
struct DirectionalLight
|
||||||
{
|
{
|
||||||
glm::vec3 direction;
|
glm::vec3 direction = glm::vec3(0, 1, 0);
|
||||||
glm::vec3 color;
|
glm::vec3 color = glm::vec3(1, 1, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Scene
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void addPointLight(PointLight point) { points.push_back(point); }
|
void addPointLight(PointLight point) { pointLights.push_back(point); }
|
||||||
void addDirectionalLight(DirectionalLight dir) { directionalLights.push_back(dir); }
|
void addDirectionalLight(DirectionalLight dir) { directionalLights.push_back(dir); }
|
||||||
void addModel(PModel model, glm::mat4 transform);
|
void addModel(PModel model, glm::mat4 transform);
|
||||||
void addModels(std::vector<PModel> models, glm::mat4 transform);
|
void addModels(std::vector<PModel> models, glm::mat4 transform);
|
||||||
void generate();
|
void generate();
|
||||||
|
|
||||||
std::optional<IntersectionInfo> traceRay(Ray ray) const;
|
void traceRay(Ray ray, Payload& payload, const float tmin, const float tmax) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<glm::vec3> positionPool;
|
std::vector<glm::vec3> positionPool;
|
||||||
@@ -44,7 +44,7 @@ private:
|
|||||||
std::vector<glm::vec3> edgesPool;
|
std::vector<glm::vec3> edgesPool;
|
||||||
std::vector<glm::vec3> faceNormalsPool;
|
std::vector<glm::vec3> faceNormalsPool;
|
||||||
|
|
||||||
std::vector<PointLight> points;
|
std::vector<PointLight> pointLights;
|
||||||
std::vector<DirectionalLight> directionalLights;
|
std::vector<DirectionalLight> directionalLights;
|
||||||
|
|
||||||
DECLARE_REF(Node)
|
DECLARE_REF(Node)
|
||||||
@@ -60,6 +60,9 @@ private:
|
|||||||
PNode hierarchy;
|
PNode hierarchy;
|
||||||
std::vector<PModel> models;
|
std::vector<PModel> models;
|
||||||
|
|
||||||
std::vector<IntersectionInfo> generateIntersections(const PNode& currentNode, Ray ray) const;
|
// tests if a ray intersects any geometry, no hit information, for shadow rays
|
||||||
std::optional<IntersectionInfo> intersectModel(const ModelReference& reference, Ray ray) const;
|
bool testIntersection(const PNode& currentNode, const Ray ray, const float tmin, const float tmax) const noexcept;
|
||||||
|
std::vector<IntersectionInfo> generateIntersections(const PNode& currentNode, const Ray ray, const float tmin, const float tmax) const noexcept;
|
||||||
|
bool testModel(const ModelReference& reference, const Ray ray, const float tmin, const float tmax) const noexcept;
|
||||||
|
std::vector<IntersectionInfo> intersectModel(const ModelReference& reference, const Ray ray, const float tmin, const float tmax) const noexcept;
|
||||||
};
|
};
|
||||||
+3
-1
@@ -1,7 +1,9 @@
|
|||||||
#include "BRDF.h"
|
#include "BRDF.h"
|
||||||
|
#include "Model.h"
|
||||||
|
|
||||||
glm::vec3 BlinnPhong::evaluate(HitInfo hit, glm::vec3 viewDir, glm::vec3 lightDir, glm::vec3 lightColor)
|
glm::vec3 BRDF::evaluate(HitInfo hit, glm::vec3 viewDir, glm::vec3 lightDir, glm::vec3 lightColor)
|
||||||
{
|
{
|
||||||
|
// todo: switch for materialtype, this is blinnphong
|
||||||
glm::vec3 normal = hit.normal;
|
glm::vec3 normal = hit.normal;
|
||||||
float diffuse = std::max(glm::dot(normal, lightDir), 0.0f);
|
float diffuse = std::max(glm::dot(normal, lightDir), 0.0f);
|
||||||
glm::vec3 h = glm::normalize(lightDir + viewDir);
|
glm::vec3 h = glm::normalize(lightDir + viewDir);
|
||||||
|
|||||||
+6
-5
@@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Material.h"
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class BRDF
|
enum class MaterialType
|
||||||
{
|
{
|
||||||
virtual glm::vec3 evaluate(HitInfo hit, glm::vec3 viewDir, glm::vec3 lightDir, glm::vec3 lightColor) = 0;
|
BlinnPhong
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlinnPhong : public BRDF
|
struct BRDF
|
||||||
{
|
{
|
||||||
glm::vec3 albedo = glm::vec3(1, 1, 1);
|
glm::vec3 albedo = glm::vec3(1, 1, 1);
|
||||||
float alpha = 1;
|
float alpha = 1;
|
||||||
glm::vec3 specularColor = glm::vec3(1, 1, 1);
|
glm::vec3 specularColor = glm::vec3(1, 1, 1);
|
||||||
float shininess = 0;
|
float shininess = 0;
|
||||||
glm::vec3 emissive = glm::vec3(0, 0, 0);
|
glm::vec3 emissive = glm::vec3(0, 0, 0);
|
||||||
virtual glm::vec3 evaluate(HitInfo hit, glm::vec3 viewDir, glm::vec3 lightDir, glm::vec3 lightColor);
|
MaterialType materialType;
|
||||||
|
glm::vec3 evaluate(struct HitInfo hit, glm::vec3 viewDir, glm::vec3 lightDir, glm::vec3 lightColor);
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
#include "Material.h"
|
#include "Material.h"
|
||||||
|
#include "BRDF.h"
|
||||||
|
|
||||||
std::unique_ptr<BRDF> Material::evaluate(HitInfo hitInfo)
|
BRDF Material::evaluate(HitInfo hitInfo)
|
||||||
{
|
{
|
||||||
return std::make_unique<BlinnPhong>();
|
return BRDF{
|
||||||
|
.albedo = glm::vec3(hitInfo.texCoords, 0),
|
||||||
|
.alpha = 1,
|
||||||
|
.emissive = glm::vec3(0, 0, 0),
|
||||||
|
.materialType = MaterialType::BlinnPhong,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-8
@@ -4,17 +4,10 @@
|
|||||||
#include "Ray.h"
|
#include "Ray.h"
|
||||||
#include "BRDF.h"
|
#include "BRDF.h"
|
||||||
|
|
||||||
enum class MaterialType
|
|
||||||
{
|
|
||||||
DIFFUSE,
|
|
||||||
SPECULAR,
|
|
||||||
REFRACTIVE,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Material
|
class Material
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<BRDF> evaluate(HitInfo hitInfo);
|
BRDF evaluate(HitInfo hitInfo);
|
||||||
PTexture albedoTexture;
|
PTexture albedoTexture;
|
||||||
PTexture emissiveTexture;
|
PTexture emissiveTexture;
|
||||||
};
|
};
|
||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
struct IntersectionInfo
|
struct IntersectionInfo
|
||||||
{
|
{
|
||||||
HitInfo hitInfo;
|
HitInfo hitInfo;
|
||||||
MaterialInfo shadingInfo;
|
BRDF brdf;
|
||||||
};
|
};
|
||||||
class Model
|
class Model
|
||||||
{
|
{
|
||||||
|
|||||||
+6
-3
@@ -4,15 +4,15 @@
|
|||||||
struct Payload
|
struct Payload
|
||||||
{
|
{
|
||||||
glm::vec3 accumulatedRadiance = glm::vec3(0);
|
glm::vec3 accumulatedRadiance = glm::vec3(0);
|
||||||
glm::vec3 accumulatedMaterial = glm::vec3(0);
|
glm::vec3 accumulatedMaterial = glm::vec3(1);
|
||||||
|
uint32_t depth = 0;
|
||||||
|
float emissive = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ray
|
struct Ray
|
||||||
{
|
{
|
||||||
glm::vec3 origin;
|
glm::vec3 origin;
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
uint32_t depth = 0;
|
|
||||||
Payload payload;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HitInfo
|
struct HitInfo
|
||||||
@@ -20,5 +20,8 @@ struct HitInfo
|
|||||||
float t;
|
float t;
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 normal;
|
glm::vec3 normal;
|
||||||
|
// not entirely sure what that does
|
||||||
|
// its the normal being flipped based on some dot product
|
||||||
|
glm::vec3 normalLight;
|
||||||
glm::vec2 texCoords;
|
glm::vec2 texCoords;
|
||||||
};
|
};
|
||||||
@@ -51,7 +51,7 @@ Window::Window(int width, int height) : width(width), height(height)
|
|||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
void main() { color = texture(tex, texcoords); });
|
void main() { color = texture(tex, vec2(texcoords.x, -texcoords.y)); });
|
||||||
glShaderSource(vertShader, 1, &vertCode, nullptr);
|
glShaderSource(vertShader, 1, &vertCode, nullptr);
|
||||||
glCompileShader(vertShader);
|
glCompileShader(vertShader);
|
||||||
int success;
|
int success;
|
||||||
|
|||||||
@@ -20,6 +20,5 @@ class Window
|
|||||||
GLuint program;
|
GLuint program;
|
||||||
GLuint vertShader;
|
GLuint vertShader;
|
||||||
GLuint fragShader;
|
GLuint fragShader;
|
||||||
GLuint textureLocation;
|
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user