我想用C语言制作一个基本的射线跟踪器,于是决定使用一个名为 .tga
文件作为输出的渲染文件,但不知道为什么,创建的文件在我能找到的所有tga文件查看器中都显示为纯白色。但不知为什么,在我能找到的所有tga文件查看器中,被创建的文件都显示为纯白色。我写入的文件的十六进制转储的开头是 在这里似乎很清楚,图像的大片区域应该是黑色的。
写入该文件的循环是。
void raycast(uint16_t width, uint16_t height, FILE* file, Sphere* sphere) {
Vec3* camera = makeVec3(0, 0, 0);
Vec3* light = makeVec3(1, -1, -1);
int count = 0;
double zMax = 1 / cos(toRads(vFOV) / 2.0);
double yMax = 1 / cos(toRads(hFOV) / 2.0);
for (uint16_t i = 0; i < height; i++) {
for (uint16_t j = 0; j < width; j++) {
int16_t zOffset = (height / 2 - i);
double zprop = zOffset / (height / 2.0);
double zCoord = zMax * zprop;
int16_t yOffset = (width / 2 - j);
double yprop = yOffset / (width / 2.0);
double yCoord = yMax * yprop;
Vec3* coord = makeVec3(1, yCoord, zCoord);
normalize(coord);
Ray* ray = makeRay(camera, coord);
Vec3* intersect = sphereIntersect(sphere, ray);
if (intersect == NULL) {
fputc(255, file);
fputc(255, file);
fputc(255, file);
} else {
printf("disp black\n");
fputc(0x00, file);
fputc(0x00, file);
fputc(0x00, file);
count++;
}
}
}
printf("%d\n", count);
}
而我看到的是 disp black
被打印到控制台,而 count
会递增到30多万,所以把0写到文件中显然没有什么问题。我尽量按照我找到的头格式来写 此处,这有什么问题吗?
我还注意到,无论我把图片放在什么地方,它都是纯色的。if
挡 if
语句总是被采取。
编辑:写头的代码
static void writeHeader(FILE* file) {
static uint16_t width = 800;
static uint16_t height = 600;
// 800x600 image, 24 bits per pixel
unsigned char header[18] = {
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00,
(unsigned char)(width & 0x00FF), (unsigned char)((width & 0xFF00) / 256),
(unsigned char)(height & 0x00FF), (unsigned char)((height & 0xFF00) / 256),
0x08, 0x00
};
fwrite(header, sizeof(char), 18, file);
}
头部是错误的。你发布的代码是在写RGB数据,但将十六进制转储与你链接的页面中的规格进行匹配,我们看到。
Identification Field | 00 = No ID field
Colour Map Type | 01 = CMap Included
Image Type Code | 01 = Type 1: Colour Mapped
Colour Map Spec | 00 00 00 01 18 ...
Image Spec
X Origin | 00 00 = 0
Y Origin | 00 00 = 0
Width | 20 03 = 800px
Height | 58 02 = 600px
Bits/Pixel | 08 = 8bpp
Descriptor | 00...
你的头说文件是颜色映射的。由于头与数据不匹配,所以被误解了,没有显示出你期望看到的东西。
你几乎可以肯定的是,你希望Type 2 "Unmapped RGB "来匹配你正在写入的数据,所以第2个字节应该是0x00(你没有提供颜色映射),第3个字节应该是0x02(表示RGB)。然后,颜色图规格应该被忽略,所以可以用零填充。大小等看起来都不错。
我不建议像这样简单的把固定的头写成一个字节数组。这样容易出错,而且不灵活。很容易定义一个 struct
定义了头,然后你就可以得到标签字段、适当类型和符号常量的优势,如果你定义了一个叫做 enum
的图片类型代码等。
链接的文章已经提供了这些,你只需要确保它没有被编译器通过pragma填充,以确保布局与描述的完全一致。
#pragma pack(push, 1)
typedef struct {
char idlength;
char colourmaptype;
char datatypecode;
short int colourmaporigin;
short int colourmaplength;
char colourmapdepth;
short int x_origin;
short int y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
} HEADER;
#pragma pack(pop)