Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HW5 Solution #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ doc/html
./vscode

.DS_Store


.idea
cmake-build-debug
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
**Dealine**: 26.11.2020

Please put your name here:
**Name:** .......
**Name:** Otmane Sabir
## Problem 1
### Supersampling (Points 10 + 10 + 10)
In this assignment we will concentrate on stochastic ray-tracin and start with developing samplers, which generate random samples covering a unit square area.
Expand Down
Binary file added render/CSamplerRandom.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/CSamplerRegular.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/CSamplerStratified.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/Glossy00.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/Glossy05.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/Glossy1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added render/areaLight.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 12 additions & 2 deletions src/LightArea.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,17 @@ class CLightArea : public CLightOmni

virtual std::optional<Vec3f> illuminate(Ray& ray) override
{
// --- PUT YOUR CODE HERE ---
return std::nullopt;
m_sampleIdx = m_sampleIdx < m_pSampler->getNumSamples() ? m_sampleIdx++ : 0;
Vec2f sample = m_pSampler->getSample(m_sampleIdx);
Vec3f coords = m_org + sample[0] * m_edge1 + sample[1] * m_edge2;
CLightOmni::setOrigin(coords);
auto res = CLightOmni::illuminate(ray);
double cos_n = -ray.dir.dot(m_normal) / ray.t;
if (res.has_value() && cos_n > 0)
{
return m_area * cos_n * res.value();
}
return std::nullopt;
}
virtual size_t getNumSamples(void) const override { return m_pSampler->getNumSamples(); }

Expand All @@ -57,4 +66,5 @@ class CLightArea : public CLightOmni
double m_area; ///< Area of the light source
Vec3f m_normal; ///< Normal to the light source surface
ptr_sampler_t m_pSampler; ///< Pointer to the sampler ref @ref CSampler
size_t m_sampleIdx = -1; ///< Sample Index
};
5 changes: 2 additions & 3 deletions src/SamplerRandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ class CSamplerRandom : public CSampler {
virtual ~CSamplerRandom(void) = default;

virtual Vec2f getSample(size_t) const override
{
// --- PUT YOUR CODE HERE ---
return Vec2f::all(0.5f);
{
return Vec2f::all(Random::U<float>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here both components will be initialized with the same random number. U() method will be called only once.

}
};
9 changes: 6 additions & 3 deletions src/SamplerRegular.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ class CSamplerRegular : public CSampler
virtual ~CSamplerRegular(void) = default;

virtual Vec2f getSample(size_t s) const
{
// --- PUT YOUR CODE HERE ---
return Vec2f::all(0.5f);
{
size_t n = sqrt(this->getNumSamples());
// get i, j from row major format
float i = (s % getNumSamples()) + 0.5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In such case I will be equal to 0 all the time, you need to use n here

float j = (s / n + 0.5);
return Vec2f(j / n, i / n);
}
};
7 changes: 5 additions & 2 deletions src/SamplerStratified.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ class CSamplerStratified : public CSampler {

virtual Vec2f getSample(size_t s) const
{
// --- PUT YOUR CODE HERE ---
return Vec2f::all(0.5f);
auto rd = Random::U<float>();
size_t n = sqrt(this->getNumSamples());
float i = s % getNumSamples();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same error is here

float j = (float)s / n;
return Vec2f((j + rd) / n, (i + rd) / n);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rd should be different

}

};
62 changes: 48 additions & 14 deletions src/ShaderGlossy.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,57 @@ class CShaderGlossy : public CShaderPhong {
virtual ~CShaderGlossy(void) = default;

virtual Vec3f shade(const Ray& ray) const override {
Vec3f res = CShaderPhong::shade(ray);

Vec3f normal = ray.hit->getNormal(ray); // shading normal

// --- PUT YOUR CODE HERE ---

Ray reflected;
reflected.org = ray.org + ray.dir * ray.t;
reflected.dir = normalize(ray.dir - 2 * normal.dot(ray.dir) * normal);

Vec3f reflection = m_scene.RayTrace(reflected);

res = 0.5 * res + 0.5 * reflection;

return res;
// shading normal
int nSamples = m_pSampler->getNumSamples();
Vec3f agg = Vec3f::all(0);
Vec3f res = CShaderPhong::shade(ray);
Vec3f normal = ray.hit->getNormal(ray);
int k = 0;
for(int i = 0; i < nSamples; i++) {
// deep copy of normal.
auto normalCpy = Vec3f(normal);
Vec2f sample = m_pSampler -> getSample(i);
auto res2 = cwsReflection(sample, normalCpy, ray, nSamples);
if (res2.has_value())
{
k++;
agg += res2.value() * m_glossiness;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is a mis-use go the glossiness effect. This implementation just makes glossiness to vanish, but the m_glossiness parameter should modulate how much the normal is deviated - thus, for m_glossiness close to 1, the samples should be concentrated on top of the hemisphere, whereas for small m_glossiness close to 0, the samples should be equally distributed over the hemisphere

}
}
res = res*0.5 + agg / k * 0.5;
return res;
}

protected:
[[nodiscard]] std::optional<Vec3f> cwsReflection(const Vec2f& sample, const Vec3f& normal, const Ray& ray, int n) const
{
Vec2f disc;
Vec2f s = 2 * sample - Vec2f::all(1);
if (s[0] == 0 && s[1] == 0)
disc = Vec2f::all(0);
float theta, r;
if (fabs(s[0]) > fabs(s[1])) {
r = s[0];
theta = 0.25f * Pif * s[1] / r;
} else {
r = s[1];
theta = 0.5f * Pif - 0.25f * Pif * s[0] / r;
}
auto rA = normalize((Vec3f(0, 0, 1) + normal) / 2);
float x = r * cosf(theta);
float y = r * sinf(theta);
s = Vec2f(x, y);
float z = sqrtf(max(0.0f, 1.0f - s[0] * s[0] - s[1] * s[1]));
auto nS = Vec3f(s[0], s[1], z);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You derive nS, but never use it. It should be used instead of the normal. m_glossiness should also participate in the derivation of the nS. For example, for glossiness close to 1, you can divide x and y parameters by a large number, etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the code above is not in use

Ray reflected;
reflected.org = ray.org + ray.dir * ray.t;
reflected.dir = normalize(ray.dir - 2 * normal.dot(ray.dir) * normal);
if (reflected.dir.dot(normal) < Epsilon)
return std::nullopt;
return m_scene.RayTrace(reflected);
};

private:
float m_glossiness; ///< 1 - perfect mirror, 0.01 - fully diffuse
ptr_sampler_t m_pSampler; ///< Pointer to the sampler ref @ref CSampler
Expand Down
43 changes: 25 additions & 18 deletions src/ShaderPhong.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,35 @@ class CShaderPhong : public CShaderFlat
shadow.org = ray.org + ray.t * ray.dir;

// iterate over all light sources
for (auto pLight : m_scene.getLights()) {
for (const auto& pLight : m_scene.getLights()) {
// get direction to light, and intensity
// --- PUT YOUR CODE HERE ---
std::optional<Vec3f> lightIntensity = pLight->illuminate(shadow);
if (lightIntensity) {
// diffuse term
float cosLightNormal = shadow.dir.dot(normal);
if (cosLightNormal > 0) {
if (m_scene.occluded(shadow))
continue;
// I thought that we can maybe move this loop inside of the illuminate
// function that way it would also go over all the light samples instead of relying
// on the recommended size but I was worried this wouldn't comply with the hw task
// so I stuck to this.
for (int i = 0; i < pLight->getNumSamples(); i++)
{
std::optional<Vec3f> lightIntensity = pLight->illuminate(shadow);
if (lightIntensity) {
// diffuse term
float cosLightNormal = shadow.dir.dot(normal);
if (cosLightNormal > 0) {
if (m_scene.occluded(shadow))
continue;

Vec3f diffuseColor = m_kd * color;
res += (diffuseColor * cosLightNormal).mul(lightIntensity.value());
}
Vec3f diffuseColor = m_kd * color;
res += (diffuseColor * cosLightNormal).mul(lightIntensity.value());
}

// specular term
float cosLightReflect = shadow.dir.dot(reflect);
if (cosLightReflect > 0) {
Vec3f specularColor = m_ks * RGB(1, 1, 1); // white highlight;
res += (specularColor * powf(cosLightReflect, m_ke)).mul(lightIntensity.value());
}
// specular term
float cosLightReflect = shadow.dir.dot(reflect);
if (cosLightReflect > 0) {
Vec3f specularColor = m_ks * RGB(1, 1, 1); // white highlight;
res += (specularColor * powf(cosLightReflect, m_ke)).mul(lightIntensity.value());
}
}
}
res /= (float)pLight->getNumSamples();
}

for (int i = 0; i < 3; i++)
Expand Down
26 changes: 13 additions & 13 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,21 @@ Mat RenderFrame(void)
const float t = 100; // texture size of the chess board

// --- Problem 2 ---
//scene.add(std::make_shared<CCameraPerspective>(resolution, Vec3f(0, 30.0f, 30.0f), normalize(Vec3f(0, -0.9f, -1)), Vec3f(0, 1, 0), 30.0f));
scene.add(std::make_shared<CCameraPerspective>(resolution, Vec3f(0, 30.0f, 30.0f), normalize(Vec3f(0, -0.9f, -1)), Vec3f(0, 1, 0), 30.0f));
//
//auto pAreaLightSampler = std::make_shared<CSamplerRandom>(3);
//auto pAreaLight = std::make_shared<CLightArea>(Vec3f::all(400), Vec3f(15, 32, 1), Vec3f(-15, 32, 1), Vec3f(-15, 32, -1), Vec3f(15, 32, -1), pAreaLightSampler);
//scene.add(pAreaLight);

//pShaderFloor = std::make_shared<CShaderPhong>(scene, Vec3f::all(1), 0.1f, 0.9f, 0.0f, 40.0f);
//auto pShaderDragon = std::make_shared<CShaderPhong>(scene, RGB(0.153f, 0.682f, 0.376f), 0.2f, 0.8f, 0.5f, 40.0f);
//CSolid dragon(pShaderDragon, dataPath + "Stanford Dragon.obj");
//scene.add(dragon);
auto pAreaLightSampler = std::make_shared<CSamplerRandom>(3);
auto pAreaLight = std::make_shared<CLightArea>(Vec3f::all(400), Vec3f(15, 32, 1), Vec3f(-15, 32, 1), Vec3f(-15, 32, -1), Vec3f(15, 32, -1), pAreaLightSampler);
scene.add(pAreaLight);

pShaderFloor = std::make_shared<CShaderPhong>(scene, Vec3f::all(1), 0.1f, 0.9f, 0.0f, 40.0f);
auto pShaderDragon = std::make_shared<CShaderPhong>(scene, RGB(0.153f, 0.682f, 0.376f), 0.2f, 0.8f, 0.5f, 40.0f);
CSolid dragon(pShaderDragon, "/Users/otmanesabir/Desktop/S5/CG/solutions/eyden-tracer-05/data/Stanford Dragon.obj");
scene.add(dragon);
// --- ------- - ---

// --- Problem 3 ---
//auto pGlossinessSampler = std::make_shared<CSamplerRandom>(3);
//pShaderFloor = std::make_shared<CShaderGlossy>(scene, Vec3f::all(1), 0.1f, 0.9f, 0.0f, 40.0f, 0.5f, pGlossinessSampler);
//auto pGlossinessSampler = std::make_shared<CSamplerRegular>(3);
//pShaderFloor = std::make_shared<CShaderGlossy>(scene, Vec3f::all(1), 0.1f, 0.9f, 0.0f, 40.0f, 1.0f, pGlossinessSampler);
// --- ------- - ---

CSolidQuad floor(pShaderFloor, Vec3f(-s, 0, -s), Vec3f(-s, 0, s), Vec3f(s, 0, s), Vec3f(s, 0, -s), Vec2f(0, 0), Vec2f(t, 0), Vec2f(t, t), Vec2f(0, t));
Expand All @@ -84,7 +84,7 @@ Mat RenderFrame(void)
scene.buildAccelStructure(30, 3);

// Sampler
auto pPixelSampler = std::make_shared<CSampler>(2);
auto pPixelSampler = std::make_shared<CSamplerRegular>(2);

Mat img(resolution, CV_32FC3); // image array
size_t nSamples = pPixelSampler->getNumSamples();
Expand Down Expand Up @@ -115,6 +115,6 @@ int main(int argc, char* argv[])
DirectGraphicalModels::Timer::stop();
imshow("Image", img);
waitKey();
imwrite("image.jpg", img);
imwrite("Glossy1.jpg", img);
return 0;
}