146 lines
5.2 KiB
C
146 lines
5.2 KiB
C
#include <stdlib.h>
|
|
#include "structs.h"
|
|
#include "collision.h"
|
|
#include "vectorOp.h"
|
|
#define MAXOBJECTS 100
|
|
#define BADPOINT (vec3){-10000000,-10000000,-10000000}
|
|
#include "helper.h"
|
|
#include <math.h>
|
|
#define epsilon 1e-8
|
|
#define lightBounces 3
|
|
enum objectType {
|
|
SPHERETYPE,
|
|
QUADTYPE
|
|
};
|
|
|
|
RGBA getRayColor(RGBA colorList[], bool isLightList[]) {
|
|
int firstLightHitIndex = -1;
|
|
RGBA rayColor = {1,1,1,1};
|
|
for (int i = 0; i <= lightBounces; i++) {
|
|
if (isLightList[i] == 1) {
|
|
firstLightHitIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (firstLightHitIndex == -1) {
|
|
rayColor = (RGBA){0,0,0,1};
|
|
}
|
|
else
|
|
{
|
|
//pixel.r += spheresHitList[firstLightHitIndex]->color.r;
|
|
//pixel.g += spheresHitList[firstLightHitIndex]->color.g;
|
|
//pixel.b += spheresHitList[firstLightHitIndex]->color.b;
|
|
//pixel.a += spheresHitList[firstLightHitIndex]->color.a;
|
|
for (int i = firstLightHitIndex; i >= 0; i--) {
|
|
rayColor.r = rayColor.r * colorList[i].r;
|
|
rayColor.g = rayColor.g * colorList[i].g;
|
|
rayColor.b = rayColor.b * colorList[i].b;
|
|
//rayColor.a = rayColor.a * colorList[i].a;
|
|
}
|
|
|
|
//pixel.r = -vec3Product(sphereNormal, lightray->direction);
|
|
//pixel = (RGBA){1 - 0.5 *( sphereNormal.x + 1), 1 - 0.5 * (sphereNormal.y +1), 1 -0.5* (sphereNormal.z + 1),1};
|
|
|
|
return rayColor;
|
|
}
|
|
}
|
|
|
|
RGBA raytrace(object objectList[], int objectCount, ray *lightray) {
|
|
RGBA objectColorList[lightBounces + 1] = {0};
|
|
object objectHitList[lightBounces + 1] = {0};
|
|
bool isLightList[lightBounces + 1] = {false};
|
|
|
|
for (int j = 0; j <= lightBounces; j++) {
|
|
object currentObject;
|
|
object *nearestObject = nullptr;
|
|
double nearestObjectDistance = 10000000;
|
|
vec3 nearestCollisionPoint = (vec3){10000,10000,10000};
|
|
double nearestCollisionPointDistance = 10000000;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < objectCount; i++) {
|
|
currentObject = objectList[i];
|
|
vec3 collisionPoint;
|
|
|
|
switch (currentObject.objectType) {
|
|
case SPHERETYPE:
|
|
collisionPoint = collisionPointSphere(lightray, (sphere*)(objectList[i].objectPointer));
|
|
break;
|
|
case QUADTYPE:
|
|
collisionPoint = collisionQuad(lightray, (quad*)(objectList[i].objectPointer));
|
|
break;
|
|
}
|
|
|
|
double collisionPointDistance = 1000000;
|
|
if (collisionPoint.x != BADPOINT.x) {
|
|
collisionPointDistance = vec3Length(vec3Subtract(collisionPoint, lightray->origin));
|
|
if (collisionPointDistance < nearestCollisionPointDistance) {
|
|
nearestCollisionPoint = collisionPoint;
|
|
nearestCollisionPointDistance = collisionPointDistance;
|
|
nearestObject = &(objectList[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
vec3 objectNormal = BADPOINT;
|
|
if (nearestObject != nullptr) {
|
|
switch (nearestObject->objectType) {
|
|
case SPHERETYPE:
|
|
sphere *nearestSphere = (sphere*)(nearestObject->objectPointer);
|
|
objectColorList[j] = nearestSphere->color;
|
|
objectNormal = vec3Scale(vec3Subtract(nearestCollisionPoint, nearestSphere->origin), 1/(nearestSphere->radius));////////////////////////////// optimize, schreibe divide vector funktion
|
|
break;
|
|
case QUADTYPE:
|
|
quad *nearestQuad = (quad*)(nearestObject->objectPointer);
|
|
objectColorList[j] = nearestQuad->color;
|
|
objectNormal = nearestQuad->normal;
|
|
break;
|
|
}
|
|
objectHitList[j] = *nearestObject;
|
|
isLightList[j] = nearestObject->isLight;
|
|
|
|
//diffus:
|
|
lightray->direction = vec3Normalize(vec3Add(objectNormal, randUnitVector())); //maybe kann man sich durch umstrukturierung das normalisieren einsparen
|
|
if (fabs(lightray->direction.x ) <= epsilon || fabs(lightray->direction.y ) <= epsilon || fabs(lightray->direction.z) <= epsilon) {
|
|
lightray->direction = objectNormal;
|
|
}
|
|
//reflektion:
|
|
//lightray->direction = vec3Add(lightray->direction, vec3Scale(sphereNormal, 2));
|
|
lightray->origin = nearestCollisionPoint;
|
|
}
|
|
}
|
|
return getRayColor(objectColorList, isLightList);
|
|
|
|
}
|
|
|
|
|
|
RGBA getPixelColor(object objectList[], int objectCount, ray *lightray) {
|
|
RGBA pixel = (RGBA){0,0,0,0};
|
|
int raysPerPixel = 2;
|
|
ray originalRay = *lightray;
|
|
|
|
for (int k = 0; k < raysPerPixel; k++) {
|
|
*lightray = originalRay;
|
|
|
|
RGBA tempPixel = raytrace(objectList, objectCount, lightray);
|
|
|
|
pixel.r += tempPixel.r;
|
|
pixel.g += tempPixel.g;
|
|
pixel.b += tempPixel.b;
|
|
//pixel.a += tempPixel.a;
|
|
}
|
|
|
|
//average pixelData
|
|
pixel.r = pixel.r / raysPerPixel;
|
|
pixel.g = pixel.g / raysPerPixel;
|
|
pixel.b = pixel.b / raysPerPixel;
|
|
//pixel.a = pixel.a / raysPerPixel;
|
|
|
|
|
|
//free(spheresHitList);
|
|
//free(spheresNormalList);
|
|
return pixel;
|
|
} |