• 利用着色器迭代求解离散泊松方程


    一直想整理一下研究生期间做的东西,在这里做一个开端吧。从毕业论文中用到的算法开始。

    求解离散泊松方程,源于当时的研究项目,从图像生成三维模型,具体内容此处不做细谈。

    为了生成具有一定特征凸起的平滑表面,利用G2连续性曲面的二阶偏微分具有G0连续性的特性,构造特征参数表面,该表面只需G0连续性,通过距离变换等计算,可以很容易获得。通过迭代计算,即可获得所需的具有G2连续性的表面。

    构造泊松等式:

    d2z(x,y)/dx2 +d2z(x,y)/dy2 =f(x,y)

    其中xy为自变量,z为所求的表面高度,f(x,y)为z对于x,y的偏微分参数,即特征表面(保证G0连续)。

    将等式写成有限差分形式:

    d2z(i,j)/dx2 +d2z(i,j)/dy2 = z(i-1,j)+z(i,j-1)+z(i+1,j)+z(i,j+1)-4z(i,j)

    利用等式的右侧可以得到:

    z(i,j)=1/4(z(i-1,j)+z(i,j-1)+z(i+1,j)+z(i,j+1)+f(i,j))

    构造Jacobi迭代:

    zn+1(i,j)=1/4(zn(i-1,j)+zn(i,j-1)+zn(i+1,j)+zn(i,j+1)+f(i,j))

    迭代计算z(i,j),直到最终收敛。

    这样一个等式的计算,可以很容易的写出来,但是对于1000*1000的点阵可能就会耗时数小时。

    为了加快计算速度,采用了片段着色器绘制来模拟计算过程,让输出的颜色值表示高度,计算过程可以加快数十倍。

    使用两张FrameBufferTexture,轮换作为输入和输出来模拟迭代计算的过程,可以非常迅速的求解。

    由于整个工程浩大,这里仅贴上GLSL部分的核心计算代码。其中constraintImg是边界条件对应的图像,红色代表dirichlet边界(边界处z值保持不变),蓝色代表neuman边界(边界处z值的梯度为0),绿色代表边界处的高度随输入渐变。(ps:前两个边界条件是常见泊松方程边界条件,最后一个是为了满足特殊需求新定义的边界条件)

      1 #version 400
      2 #extension GL_ARB_texture_rectangle : enable
      3 
      4 
      5 //original image which will not be changed
      6 uniform sampler2DRect inputImg;
      7 
      8 //red as dirichlet boundary,blue as neumann boundary
      9 uniform sampler2DRect constraintImg;
     10 
     11 uniform sampler2DRect tmpImg;
     12 
     13 uniform vec2 size;
     14 
     15 
     16 void main()
     17 {
     18     vec2 coord = gl_FragCoord.xy;
     19     vec4 inputColor=texture2DRect(inputImg, coord);
     20     vec4 tmpColor = texture2DRect(tmpImg, coord);
     21     vec4 constraintColor= texture2DRect(constraintImg, coord);
     22     
     23     if(inputColor.w<0.01)//input 4channel as mask
     24     {
     25         //outside mask,should be zero
     26         gl_FragColor = vec4(0,0,0,1);
     27     }
     28     else if(constraintColor.x>0.99)//red
     29     {
     30         //dirichlet boundary,remain the original color
     31         gl_FragColor = inputColor;
     32     }
     33     else if(constraintColor.x<0.01 && constraintColor.y>0.01)//green
     34     {
     35         if(constraintColor.y>0.99)
     36             gl_FragColor = inputColor;
     37         else
     38         {
     39             vec4 f = vec4(constraintColor.w,constraintColor.w,constraintColor.w,constraintColor.w);
     40             vec4 a = texture2DRect(tmpImg, coord + vec2(-1, 0));
     41             vec4 b = texture2DRect(tmpImg, coord + vec2(1, 0));
     42             vec4 c = texture2DRect(tmpImg, coord + vec2(0, -1));
     43             vec4 d = texture2DRect(tmpImg, coord + vec2(0, 1));
     44             vec4 res= 0.25*(a+b+c+d+f);
     45             res=(1 - constraintColor.y) * res + constraintColor.y * inputColor;
     46             gl_FragColor = res;
     47         }
     48     }
     49     else if(constraintColor.x<0.01 && constraintColor.z>0.99)//blue
     50     {
     51         //neumann boundary,derivative is zero,should be inside mask
     52         //so we decide to use the average color of its inside region neighbors as the approximation
     53         int count=0;
     54         vec4 res = vec4(0,0,0,0);
     55         vec4 ma = texture2DRect(inputImg, coord+vec2(-1,0));
     56         if(ma.w>=0.9)//inside mask region
     57         {
     58             vec4 a = texture2DRect(tmpImg, coord+vec2(-1,0));
     59             res+=a;
     60             count+=1;
     61             
     62         }
     63 
     64         vec4 mb = texture2DRect(inputImg, coord+vec2(1,0));
     65         if(mb.w>=0.9)
     66         {
     67             vec4 b = texture2DRect(tmpImg, coord + vec2(1, 0));
     68             res+=b;
     69             count+=1;
     70         }
     71 
     72         vec4 mc = texture2DRect(inputImg, coord+vec2(0,-1));
     73         if(mc.w>=0.9)
     74         {
     75             vec4 c = texture2DRect(tmpImg, coord + vec2(0, -1));
     76             res+=c;
     77             count+=1;
     78         }
     79 
     80         vec4 md = texture2DRect(inputImg, coord+vec2(0,1));
     81         if(md.w>=0.9)
     82         {        
     83             vec4 d = texture2DRect(tmpImg, coord + vec2(0, 1));
     84             res+=d;
     85             count+=1;
     86         }
     87         
     88         if(count>0)
     89             res/=count;
     90 
     91         gl_FragColor=res;
     92     }
     93     else
     94     {
     95         //inside poisson,jacobi iteration
     96         vec4 f = vec4(constraintColor.w,constraintColor.w,constraintColor.w,constraintColor.w);
     97         vec4 a = texture2DRect(tmpImg, coord + vec2(-1, 0));
     98         vec4 b = texture2DRect(tmpImg, coord + vec2(1, 0));
     99         vec4 c = texture2DRect(tmpImg, coord + vec2(0, -1));
    100         vec4 d = texture2DRect(tmpImg, coord + vec2(0, 1));
    101         vec4 res = 0.25*(a+b+c+d+f);
    102 
    103         gl_FragColor=res;
    104     }
    105     
    106 }
  • 相关阅读:
    confluence --常用插件整合
    fuse--s3挂载到centos7.5服务器
    gvm--go版本管理工具
    等保1.0与等保2.0的区别
    postfix -- 发件调试
    postfix邮件服务器
    confluence -- 命令行备份还原
    浏览器使用小tip
    windows如何正确下载补丁包
    xwiki使用中的问题
  • 原文地址:https://www.cnblogs.com/kevonyang/p/4986916.html
Copyright © 2020-2023  润新知