diff --git a/examples.c b/examples.c index d17a5aa..be88367 100644 --- a/examples.c +++ b/examples.c @@ -39,25 +39,24 @@ void exampleSphere( int width, int height, int channels, unsigned char **image) vec3 sphereOrigin = (vec3){0,-1.5,5}; double sphereRadius = 1.0; int objectCount = 7; - sphere obj1 = (sphere){sphereOrigin, sphereRadius,(RGBA){1,0.5,1,1},0}; - sphere **objectList = (sphere **) calloc(objectCount+1, sizeof(sphere*));; - objectList[0] = &obj1; - sphere obj2 = (sphere){vec3Add(sphereOrigin, (vec3){3,0,0}), sphereRadius, (RGBA){1,1,0.5,1},0}; - objectList[1] = &obj2; - sphere obj3 = (sphere){vec3Add(sphereOrigin, (vec3){-2,1,0}), sphereRadius, (RGBA){1,1,1,1},0}; - objectList[2] = &obj3; - sphere obj4 = (sphere){vec3Add(sphereOrigin, (vec3){1,1,3}), sphereRadius, (RGBA){0.5,1,1,1},0}; - objectList[3] = &obj4; - sphere light1 = (sphere){(vec3){1,1,4.5}, sphereRadius, (RGBA){1,1,1,1},1}; - objectList[4] = &light1; - sphere obj5 = (sphere){(vec3){0, -6, 6.5}, 5, (RGBA){1,0.2,0.6,1},0}; - objectList[5] = &obj5; - sphere light2 = (sphere){(vec3){1,-2,4}, sphereRadius, (RGBA){1,1,1,1},1}; - objectList[6] = &light2; + object objectList[objectCount]; + sphere obj1 = (sphere){sphereOrigin, sphereRadius,(RGBA){1,0.5,1,1}}; + objectList[0] = (object){0, &obj1, 0}; + sphere obj2 = (sphere){vec3Add(sphereOrigin, (vec3){3,0,0}), sphereRadius, (RGBA){1,1,0.5,1}}; + objectList[1] = (object){0, &obj2, 0}; + sphere obj3 = (sphere){vec3Add(sphereOrigin, (vec3){-2,1,0}), sphereRadius, (RGBA){1,1,1,1}}; + objectList[2] = (object){0, &obj3, 0}; + sphere obj4 = (sphere){vec3Add(sphereOrigin, (vec3){1,1,3}), sphereRadius, (RGBA){0.5,1,1,1}}; + objectList[3] = (object){0, &obj4, 0}; + sphere light1 = (sphere){(vec3){1,1,4.5}, sphereRadius, (RGBA){1,1,1,1}}; + objectList[4] = (object){0, &light1, 1}; + sphere obj5 = (sphere){(vec3){0, -6, 6.5}, 5, (RGBA){1,0.2,0.6,1}}; + objectList[5] = (object){0, &obj5, 0}; + sphere light2 = (sphere){(vec3){1,-2,4}, sphereRadius, (RGBA){1,1,1,1}}; + objectList[6] = (object){0, &light2, 1}; displaySzene(objectList, objectCount, cam1, width, height, channels, image); - free(objectList); } diff --git a/interface.c b/interface.c index 96b9932..8f5850e 100644 --- a/interface.c +++ b/interface.c @@ -10,7 +10,7 @@ #include #include "helper.h" -void displaySzene(sphere **objectList, int objectCount, camera cam1, int width, int height, int channels, unsigned char **image) { +void displaySzene(object objectList[], int objectCount, camera cam1, int width, int height, int channels, unsigned char **image) { const vec3 worldUp = (vec3){0, 1, 0}; vec3 screenX = vec3Cross(worldUp, cam1.direction); vec3 screenY = vec3Cross(screenX, cam1.direction); @@ -43,7 +43,7 @@ void displaySzene(sphere **objectList, int objectCount, camera cam1, int width, lightRay->direction = vec3Normalize(vec3Subtract(*pixelOrigin, cam1.origin)); - pixelColor = raytraceSphere(objectList, lightRay); + pixelColor = getPixelColor(objectList,objectCount, lightRay); free(pixelOrigin); free(lightRay); diff --git a/interface.h b/interface.h index e55b2c3..6a54300 100644 --- a/interface.h +++ b/interface.h @@ -1,4 +1,4 @@ #pragma once #include "structs.h" -void displaySzene(sphere **objectList, int objectCount, camera cam1, int width, int height, int channels, unsigned char **image); +void displaySzene(object objectList[], int objectCount, camera cam1, int width, int height, int channels, unsigned char **image); diff --git a/raytrace.c b/raytrace.c index 4733c68..77e6f19 100644 --- a/raytrace.c +++ b/raytrace.c @@ -2,156 +2,145 @@ #include "structs.h" #include "collision.h" #include "vectorOp.h" -#define MAXSPHERES 100 +#define MAXOBJECTS 100 +#define BADPOINT (vec3){-10000000,-10000000,-10000000} #include "helper.h" #include #define epsilon 1e-8 +#define lightBounces 3 +enum objectType { + SPHERETYPE, + QUADTYPE +}; -RGBA raytraceSphere(sphere **sphereList, int sphereCount, quad **quadList, int quadCount, ray *lightray) { +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 = ¤tObject; + } + } + } + + 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}; - #define lightBounces 3 - //sphere **spheresHitList = (sphere **)calloc( (lightBounces + 1),sizeof(sphere*) ); - //vec3 *spheresNormalList = (vec3 *)calloc( lightBounces + 1,sizeof(vec3) ); - int hitLightIndex = -1; - vec3 sphereNormal; - int raysPerPixel = 20; + int raysPerPixel = 2; ray originalRay = *lightray; for (int k = 0; k < raysPerPixel; k++) { - sphere *spheresHitList[lightBounces + 1] = {0}; - quad *quadHitList[lightBounces + 1] = {0}; - vec3 spheresNormalList[lightBounces + 1] = {0}; *lightray = originalRay; - RGBA tempPixel = (RGBA){1,1,1,1}; - sphere *nearestSphere = nullptr; - quad *nearestQuad = nullptr; - vec3 nearestCollisionPoint = {10000,10000,10000}; - RGBA objectColorList[lightBounces + 1] = {0}; + RGBA tempPixel = raytrace(objectList, objectCount, lightray); - for (int j = 0; j <= lightBounces; j++) { - nearestSphere = nullptr; - double nearestSphereDistance = 10000000; - nearestQuad = nullptr; - double nearestQuadDistance = 10000000; - nearestCollisionPoint = (vec3){10000,10000,10000}; - - for (int i = 0; i < sphereCount; i++) { - vec3 collisionPoint = collisionPointSphere(lightray, sphereList[i]); - double collisionPointDistance = 1000000; - if (collisionPoint.x == -10000000) { - - } - else{ - collisionPointDistance = vec3Length(vec3Subtract(collisionPoint, lightray->origin)); - if (collisionPointDistance < vec3Length(vec3Subtract(nearestCollisionPoint, lightray->origin))) { - nearestCollisionPoint = collisionPoint; - nearestSphere = sphereList[i]; - nearestSphereDistance = collisionPointDistance; - } - - } - } - - for (int i = 0; i < quadCount; i++) { - vec3 collisionPoint = collisionQuad(lightray, quadList[i]); - double collisionPointDistance = 1000000; - if (collisionPoint.x == -10000000) { - - } - else{ - collisionPointDistance = vec3Length(vec3Subtract(collisionPoint, lightray->origin)); - if (collisionPointDistance < vec3Length(vec3Subtract(nearestCollisionPoint, lightray->origin))) { - nearestCollisionPoint = collisionPoint; - nearestQuad = quadList[i]; - nearestQuadDistance = collisionPointDistance; - } - - } - } - if (nearestQuadDistance > nearestSphereDistance) { - if (nearestSphere != nullptr) { - objectColorList[j] = nearestSphere->color; - spheresHitList[j] = nearestSphere; - sphereNormal = vec3Scale(vec3Subtract(nearestCollisionPoint, nearestSphere->origin), 1/(nearestSphere->radius));////////////////////////////// optimize, schreibe divide vector funktion - spheresNormalList[j] = sphereNormal; - //diffus: - lightray->direction = vec3Add(sphereNormal, randUnitVector()); - if (fabs(lightray->direction.x ) <= epsilon || fabs(lightray->direction.y ) <= epsilon || fabs(lightray->direction.z) <= epsilon) { - lightray->direction = sphereNormal; - } - //reflektion: - //lightray->direction = vec3Add(lightray->direction, vec3Scale(sphereNormal, 2)); - lightray->origin = nearestCollisionPoint; - } - else { - sphereNormal = (vec3){1,1,1}; - } - } - else { - - if (nearestQuad != nullptr) { - objectColorList[j] = nearestQuad->color; - quadHitList[j] = nearestQuad; - //diffus: - lightray->direction = vec3Add(nearestQuad->normal, randUnitVector()); - if (fabs(lightray->direction.x ) <= epsilon || fabs(lightray->direction.y ) <= epsilon || fabs(lightray->direction.z) <= epsilon) { - lightray->direction = nearestQuad->normal; - } - //reflektion: - //lightray->direction = vec3Add(lightray->direction, vec3Scale(sphereNormal, 2)); - lightray->origin = nearestCollisionPoint; - } - else { - //sphereNormal = (vec3){1,1,1}; - } - } - - - - } - - int firstLightHitIndex = -1; - for (int i = 0; i <= lightBounces && spheresHitList[i] != nullptr; i++) { - if (spheresHitList[i]->isLight == 1) { - firstLightHitIndex = i; - break; - } - } - if (firstLightHitIndex == -1) { - tempPixel = (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--) { - tempPixel.r = tempPixel.r * spheresHitList[i]->color.r; - tempPixel.g = tempPixel.g * spheresHitList[i]->color.g; - tempPixel.b = tempPixel.b * spheresHitList[i]->color.b; - tempPixel.a = tempPixel.a * spheresHitList[i]->color.a; - } - pixel.r += tempPixel.r; - pixel.g += tempPixel.g; - pixel.b += tempPixel.b; - pixel.a += tempPixel.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}; - } + 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; + //pixel.a = pixel.a / raysPerPixel; //free(spheresHitList); //free(spheresNormalList); return pixel; - } \ No newline at end of file diff --git a/raytrace.h b/raytrace.h index cd49199..0da51c3 100644 --- a/raytrace.h +++ b/raytrace.h @@ -1,4 +1,8 @@ #pragma once #include "structs.h" -RGBA raytraceSphere(sphere **, ray *); +RGBA getPixelColor(object [], int, ray *); + +RGBA raytrace(object [], int, ray *); + +RGBA getRayColor(RGBA [], bool []); diff --git a/structs.h b/structs.h index c3095bb..2369b0a 100644 --- a/structs.h +++ b/structs.h @@ -32,7 +32,6 @@ struct sphere { vec3 origin; double radius; RGBA color; - int isLight; }; typedef struct sphere sphere; struct plane { @@ -46,5 +45,10 @@ struct quad { vec3 v2; vec3 normal; RGBA color; - int isLight; -}; typedef struct quad quad; \ No newline at end of file +}; typedef struct quad quad; + +struct object { + int objectType; // 0 = sphere, 1 = Quad + void *objectPointer; + bool isLight; +}; typedef struct object object; \ No newline at end of file diff --git a/test.png b/test.png index 26dd57a..a2c520a 100644 Binary files a/test.png and b/test.png differ