C 光线跟踪器不根据方向提供不同的光强度

C 光线跟踪器不根据方向提供不同的光强度,c,graphics,geometry,raytracing,C,Graphics,Geometry,Raytracing,目标:我正在尝试用C创建一个光线跟踪器。我刚刚添加了一个光源,该光源应根据光线的位置为我的三个球体中的每个球体提供着色效果。如果灯光位于所有灯光的左侧,则应在右侧加上阴影 问题:当改变光的强度和位置时,所有球体都会均匀变化。球体的照明或多或少是相等的,球体上各个像素的照明没有变化 我的调试尝试:我尝试通过打印出许多不同的信息来查看变量输出,我认为源代码来自我的变量 diffuse_light_intensity 变化不大(在屏幕上的所有迭代过程中,由于表面上的光线角度变化很大,所以该值会经常变

目标:我正在尝试用C创建一个光线跟踪器。我刚刚添加了一个光源,该光源应根据光线的位置为我的三个球体中的每个球体提供着色效果。如果灯光位于所有灯光的左侧,则应在右侧加上阴影

问题:当改变光的强度和位置时,所有球体都会均匀变化。球体的照明或多或少是相等的,球体上各个像素的照明没有变化

我的调试尝试:我尝试通过打印出许多不同的信息来查看变量输出,我认为源代码来自我的变量

diffuse_light_intensity
变化不大(在屏幕上的所有迭代过程中,由于表面上的光线角度变化很大,所以该值会经常变化,但该值会变化两次)

我的代码:(我的理论是问题在于场景相交()或投射光线())

#包括
#包括
#包括
#包括
#包括
类型定义结构{
浮动位置[3];
漂浮强度;
}光;
类型定义结构{
浮动漫反射颜色[3];
}材料;
类型定义结构{
浮心[3];
浮动半径;
材料;
}球体;
int-arrSub(常量浮点arr1[],常量浮点arr2[],浮点子数组[],int-length){
/*
需要3个大小相同的阵列(表示为长度),
arr1-arr2将产生第三个阵列子阵列
*/
for(int i=0;is.radius*s.radius)返回false;//不存在交点,则返回false。
浮动thc=sqrtf((s.半径*s.半径-d2));
t0=tca-thc;
浮点数t1=tca+thc;
if(t0<0){
t0=t1;
}
如果(t0<0)返回false;
返回true;
}
布尔场景相交(常量浮点原点[]、常量浮点方向[]、常量球体s[]、整数长度、浮点命中[]、浮点N[]、材质*ptr\m){
浮动球体距离=整数最大值;
对于(大小i=0;i#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <limits.h>

typedef struct {
    float position[3];
    float intensity;
} Light;

typedef struct {
    float diffuse_color[3];

}  Material;

typedef struct {
    float center[3];
    float radius;
    Material material;

} Sphere;

int arrSub(const float arr1[], const float arr2[], float subArr[], int length) {
    /*
    Requires 3 equally sized arrays (denoted as length),
    arr1 - arr2 will result in the third array subArr
    */
    for (int i = 0; i < length; i++) {
        subArr[i] = arr1[i] - arr2[i];
    }
    return 0;
}

int arrAdd(const float arr1[], const float arr2[], float addArr[], int length) {
    /*
    Requires 3 equally sized arrays (denoted as length),
    arr1 + arr2 will result in the third array subArr
    */
    for (int i = 0; i < length; i++) {
        addArr[i] = arr1[i] + arr2[i];
    }
    return 0;
}

int arrScalarMult(const float arr1[], float scalar, float newArr[], int length) {
    /*
    Requires 3 equally sized arrays (denoted as length),
    arr1 - arr2 will result in the third array subArr
    */
    for (int i = 0; i < length; i++) {
        newArr[i] = arr1[i] * scalar;
    }
    return 0;
}

float dotProduct(const float arr1[], const float arr2[], int length) {
    /*
    Returns the dot product of two equal sized arrays 
    (treated as vectors)

    a (dot) b = a1b1 + a2b2 + ... anbn
    */
    float result = 0;

    for (int i = 0; i < length; i++) {
        result += arr1[i] * arr2[i];
    }

    return result;
}

int normalize(float arr[], int len) {
    //Normalize a vector (array)

    float sumSqr;
    float norm;

    for (int i = 0; i < len; i++) {
        sumSqr += arr[i] * arr[i];
    }

    norm = sqrt(sumSqr);

    for (int i = 0; i < len; i++) {
        arr[i] = arr[i] / norm;
    }

    return 0;
}

bool ray_intersect(const float origin[], const float dir[], float t0, Sphere s) {
    /*
    Ray-Sphere Intersection

    Vectors:
        origin (the zero vector)
        dir (direction vector)
        L (vector from origin to center of sphere)
    Scalars:
        tca
        d2
        thc
        t0
        t1    
    */
    float L[3] = {0,0,0}; //The zero vector
    arrSub(s.center, origin, L, 3); //L is now the vector from origin to the sphere's center

    float tca = dotProduct(L, dir, 3); //Projection of L onto dir
    float d2 = dotProduct(L, L, 3) - tca*tca;

    if (d2 > s.radius * s.radius) return false; //There is no intersection, so return false.

    float thc = sqrtf((s.radius*s.radius - d2));
    t0 = tca - thc;
    float t1 = tca + thc;
    if (t0 < 0) {
        t0 = t1;
    }
    if (t0 < 0) return false;

    return true;
}

bool scene_intersect(const float origin[], const float dir[], const Sphere s[], int len, float hit[], float N[], Material * ptr_m) {
    float sphere_dist = INT_MAX;

    for (size_t i=0; i < len; i++) {
        float dist_i;
        if (ray_intersect(origin, dir, dist_i, s[i]) && dist_i < sphere_dist) {
            sphere_dist = dist_i;

            float dirDist[3];
            arrScalarMult(dir, dist_i, dirDist, 3);
            arrAdd(origin, dirDist, hit, 3);

            float hitMinusCenter[3];
            arrSub(hit, s[i].center, hitMinusCenter, 3);
            normalize(hitMinusCenter, 3);

            N[0] = hitMinusCenter[0];
            N[1] = hitMinusCenter[1];
            N[2] = hitMinusCenter[2];

            * ptr_m = s[i].material;
        }
    }
    return sphere_dist<1000;
}

int cast_ray(const float origin[], const float dir[], const Sphere s[], const Light l[], int l_size, unsigned char colorArr[]) {
    float point[3], N[3];
    Material m;
    Material * ptr_m = &m;

    if (!scene_intersect(origin, dir, s, 3, point, N, ptr_m)) {
        //background
        colorArr[0] = 5; //red
        colorArr[1] = 100; //green
        colorArr[2] = 250; //blue
    } else {
        float diffuse_light_intensity = 0;
        float light_dir[3];

        for (size_t i = 0; i < l_size; i++) {
            arrSub(l[i].position, point, light_dir, 3);
            normalize(light_dir, 3);
            diffuse_light_intensity += l[i].intensity * ((0.f >= dotProduct(light_dir, N, 3) ? (0.f) : (dotProduct(light_dir, N, 3))));
        }
        //light up pixel
        colorArr[0] = m.diffuse_color[0] * diffuse_light_intensity;
        colorArr[1] = m.diffuse_color[1] * diffuse_light_intensity;
        colorArr[2] = m.diffuse_color[2] * diffuse_light_intensity;
    }

    return 0;
}

int render(const Sphere s[], const Light l[], int l_length) {
    /*
    Creates image in a new color each step.
    */
    const int width = 1024;
    const int height = 768;

    FILE *fp = fopen("fourth.ppm", "wb"); // Write in binary mode
    (void) fprintf(fp, "P6\n%d %d\n255\n", width, height);

    float fov = 3.1415926535/2.; // Field of View

    #pragma omp parallel for
    for (size_t j = 0; j < height; j++) {
        for (size_t i = 0; i < width; i++) {

            float x = (2*(i+.5)/(float)width - 1)*tan(fov/2.)*width/(float)height;
            float y = -(2*(j+.5)/(float)height - 1)*tan(fov/2.);

            float dir[] = {x,y,-1};
            normalize(dir, 3);

            unsigned char color[3];
            const float origin[] = {0,0,0};
            cast_ray(origin, dir, s, l, l_length, color);
            (void) fwrite(color, 1, 3, fp);
        }
    }
    (void) fclose(fp);
    return 0;
}

int main(void) {
    Material red = {255,0,0};
    Material pink = {150,10,150};
    Material gold = {255, 195, 0};

    //Populate with spheres
    Sphere s[3];
    Sphere originalS = {{-3,0,-16},2,gold};
    Sphere bigS = {{-1.0, -1.5, -12}, 3, red};
    Sphere anotherS = {{7,5,-18},2,pink};

    s[0] = originalS;
    s[1] = bigS;
    s[2] = anotherS;

    //Add light source
    Light l[1];

    Light test_light = {{-20,20,20}, 1.5};

    l[0] = test_light;

    render(s,l, 1);
    printf("Run success!\n");
    return 0;
}