您的位置:首页 > 其它

Example 4 : Thin lens camera

2016-06-14 11:52 351 查看
main.c

#include <stdio.h>
#include <math.h>
#include <il/il.h>

#include "vec3.h"
#include "sample.h"
#include "shapes.h"

#define IMAGE_WIDTH		512
#define IMAGE_HEIGHT	384
#define NUM_SAMPLES		16

shape_t shapes[4];
light_t lights[1];

typedef struct camera_s
{
vec3 eye;
vec3 lookat;
vec3 up;
float d;	// dist to perfect focus
float aperature;

float l,r,t,b;	// extents of view
} camera_t;

unsigned char floattochar(float c)
{
int i = (int)c;
if (i <= 0)
return 0;
if (i >= 255)
return 255;
else
return (unsigned char)(c);
}

int main(int argc, int argv)
{
int r, c, s;
float x_samples[NUM_SAMPLES];
float y_samples[NUM_SAMPLES];
float xl_samples[NUM_SAMPLES];
float yl_samples[NUM_SAMPLES];
float t_samples[NUM_SAMPLES];
unsigned char image[IMAGE_WIDTH * IMAGE_HEIGHT * 3];
float aspect;
vec3 total, color, hitpos;

vec3 start, end, dir;
hit_t hit;

camera_t cam;
vec3 cam_f, cam_r, cam_u;

ILuint iname;

ilInit();
ilEnable(IL_FILE_OVERWRITE);

// 高,宽比
aspect = (float) IMAGE_HEIGHT / (float)IMAGE_WIDTH;
VectorSet(dir, 0, 0, -1);

// 初始化球和三角形
shapes[0].type = SHAPE_SPHERE;
VectorSet(shapes[0].sphere.center, -2.6f, -0.5f, -1.5f);
shapes[0].sphere.radius = 1;
VectorSet(shapes[0].move_velocity, 0, 0, 0);
VectorSet(shapes[0].color, 1, 0, 0);

shapes[1].type = SHAPE_SPHERE;
VectorSet(shapes[1].sphere.center, 2.6f, 0.5f, -4);
shapes[1].sphere.radius = 1;
VectorSet(shapes[1].move_velocity, 0, 0, 0);
VectorSet(shapes[1].color, 0, 1, 0);

shapes[3].type = SHAPE_TRI;
VectorSet(shapes[2].tri.verts[2], 0, 0.2f, -5);
VectorSet(shapes[2].tri.verts[1], 0, -0.4f, -1);
VectorSet(shapes[2].tri.verts[0], 0, 0.6f, -2);
VectorSet(shapes[2].move_velocity, 0, 0, 0);
VectorSet(shapes[2].color, 1, 1, 0);

// 初始化光源
VectorSet(lights[0].ambient, 0.1f, 0.1f, 0.1f);
VectorSet(lights[0].diffuse, 1, 1, 1);
VectorSet(lights[0].specular, 0.1f, 0.1f, 0.1f);
VectorSet(lights[0].pos, -2, 2, -2);

// 初始化摄像机
VectorSet(cam.eye, -5,0,-2.8f);
VectorSet(cam.lookat, 0,0,-2.8f);
VectorSet(cam.up,  0,1,0);
// To specify the aperture of the lens we could just specify R,
// a large hole = (pinhole) = (aperture)
cam.aperature = 0.25f;

// 相当于s, the distance from e to the viewing rectangle;
// 这里进行调节参数的话,就可以使得哪一些物体清晰,哪一些物体是模糊,主要是看这个the viewing rectangle的位置,因为要发射线到这个
// the viewing rectangle 上的pixel中
cam.d = 2.5f;
cam.l = -0.5f;
cam.r = 0.5f;
cam.t = 0.5f*aspect;
cam.b = -0.5f*aspect;

// we calculate the rest

// cam_f == cam_forward
VectorSub(cam.lookat, cam.eye, cam_f);
VectorNormalize(cam_f);
// cam_r == cam_right
CrossProduct(cam_f, cam.up, cam_r);
VectorNormalize(cam_r);
// cam_u == cam_up
CrossProduct(cam_r, cam_f, cam_u);
VectorNormalize(cam_u);

for (r=0; r<IMAGE_HEIGHT; r++)
{
for (c=0; c<IMAGE_WIDTH; c++)
{
// pixel samples
sample_multi_jitter_2d(NUM_SAMPLES, x_samples, y_samples);
filter_cubic(NUM_SAMPLES, x_samples);
filter_cubic(NUM_SAMPLES, y_samples);

// time samples
sample_jitter_1d(NUM_SAMPLES, t_samples);
filter_cubic(NUM_SAMPLES, t_samples);
sample_shuffle(NUM_SAMPLES, t_samples);

// lens samples
sample_multi_jitter_2d(NUM_SAMPLES, xl_samples, yl_samples);
sample_shuffle_2d(NUM_SAMPLES, xl_samples, yl_samples);

VectorSet(total, 0, 0, 0);
for (s=0; s<NUM_SAMPLES; s++)
{
// 这里范围就变成了[-0.5, 0.5]
xl_samples[s] -= 0.5f;
yl_samples[s] -= 0.5f;
VectorCopy(cam.eye, start);

// if cam.aperature = 0, all xl_samples[s] is miss
VectorMA(start, cam.aperature*xl_samples[s], cam_r, start);
VectorMA(start, cam.aperature*yl_samples[s], cam_u, start);

// ((((x_samples[s]+0.5f+c) / ((float)IMAGE_WIDTH )))*(cam.r-cam.l) + cam.l);主要的功能就是把
// 512 *512 的pixel 映射到 cam.rltb这个view上

// 为什么要乘上 cam.d(s)

// note that although s is arbitrary as long as it is positive, the bigger it is
// the bigger the window height and width have to be to get the same image.The
// ratio of v\ - v0 to 2s is the tangent of half of the "vertical field-of-view." This
// is another way to fix some viewing parameters.

// 就是,2s 与 (v1 - v0)成比例,如果 假设了v1 = -v0的话,那么,s就与v1,v0成比例
x_samples[s] = cam.d*((((x_samples[s]+0.5f+c) / ((float)IMAGE_WIDTH )))*(cam.r-cam.l) + cam.l);
y_samples[s] = cam.d*((((y_samples[s]+0.5f+r) / ((float)IMAGE_HEIGHT)))*(cam.t-cam.b) + cam.b);
VectorCopy(cam.eye, end);
VectorMA(end, cam.d, cam_f, end);
VectorMA(end, x_samples[s], cam_r, end);
VectorMA(end, y_samples[s], cam_u, end);

// VectorSub(a,b,c) ==>  c = a - b, b->a
// start -> end
VectorSub(end, start, dir);
VectorNormalize(dir);

if (shape_intersect_all(start, dir, t_samples[s], &hit))
{
VectorMA(start, hit.t, dir, hitpos);
shape_shade(hit.shape, hitpos, t_samples[s], color);

VectorAdd(total, color, total);
}

// background
else
{
total[0] += 0.2f;
total[1] += 0.2f;
total[2] += 0.2f;
}
}

VectorScale(total, 255.0f / NUM_SAMPLES, total);

image[(r*IMAGE_WIDTH + c)*3 + 0] = floattochar(total[0]);
image[(r*IMAGE_WIDTH + c)*3 + 1] = floattochar(total[1]);
image[(r*IMAGE_WIDTH + c)*3 + 2] = floattochar(total[2]);
}
}

/* write the image */
ilGenImages(1, &iname);
ilBindImage(iname);

ilTexImage(IMAGE_WIDTH, IMAGE_HEIGHT, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, image);

ilSaveImage("out.png");
ilDeleteImages(1, &iname);

return 0;
}


主要的思想都在代码的注释里面,

比较重要的就是,

1. aperture 个人理解就是,A real pinhole camera. 中的那个pinhole的R(半径)。

2.


S与整个view(由(u0,v0),(u1, v1)构成的)有比例关系。

although s is arbitrary as long as it is positive, the bigger it is the bigger the window height and width have to be to get the same image. The ratio of v1 - v0 to 2s is the tangent of half of the "vertical field-of-view." This  is another way to fix some
viewing parameters.

3. 整体思路



q点是根据aperature随机生成,如果aperature是0的话,那么就没有模糊效果,因为起点没有任何变化,那么,就相当于之前的muilt sample。

只有当aperature不为0的时候,生成的q是随机的,对应不在s距离上的物体,射线射到的这些物体上的hitPoint偏差较大,所以形成模糊。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Realistic Ray Tracin