First commit

This commit is contained in:
2026-10-11 19:01:42 +03:00
parent 35526d0f28
commit 52e5e6a73e
18 changed files with 9342 additions and 62 deletions
+322
View File
@@ -0,0 +1,322 @@
/************************************************************
Title : A Photo-realistic Renderer Based on Photon Mapping
Students : Davood Rasti
Alireza Rasti
Version : 0.01
Date : 23-06-2012
Updated : 01-10-2026
*************************************************************/
#pragma once
#include "./3rdparty/stb_collection/stb_image.h"
#include "vector3d.h"
#include <algorithm>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <vector>
namespace PRRPM
{
// Structures
struct Ray
{
Vector3d origin;
Vector3d direction;
int objectID;
ui32 objectType;
Vector3d intersectionPosition;
f32 distance;
};
struct Triangle
{
Vector3d point1;
Vector3d point2;
Vector3d point3;
Vector3d color;
Vector3d normal;
ui8 materialID;
};
struct Sphere
{
Vector3d position;
float radius;
Vector3d color;
ui32 numberOfSpheres;
ui8 materialID;
};
struct IntersectionPoint
{
Vector3d color;
Vector3d positionAndOrigin;
Vector3d normal;
Vector3d fluxAndDirection;
f32 radiusSquare;
i32 nubmerOfPhotonAndMaterialID;
int pixelIndex;
int cellID;
};
struct LightSource
{
ui8 type;
Vector3d position;
Vector3d intensity;
Vector3d size;
};
extern ui32 imageWidth;
extern ui32 imageHeight;
extern ui32 numberOfPhotons;
extern ui32 numberOfPhotonPass;
extern ui32 numberOfBounces;
inline constexpr f32 maxSceneDepth = 1000.0f;
inline constexpr f32 alpha = 0.7f;
extern std::string outFileName;
extern std::vector<Vector3d> imageBufferList;
extern bool isLightOn;
extern bool isPhotonMapping;
extern bool isGUI;
inline constexpr f32 refractiveIndexIn = 1.0f;
inline constexpr f32 refractiveIndexOut = 1.5f;
inline constexpr int gridSize = 16000000;
inline constexpr f32 irridianceRadiusSquare = 0.000016f;
inline constexpr int numberOfGridCell = 250;
inline constexpr int numberOfGridCellXY = 252;
inline constexpr int numberOfGridCellXMY = 63000;
extern Vector3d neighborsDirection[27];
extern std::vector<Triangle> triangleList;
extern std::vector<Sphere> sphereList;
extern std::vector<LightSource> lightSourcesList;
extern std::vector<IntersectionPoint> intersectionPointsList;
extern std::vector<IntersectionPoint> secondIntersectionPointsList;
extern std::vector<int> hastValueList;
inline bool compareByCellID(const IntersectionPoint& firstPoint,
const IntersectionPoint& secondPoint)
{
return (firstPoint.cellID < secondPoint.cellID);
}
inline bool compareByMetalID(const IntersectionPoint& firstPoint,
const IntersectionPoint& secondPoint)
{
return (firstPoint.nubmerOfPhotonAndMaterialID < secondPoint.nubmerOfPhotonAndMaterialID);
}
inline bool isCellIDOut(const IntersectionPoint& point)
{
return (point.cellID == -1);
}
inline bool isMetalIDOut(const IntersectionPoint& point)
{
return (point.nubmerOfPhotonAndMaterialID == -2);
}
inline int computeCellID(const Vector3d& position)
{
int x = (position.x + 0.6) * numberOfGridCell;
int y = (position.y + 0.6) * numberOfGridCell;
int z = (position.z - 1.0) * numberOfGridCell;
return (z * numberOfGridCellXMY + y * numberOfGridCellXY + x);
}
inline void generatePhotonRayFromLighSource(Ray* ray, const LightSource& lightSource,
std::default_random_engine& randomNumberGenerator)
{
std::uniform_real_distribution<f32> uniform(0.0, 1.0);
if (lightSource.type == 0)
{
f32 u = MathUtility::TwoPI * uniform(randomNumberGenerator);
f32 v = acosf(sqrtf(uniform(randomNumberGenerator))) * 2.0;
f32 w = sinf(v);
ray->direction = Vector3d(cosf(u) * w, cosf(v), sinf(u) * w);
ray->origin = lightSource.position;
}
else if (lightSource.type == 1)
{
std::uniform_real_distribution<f32> uniformX(-lightSource.size.x, lightSource.size.x);
std::uniform_real_distribution<f32> uniformZ(-lightSource.size.z, lightSource.size.z);
std::uniform_real_distribution<f32> uniformNP(-1.0, 1.0);
f32 u = uniform(randomNumberGenerator);
f32 v = MathUtility::TwoPI * uniform(randomNumberGenerator);
f32 uSquare = sqrtf(u);
f32 x = cosf(v) * uSquare;
f32 y = sin(v) * uSquare;
f32 z = sqrtf(1.0 - u);
ray->direction = Vector3d(x, -y, z * uniformNP(randomNumberGenerator));
ray->origin.x = uniformX(randomNumberGenerator);
ray->origin.y = 0;
ray->origin.z = uniformZ(randomNumberGenerator);
ray->origin = ray->origin + lightSource.position;
}
ray->direction.normalize();
}
inline void intersectTriangle(Ray* ray, unsigned int triangleIndex)
{
Vector3d edge1 = triangleList[triangleIndex].point2 - triangleList[triangleIndex].point1;
Vector3d edge2 = triangleList[triangleIndex].point3 - triangleList[triangleIndex].point1;
Vector3d pVector = ray->direction.cross(edge2);
f32 determinat = edge1.dot(pVector);
if (determinat < 0.000001)
return;
Vector3d tVector = ray->origin - triangleList[triangleIndex].point1;
f32 u = tVector.dot(pVector);
if (u < 0.0 || u > determinat)
return;
Vector3d qVector = tVector.cross(edge1);
f32 v = ray->direction.dot(qVector);
if (v < 0.0 || (u + v) > determinat)
return;
float inverseDeterminat = 1.0f / determinat;
float t = edge2.dot(qVector) * inverseDeterminat;
u *= inverseDeterminat;
v *= inverseDeterminat;
ray->distance = t;
ray->intersectionPosition = triangleList[triangleIndex].point1 + (edge1 * u) + (edge2 * v);
}
inline void intersectSphere(Ray* ray, unsigned int sphereIndex)
{
Vector3d dist = sphereList[sphereIndex].position - ray->origin;
f32 b = ray->direction.dot(dist);
f32 delta = b * b - dist.dot(dist) +
(sphereList[sphereIndex].radius * sphereList[sphereIndex].radius);
if (delta < 0.0f)
return;
f32 t0 = b - sqrt(delta);
f32 t1 = b + sqrt(delta);
f32 distance = maxSceneDepth;
if ((t0 > 0.001f) && (t0 < distance))
distance = t0;
else if ((t1 > 0.001f) && (t1 < distance))
distance = t1;
ray->distance = distance;
}
inline void intersectObjects(Ray* ray)
{
Ray tempRay;
tempRay.direction = ray->direction;
tempRay.origin = ray->origin;
tempRay.distance = maxSceneDepth;
ray->distance = maxSceneDepth;
for (unsigned int iTriangle = 0; iTriangle < triangleList.size(); ++iTriangle)
{
intersectTriangle(&tempRay, iTriangle);
if (tempRay.distance < ray->distance)
{
ray->intersectionPosition = tempRay.intersectionPosition;
ray->objectID = iTriangle;
ray->objectType = 0;
ray->distance = tempRay.distance;
}
}
tempRay.objectID = -1;
tempRay.distance = maxSceneDepth;
for (unsigned int iSphere = 0; iSphere < sphereList.size(); ++iSphere)
{
intersectSphere(&tempRay, iSphere);
if (tempRay.distance < ray->distance)
{
ray->objectID = iSphere;
ray->objectType = 1;
ray->distance = tempRay.distance;
ray->intersectionPosition = (ray->direction * ray->distance) + ray->origin;
}
}
}
inline Vector3d getSurfaceNormal(const Ray& ray)
{
Vector3d surfaceNormal;
if (ray.objectType == 0)
surfaceNormal = triangleList[ray.objectID].normal;
else
{
surfaceNormal = ray.intersectionPosition - sphereList[ray.objectID].position;
surfaceNormal.normalize();
}
return surfaceNormal;
}
inline Vector3d getObjectColor(ui32 objectID, ui32 objectType)
{
if (objectType == 0)
return triangleList[objectID].color;
else
return sphereList[objectID].color;
}
inline ui8 getObjectMaterial(ui32 objectID, ui32 objectType)
{
if (objectType == 0)
return triangleList[objectID].materialID;
else
return sphereList[objectID].materialID;
}
inline void calculateReflectionFractionDirection(Vector3d rayDirection, Vector3d normal,
Vector3d* reflectionDirection,
Vector3d* refractionDirection,
f32* cosOutAngle, f32* reflectionIntensity)
{
Vector3d secondNormal;
if (normal.dot(rayDirection) < 0)
secondNormal = normal;
else
secondNormal = normal * -1;
*reflectionDirection = rayDirection - normal * normal.dot(rayDirection) * 2.0f;
bool isRayGoingToObject = (normal.dot(secondNormal) > 0.0f);
f32 refractiveIndex = isRayGoingToObject ? refractiveIndexIn / refractiveIndexOut
: refractiveIndexOut / refractiveIndexIn;
f32 cosInAngle = rayDirection.dot(secondNormal);
*cosOutAngle = 1.0f - refractiveIndex * refractiveIndex * (1.0f - cosInAngle * cosInAngle);
if (*cosOutAngle >= 0)
{
*refractionDirection = rayDirection * refractiveIndex -
normal * ((isRayGoingToObject ? 1 : -1) *
(cosInAngle * refractiveIndex + sqrt(*cosOutAngle)));
refractionDirection->normalize();
f32 reflectivity = pow((refractiveIndex - 1), 2) / pow((refractiveIndex + 1), 2);
f32 angle = (isRayGoingToObject ? -cosInAngle : refractionDirection->dot(normal));
*reflectionIntensity = reflectivity + (1.0f - reflectivity) * pow((1.0f - angle), 5);
}
}
} // namespace PRRPM