Example 4 : Thin lens camera

来源:互联网 发布:网络交换机的设置 编辑:程序博客网 时间:2024/06/06 01:57

main.c

#include <stdio.h>#include <math.h>#include <il/il.h>#include "vec3.h"#include "sample.h"#include "shapes.h"#define IMAGE_WIDTH512#define IMAGE_HEIGHT384#define NUM_SAMPLES16shape_t shapes[4];light_t lights[1];typedef struct camera_s{vec3 eye;vec3 lookat;vec3 up;float d;// dist to perfect focusfloat 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;elsereturn (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_forwardVectorSub(cam.lookat, cam.eye, cam_f);VectorNormalize(cam_f);// cam_r == cam_rightCrossProduct(cam_f, cam.up, cam_r);VectorNormalize(cam_r);// cam_u == cam_upCrossProduct(cam_r, cam_f, cam_u);VectorNormalize(cam_u);for (r=0; r<IMAGE_HEIGHT; r++){for (c=0; c<IMAGE_WIDTH; c++){// pixel samplessample_multi_jitter_2d(NUM_SAMPLES, x_samples, y_samples);filter_cubic(NUM_SAMPLES, x_samples);filter_cubic(NUM_SAMPLES, y_samples);// time samplessample_jitter_1d(NUM_SAMPLES, t_samples);filter_cubic(NUM_SAMPLES, t_samples);sample_shuffle(NUM_SAMPLES, t_samples);// lens samplessample_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 missVectorMA(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 -> endVectorSub(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);}// backgroundelse{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偏差较大,所以形成模糊。


0 0
原创粉丝点击