#include #include "structs.h" #include "collision.h" #include "vectorOp.h" #define MAXOBJECTS 100 #define BADPOINT (vec3){-10000000,-10000000,-10000000} #include "helper.h" #include #define epsilon 1e-8 #define RAYSPERPIXEL 400 #define lightBounces 16 #define GLOBALILLUMINATION 0.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){GLOBALILLUMINATION * colorList[0].r,GLOBALILLUMINATION * colorList[0].g,GLOBALILLUMINATION * colorList[0].b,1}; //rayColor = (RGBA){0,0,0,1}; //return rayColor; firstLightHitIndex = lightBounces - 1; isLightList[firstLightHitIndex] = 1; //colorList[firstLightHitIndex] = (RGBA){GLOBALILLUMINATION,GLOBALILLUMINATION,GLOBALILLUMINATION,1}; colorList[firstLightHitIndex] = (RGBA){0,0,0,1}; } //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}; 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; }