AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

采样

1,最小标准随机数生成器Linear congruential generator(LCG):

如图所示:感觉随机度很高。书中这个随机周期很高了,绝对够用。

void gen_points(int npts;float ptpos[])
{
    int m = pow(2,31) - 1;
    int a = 16807;
    int b = 45454;
    
    int seed = 1412133;
    float ui = 0.0f;
    for(int i=0;i<npts*3;i++){
        
        seed = (a * seed + b)  % m;
        ui = float(seed) / float(m);
        //printf("%f  ,%f \n",ui,seed);
        append(ptpos,ui);
    }
}




float pts[];
int   np = 10000;

// generation random points
gen_points(np,pts);


for(int i=0;i<np;i++)
{
    float x = pts[i*3];
    float y = pts[i*3+1];
    float z = pts[i*3+2];
    addpoint(geoself(),set(x,y,z));
}
View Code

 

2,随机游走random walk:

int np = 100;
float w = 0 ;
float scale = 0.1;

for(int i=0;i<np;i++)
{   
    // add main point
    int add_ptnum = addpoint(geoself(),set(i*scale,w,0));
    
    if (rand(i*10000)> (1.0/2.0) )
    {
        // up
        w += 1.0f * scale;
    }
    else{
        // down
        w -= 1.0f* scale;
    }
}
View Code

 

 

3,布朗运动brownian motion

不改变期望,也不改变方差.............

int np = 100;
float w = 0 ;
float scale = 1;

// substeps movement!
int substeps = 6;
float substep_scale = 1 / sqrt(substeps);
for(int i=0;i<np;i++)
{   
    for(int j =0;j<substeps;j++)
    {
            // add main point
        int add_ptnum = addpoint(geoself(),set( (i*substeps + j)*scale/substeps,w,0));
        if (rand(i*10+j*1000)> (1.0/2.0f) )
        {
            // up
            w += 1.0f * scale * substep_scale;
        }
        else{
            // down
            w -= 1.0f* scale * substep_scale;
        }
    }
    
}
    
View Code

然后书中给了 用randn生成正态分布,模拟布朗运动,在houdini随便对应个rand

int k = 100;
float dt = 1.0/24.000f;
float sqdelt = sqrt(dt);
float b = 0;
for (int i=0;i<k;i++)
{
    addpoint(geoself(),set(i,b,0));
    b = b + sqdelt  * fit(rand(i),0,1,-5,5);
}
View Code

 

 

 

 

单位方块的采样点:

1,抖动采样

int n = 10;
for(int j=0;j<n;j++){
    for(int i=0;i<n;i++){
        float x = (i + rand(i*500+j*500))/n;
        float y = (j + rand(j*5000+i*1000000))/n;
        addpoint(geoself(),set(x,y,0));
    }
}
View Code

 

抗锯齿 抖动采样:

注释的部分就是像素中心发射一根光线:

但是这个引来一个问题,这个方法肯定不能并发,因为书中讲的random方法,不是线程安全。应该把houdini的rand()方法做出来。

void RT_World::render()
{

    // INIT our PPMIO
    PPMIO *imageIo = new PPMIO;
    PPMIO::WriteParam imageIoParam;
    // 

    imageIoParam.width = vp.hres;
    imageIoParam.height = vp.vres;
    imageIoParam.maxPixelValue = 255;

    // IO will save ascii type for easy reading
    imageIoParam.imageIOType = PPMIO::ASCII_P3_TYPE;     
    imageIoParam.imageType = PPMIO::RGB_TYPE;
// IO image buffer;
    PPMIO::RGB  *data = new PPMIO::RGB[vp.hres*vp.hres];
//
    RT_RGB pixel_color;
    RT_Ray ray;
    double zw = 100;
    ray.d = RT_VEC_3D({ 0,0,-1 });

    RT_VEC_2D sample_point; // unit square sample point
    RT_VEC_2D pixel_pos;    // pixel pos with sample point

    RT_Log_StdOut("Start Rendering");
    for (int r = 0; r < vp.vres; r++) {        // loop the row
        for (int c = 0; c < vp.hres; c++) {    // loop the column

            pixel_color = black_color;
            //double x = vp.size  * (c - 0.5 *(vp.hres - 1.0));
            //double y = vp.size  * (r - 0.5 *(vp.vres - 1.0));
            //cout << "rendering pixel x/y:   " << x << "/" << y << endl;
            //ray.o = RT_VEC_3D({ x,y,zw });
            //pixel_color = tracer_ptr->trace_ray(ray);
            //cout << "trace ptr get color->" << pixel_color << endl;


            // for samples
            for (int i = 0; i < vp.num_samples; i++) {
                sample_point = vp.sampler_ptr->sample_unit_square();
                pixel_pos[0] = vp.size * (c - 0.5*vp.hres + sample_point[0]);
                pixel_pos[1] = vp.size * (r - 0.5*vp.vres + sample_point[1]);
                ray.o = RT_VEC_3D({ pixel_pos[0],pixel_pos[1],RT_SCALAR(zw) });
                pixel_color += tracer_ptr->trace_ray(ray);
            }
            pixel_color /= vp.num_samples;

        


            // because our ray born from Cartesian coordinates
            // we need trans to our image coord
            int row = (vp.vres-1) - r;
            int column = c;
            // our pixel_color is 0~1 , we need convert to RGB 0~255 space
            //cout << "current set x y :" << row << "|" << column << endl;
            int index = row * vp.hres + column;
            PPMIO::RGB indexRGB;
            indexRGB.R = unsigned char(pixel_color[0] * 255);
            indexRGB.G = unsigned char(pixel_color[1] * 255);
            indexRGB.B = unsigned char(pixel_color[2] * 255);
            data[index] = indexRGB;

        }
    }


    imageIo->writeImage("c:/test_aa.ppm", data, imageIoParam);
    delete imageIo;
    delete []data;

    RT_Log_StdOut("End Rendering");

}

 

 

 

 

 

2,比较有意思的,相邻像素随机在 采样集合 采取不同的 samples: 

inline int
rand_int(void) {
    return(rand());
}

void unit_test_random_ray() {
    int num_samples = 25;
    int num_sets = 10;
    int count = 0;
    int jump = 0;
    // per ray has unique own jump
    cout << "construct samples:" << num_samples << "with num_set:" << num_sets << endl;
    for (int ray = 0; ray < 5; ray++) {
        cout << "sending the ray id:" << ray << endl;
        // loop 25 times,get 25 points
        for (int i = 0; i < num_samples; i++)
        {
            if (count % num_samples == 0) {
                jump = (rand_int() % num_sets) * num_samples;
                cout << "set jump init:" << jump << endl;

            }
            // 25  samples position index we get:
            cout <<"cout index:" << count <<"  RND:" << jump + (count++ % num_samples) << endl;
        }
    }
}
View Code

 

 而且在set里面访问连续的samples,还可以把这些连续的打乱访问。

void unit_test_random_ray2() {
    int num_samples = 25;
    int num_sets = 10;
    int count = 0;
    int jump = 0;


    vector<int> shuffled_indices;
    // set up shuffle_indices
    vector <int> indices;
    for (int i = 0; i < num_samples; i++) {
        indices.push_back(i);
    }
    for (int p = 0; p < num_sets; p++) {
        random_shuffle(indices.begin(), indices.end());
        for (int j = 0; j < num_samples; j++) {
            shuffled_indices.push_back(indices[j]);
        }
    }



    // per ray has unique own jump
    cout << "construct samples:" << num_samples << "with num_set:" << num_sets << endl;
    for (int ray = 0; ray < 5; ray++) {
        cout << "sending the ray id:" << ray << endl;
        // loop 25 times,get 25 points
        for (int i = 0; i < num_samples; i++)
        {
            if (count % num_samples == 0) {
                jump = (rand_int() % num_sets) * num_samples;
                cout << "set jump init:" << jump << endl;

            }
            // 25  samples position index we get:
            cout << "cout index:" << count << "  RND:" << jump + shuffled_indices[jump+(count++ % num_samples)] << endl;
        }
    }
}
View Code

 

 

 例如书中给的图是用的第一种方式访问,反射有明显的水波纹.第二种就改善这个问题:

 

3,圆采样映射。

float r = 0;
float phi = 0;
if(@P.x > -@P.y)
{
    if(@P.x > @P.y)
    {
        r = @P.x;
        phi = @P.y / @P.x;
    }
    else
    {
        r= @P.y;
        phi = 2 - @P.x / @P.y;
    }
}

else{
    if(@P.x < @P.y)
    {
        r = -@P.x;
        phi = 4 + @P.y/@P.x;
    }
    else{
        r = -@P.y ;
        if(@P.y != 0.0){
            phi = 6 - @P.x / @P.y;
        }
        else
            phi = 0.0;
    }
}


phi *= 3.1415926/4.0;
@P.x = r * cos(phi);
@P.y = r * sin(phi);
View Code

 

 4,(书里是8.4章)采样与轴对齐透视,也就是当eye点z轴有数值,然后定义在视线方向有个距离d

 

void RT_World::render_perspective_zw() {

    // INIT our PPMIO
    PPMIO *imageIo = new PPMIO;
    PPMIO::WriteParam imageIoParam;
    // 

    imageIoParam.width = vp.hres;
    imageIoParam.height = vp.vres;
    imageIoParam.maxPixelValue = 255;

    // IO will save ascii type for easy reading
    imageIoParam.imageIOType = PPMIO::ASCII_P3_TYPE;
    imageIoParam.imageType = PPMIO::RGB_TYPE;

    std::cout << "Start Construct Image buffer data\n";
    // IO image buffer;
    PPMIO::RGB  *data = new PPMIO::RGB[vp.hres*vp.hres];
    std::cout << "End Construct Image buffer data\n";

    //
    RT_RGB pixel_color;
    RT_Ray ray;

    RT_SCALAR eye = 100; // view point
    RT_SCALAR d = 20;    // distance view point to ViewPlane!
    ray.o = RT_VEC_3D({0.0,0.0,eye});

    RT_VEC_2D sample_point; // unit square sample point
    RT_VEC_2D pixel_pos;    // pixel pos with sample point

    RT_Log_StdOut("Start Rendering");
    for (int r = 0; r < vp.vres; r++) {        // loop the row
        for (int c = 0; c < vp.hres; c++) {    // loop the column

            pixel_color = black_color;


            // for samples
            for (int i = 0; i < vp.num_samples; i++) {
                sample_point = vp.sampler_ptr->sample_unit_square();
                pixel_pos[0] = vp.size * (c - 0.5*vp.hres + sample_point[0]);
                pixel_pos[1] = vp.size * (r - 0.5*vp.vres + sample_point[1]);
                // cal ray direction
                ray.d = RT_VEC_3D({ pixel_pos[0] - ray.o[0],pixel_pos[1] - ray.o[1],-d });
                ray.d.normalize();
                //ray.o = RT_VEC_3D({ pixel_pos[0],pixel_pos[1],RT_SCALAR(zw) });
                pixel_color += tracer_ptr->trace_ray(ray);
            }
            pixel_color /= vp.num_samples;




            // because our ray born from Cartesian coordinates
            // we need trans to our image coord
            int row = (vp.vres - 1) - r;
            int column = c;
            // our pixel_color is 0~1 , we need convert to RGB 0~255 space
            //cout << "current set x y :" << row << "|" << column << endl;
            int index = row * vp.hres + column;
            PPMIO::RGB indexRGB;
            indexRGB.R = unsigned char(pixel_color[0] * 255);
            indexRGB.G = unsigned char(pixel_color[1] * 255);
            indexRGB.B = unsigned char(pixel_color[2] * 255);
            data[index] = indexRGB;

        }
    }


    imageIo->writeImage("c:/test_aa_pzw_e100_d_100.ppm", data, imageIoParam);
    delete imageIo;
    delete[]data;

    RT_Log_StdOut("End Rendering");
}
View Code

 

 

 

 

 

参考

<<数值分析>>

<<RayTracing from ground up>>

<<Fundamentals of computer graphics>>

posted on 2019-05-27 11:54  gearslogy  阅读(455)  评论(0编辑  收藏  举报