From 57a1be7924fc7d5cbad6af50d2b473c2393c69e0 Mon Sep 17 00:00:00 2001 From: Mikhail Romanko Date: Sat, 4 Jul 2026 18:10:01 +0300 Subject: [PATCH] Simplify code of the raytracer demo --- examples/demo.c | 124 ++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/examples/demo.c b/examples/demo.c index 8904039..40c68a6 100644 --- a/examples/demo.c +++ b/examples/demo.c @@ -1,12 +1,10 @@ -#include #include +#include +#include #include "CgeMath.h" #define WIDTH 640 #define HEIGHT 480 -#define BG_R 0.05f -#define BG_G 0.05f -#define BG_B 0.1f #define MAX_BOUNCES 7 static int toInt(float x) { @@ -22,6 +20,7 @@ typedef struct { float specular; } Sphere; +static const float bg[3] = {0.05f, 0.05f, 0.1f}; static const float red[3] = {1.0f, 0.0f, 0.0f}; static const float green[3] = {0.0f, 1.0f, 0.0f}; static const float blue[3] = {0.0f, 0.0f, 1.0f}; @@ -41,75 +40,63 @@ int traceRay(const float origin[3], const float direction[3], float *t, int *hitIndex, float hitPoint[3], float normal[3]) { float t0, closest; float p[3]; - int i, hit; - - closest = 1e10f; - hit = -1; + int i; + closest = 1.0 / 0.0; + *hitIndex = -1; for (i = 0; i < numSpheres; i++) { - if (CgeRay3fIntersectSphere(origin, direction, spheres[i].center, spheres[i].radius, &t0, p) == 1) { + if (CgeRay3fIntersectSphere(origin, direction, spheres[i].center, spheres[i].radius, &t0, p)) { if (t0 > 0.001f && t0 < closest) { closest = t0; - hit = i; - CgeVec3fSub(p, spheres[i].center, normal); + *t = t0; + *hitIndex = i; + + memcpy(hitPoint, p, sizeof(p)); + CgeVec3fSub(hitPoint, spheres[i].center, normal); CgeVec3fNormal(normal, normal); } } } - if (direction[1] != 0.0f) { - float tPlane; - tPlane = (-1.0f - origin[1]) / direction[1]; - if (tPlane > 0.001f && tPlane < closest) { - closest = tPlane; - hit = -2; - } - } + t0 = (-1.0f - origin[1]) / direction[1]; + if (t0 > 0.001f && t0 < closest) { + closest = t0; + *t = t0; + *hitIndex = -2; - if (closest == 1e10f) { - return -1; - } - - *t = closest; - *hitIndex = hit; - - hitPoint[0] = origin[0] + closest * direction[0]; - hitPoint[1] = origin[1] + closest * direction[1]; - hitPoint[2] = origin[2] + closest * direction[2]; - - if (hit >= 0) { - CgeVec3fSub(hitPoint, spheres[hit].center, normal); - CgeVec3fNormal(normal, normal); - } else if (hit == -2) { + CgeVec3fScale(direction, closest, hitPoint); + CgeVec3fAdd(origin, hitPoint, hitPoint); normal[0] = 0.0f; normal[1] = 1.0f; normal[2] = 0.0f; } - return 1; + return *hitIndex != -1; } void traceColor(const float origin[3], const float direction[3], float color[3], int depth) { - float viewDir[3], halfVec[3], reflectDir[3], offset[3], reflectOrigin[3]; - float hitPoint[3], normal[3], localColor[3], reflectColor[3]; - float toLight[3], lightDir[3], dummyPoint[3], dummyNormal[3]; - float t, NdotL, diffuse, specular, brightness, tile, NdotH, reflectivity; - float shadow, tShadow; - const float *surf; - int hitIndex, dummyIdx, ix, iz; + float normal[3], hitPoint[3]; + float t; + int hitIndex; if (depth >= MAX_BOUNCES) { color[0] = color[1] = color[2] = 0.0f; return; } - if (traceRay(origin, direction, &t, &hitIndex, hitPoint, normal) >= 0) { + if (traceRay(origin, direction, &t, &hitIndex, hitPoint, normal)) { + float localColor[3], toLight[3], lightDir[3]; + float dummyPoint[3], dummyNormal[3]; + float NdotL, diffuse, specular, brightness, reflectivity; + float shadow; + int dummyIdx; + CgeVec3fSub(lightPos, hitPoint, toLight); CgeVec3fNormal(toLight, lightDir); shadow = 1.0f; - if (traceRay(hitPoint, lightDir, &tShadow, &dummyIdx, dummyPoint, dummyNormal) >= 0) { + if (traceRay(hitPoint, lightDir, &t, &dummyIdx, dummyPoint, dummyNormal)) { float lightDist = CgeVec3fDistance(lightPos, hitPoint); - if (tShadow < lightDist) { + if (t < lightDist) { shadow = 0.0f; } } @@ -119,6 +106,9 @@ void traceColor(const float origin[3], const float direction[3], float color[3], specular = 0.0f; if (hitIndex >= 0 && NdotL > 0.0f) { + float viewDir[3], halfVec[3]; + float NdotH; + CgeVec3fSub(origin, hitPoint, viewDir); CgeVec3fNormal(viewDir, viewDir); @@ -126,72 +116,62 @@ void traceColor(const float origin[3], const float direction[3], float color[3], CgeVec3fNormal(halfVec, halfVec); NdotH = CgeVec3fDot(normal, halfVec); - if (NdotH > 0.0f) { + if (NdotH > 0.0f) specular = powf(NdotH, spheres[hitIndex].shininess) * spheres[hitIndex].specular; - } } brightness = ambient + diffuse * shadow + specular * shadow; if (hitIndex == -2) { + float tile; + int ix, iz; + ix = (int)floorf(hitPoint[0]); iz = (int)floorf(hitPoint[2]); tile = ((ix + iz) % 2 == 0) ? 1.0f : 0.3f; localColor[0] = localColor[1] = localColor[2] = tile * brightness; } else { - surf = spheres[hitIndex].color; - localColor[0] = surf[0] * brightness; - localColor[1] = surf[1] * brightness; - localColor[2] = surf[2] * brightness; + CgeVec3fScale(spheres[hitIndex].color, brightness, localColor); } reflectivity = (hitIndex >= 0) ? spheres[hitIndex].reflectivity : 0.0f; if (reflectivity > 0.0f) { + float reflectDir[3], offset[3], reflectOrigin[3], reflectColor[3]; + CgeVec3fReflect(direction, normal, reflectDir); CgeVec3fScale(reflectDir, 0.001f, offset); CgeVec3fAdd(hitPoint, offset, reflectOrigin); traceColor(reflectOrigin, reflectDir, reflectColor, depth + 1); - localColor[0] = localColor[0] * (1.0f - reflectivity) + reflectColor[0] * reflectivity; - localColor[1] = localColor[1] * (1.0f - reflectivity) + reflectColor[1] * reflectivity; - localColor[2] = localColor[2] * (1.0f - reflectivity) + reflectColor[2] * reflectivity; + CgeVec3fScale(localColor, (1.0f - reflectivity), localColor); + CgeVec3fScale(reflectColor, reflectivity, reflectColor); + CgeVec3fAdd(localColor, reflectColor, localColor); } - color[0] = localColor[0]; - color[1] = localColor[1]; - color[2] = localColor[2]; + memcpy(color, localColor, sizeof(localColor)); } else { - color[0] = BG_R; - color[1] = BG_G; - color[2] = BG_B; + memcpy(color, bg, sizeof(bg)); } } int main() { int x, y; - float u, v, aspect, fov; + float aspect; float direction[3], color[3]; printf("P3\n%d %d\n255\n", WIDTH, HEIGHT); - aspect = (float)WIDTH / (float)HEIGHT; - fov = 1.0f; for (y = 0; y < HEIGHT; y++) { for (x = 0; x < WIDTH; x++) { - u = (2.0f * (x + 0.5f) / (float)WIDTH - 1.0f) * aspect; - v = (2.0f * (HEIGHT - y - 0.5f) / (float)HEIGHT - 1.0f); + direction[0] = (2.0f * (x + 0.5f) / (float)WIDTH - 1.0f) * aspect; + direction[1] = (2.0f * (HEIGHT - y - 0.5f) / (float)HEIGHT - 1.0f); + direction[2] = -1.0; - direction[0] = u; - direction[1] = v; - direction[2] = -fov; CgeVec3fNormal(direction, direction); traceColor(origin, direction, color, 0); - - if (color[0] < 0.0f) color[0] = 0.0f; else if (color[0] > 1.0f) color[0] = 1.0f; - if (color[1] < 0.0f) color[1] = 0.0f; else if (color[1] > 1.0f) color[1] = 1.0f; - if (color[2] < 0.0f) color[2] = 0.0f; else if (color[2] > 1.0f) color[2] = 1.0f; + CgeVec3fClamp(color, 0.0f, 1.0f, color); color[0] = powf(color[0], 1.0f / 2.2f); color[1] = powf(color[1], 1.0f / 2.2f);