在C语言中实现基本光线跟踪器
因此,我目前正在编写一个教程来实现一个非常基本的光线跟踪器(目前只是绘制实心球体)。上述教程位于以下位置: 本教程完全与语言无关,只涉及伪代码。我试图将此伪代码转换为C,但遇到了困难。我的程序编译得很好,但输出的.ppm图像文件遇到早期EOF错误。缺乏关于这个问题的信息使我陷入困境 这是我的C代码,它是伪代码的直接翻译:在C语言中实现基本光线跟踪器,c,graphics,C,Graphics,因此,我目前正在编写一个教程来实现一个非常基本的光线跟踪器(目前只是绘制实心球体)。上述教程位于以下位置: 本教程完全与语言无关,只涉及伪代码。我试图将此伪代码转换为C,但遇到了困难。我的程序编译得很好,但输出的.ppm图像文件遇到早期EOF错误。缺乏关于这个问题的信息使我陷入困境 这是我的C代码,它是伪代码的直接翻译: #include <stdio.h> #include <math.h> #define WIDTH 512 #define HEIGHT 512
#include <stdio.h>
#include <math.h>
#define WIDTH 512
#define HEIGHT 512
typedef struct {
float x, y, z;
} vector;
float vectorDot(vector *v1, vector *v2) {
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
}
void writeppm(char *filename, unsigned char *img, int width, int height){
FILE *f;
f = fopen(filename, "w");
fprintf(f, "P6 %d %d %d\n", width, height, 255);
fwrite(img, 3, width*height, f);
fclose(f);
}
float check_ray(px, py, pz, dx, dy, dz, r) {
vector v1 = {px, py, pz};
vector v2 = {dx, dy, dz};
float det, b;
b = -vectorDot(&v1, &v2);
det = b*b - vectorDot(&v1, &v1) + r*r;
if (det<0)
return -1;
det = sqrtf(det);
float t1 = b - det;
float t2 = b + det;
return t1;
}
int main(void) {
int img[WIDTH*HEIGHT*3], distToPlane;
float cameraY, cameraZ, cameraX, pixelWorldX, pixelWorldY, pixelWorldZ, amp, rayX, rayY, rayZ;
for (int px = 0; px<WIDTH; px++) {
for (int py = 0; py<HEIGHT; py++) {
distToPlane = 100;
pixelWorldX = distToPlane;
pixelWorldY = (px - WIDTH / 2) / WIDTH;
pixelWorldZ = (py - HEIGHT / 2) / WIDTH;
rayX = pixelWorldX - cameraX;
rayY = pixelWorldY - cameraY;
rayZ = pixelWorldZ - cameraZ;
amp = 1/sqrtf(rayX*rayX + rayY*rayY + rayZ*rayZ);
rayX *= amp;
rayY *= amp;
rayZ *= amp;
if (check_ray(50, 50, 50, rayX, rayY, rayZ, 50)) {
img[(py + px*WIDTH)*3 + 0] = 0;
img[(py + px*WIDTH)*3 + 1] = 0;
img[(py + px*WIDTH)*3 + 2] = 128;
}
else {
img[(py + px*WIDTH)*3 + 0] = 255;
img[(py + px*WIDTH)*3 + 1] = 255;
img[(py + px*WIDTH)*3 + 2] = 255;
}
}
}
writeppm("image.ppm", "img", WIDTH, HEIGHT);
}
#包括
#包括
#定义宽度512
#定义高度512
类型定义结构{
浮动x,y,z;
}载体;
浮点向量点(向量*v1,向量*v2){
返回v1->x*v2->x+v1->y*v2->y+v1->z*v2->z;
}
void writeppm(字符*文件名,无符号字符*img,整数宽度,整数高度){
文件*f;
f=fopen(文件名,“w”);
fprintf(f,“P6%d%d%d\n”,宽度、高度,255);
fwrite(img,3,宽度*高度,f);
fclose(f);
}
浮动检查射线(px、py、pz、dx、dy、dz、r){
向量v1={px,py,pz};
向量v2={dx,dy,dz};
浮点数,b;
b=-矢量点(&v1和&v2);
det=b*b-矢量点(&v1,&v1)+r*r;
如果(det您可能希望删除以下代码行中“img”
左右的引号:
writeppm("image.ppm", "img", WIDTH, HEIGHT);
看到它的原型是怎样的void writeppm(char*,unsigned char*,int,int)
,尽管我很惊讶您的编译器至少没有给您一个关于类型不匹配的警告
另外,为了记录在案,我建议使用一些错误检查代码(比如检查fwrite的返回值,或者检查fopen的返回值)——但这只是我的问题
此外,如果您没有,请在编译时启用所有警告(例如使用gcc use-ansi-Wall-pedantic),这将帮助您捕获类型不匹配和其他小问题我在main中看到两个错误
int img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", "img", WIDTH, HEIGHT);
应该是
unsigned char img[WIDTH*HEIGHT*3];
...
writeppm("image.ppm", img, WIDTH, HEIGHT);
也许我太迂腐了,但你没有问任何问题。你只使用
writeppm(“image.ppm”、“img”、“WIDTH、HEIGHT”)将3个字符img
写入文件;
,其余字符来自随机内存。不过,这不应该导致你说的错误。你是否在需要“wb”的操作系统上
写入二进制文件?。在修复了check_ray
的声明后,我得到的是一个有效的PPM,但它是一个甚至蓝色的图像。您的代码中一定还有其他错误。好的,我已经更改了它,“img”应该是img,以便将img数组传递到saveppm函数中。您还需要更改int img[..
到无符号字符img[..
。谢谢,这已经修复了它。