zoukankan      html  css  js  c++  java
  • 体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)

    转自:http://blog.csdn.net/liu_lin_xm/article/details/4850630

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文 名“GPU编程与CG语言之阳春白雪下里巴人”    

    算法流程

     

     

    图 47 展示了使用光线投射算法进行体绘制的实现流程。

    首先要渲染出正向面深度图和背向面深度图,这是为了计算射线穿越的最大距离,做为循环采样控制的结束依据;然后在顶点着色程序中计算顶点位置和射线方向,射线方向由视线方向和点的世界坐标决定,其实射线方向也可以放在片段着色程序中进行计算。然后到了最关键的地方,就是循环纹理采样、合成。

    每一次循环都要计算新的采样纹理坐标和采样距离,然后进行颜色合成和透明度累加,如果采样距离超过了最大穿越距离,或者透明度累加到 1 ,则循环结束。将合成得到的颜色值输出即可。

    图 48 给出了使用光线投射算法进行体绘制的效果图:

     

     

    15.4 光线投射算法实现

    本节给出光线投射算法的着色程序实现代码。依然是分为三个部分:结构体、顶点着色程序和片段着色程序。

    代码 22 光线投射算法结构体

    struct VertexIn

    {

      float4 position : POSITION;    

      float4 texCoord:  TEXCOORD;

    };

    struct VertexScreen

    {

      float4 position   : POSITION; 

      float4 worldPos   : TEXCOORD0;

      float4 projPos    : TEXCOORD1;

      float4 texCoord   : TEXCOORD2;

    };

    代码 23 光线投射算法顶点着色程序

    VertexScreen main_v(VertexIn posIn,

                            uniform float4x4 world,

                      uniform float4x4 worldViewProj,

                      uniform float4x4 texViewProj)

    {

        VertexScreen posOut;

       

        posOut.position = mul(worldViewProj, posIn.position);

        posOut.worldPos = mul(world,posIn.position);

        posOut.projPos = mul(texViewProj, posOut.worldPos); 

        posOut.texCoord = posIn.texCoord;

        return posOut;

    }

    代码 24 光线投射算法片段着色程序

    void main_f(VertexScreen posIn,

               uniform float3 eyePosition,

               uniform sampler3D volumeTex: register(s0),

               uniform sampler2D frontDepthTex: register(s1) ,

               uniform sampler2D backDepthTex: register(s2) ,

            out float4 result        : COLOR)

    {

           // 根据视点和当前顶点世界坐标计算方向

           float3 dir = posIn.worldPos.xyz-eyePosition;

           dir = normalize(dir);

           float3 deltaDir = float3(0.0, 0.0, 0.0);

          

           // 获取当前顶点的三维纹理坐标

           float3 tex = posIn.texCoord.xyz;

           float2 uvDelta;

           uvDelta.x = 0.0;//ddx( tex ).x;

           uvDelta.y = 0.0;//ddy( tex ).y;

          

           // 取出深度间隔值 , 并设置采样间隔

           float2 uv= posIn.projPos.xy/posIn.projPos.w;

           float frontDis = tex2D(frontDepthTex,uv).x;

           float backDis = tex2D(backDepthTex,uv).x;

           float len = backDis-frontDis;

          

           // 初始化颜色值、采样值、透明度

      float3 norm_dir = normalize(dir);

      float stepsize = 0.01;

      float delta = stepsize;

      float3 delta_dir = norm_dir * delta;

      float delta_dir_len = length(delta_dir);

      float3 vec = posIn.texCoord.xyz;

      float4 col_acc = float4(0,0,0,0);

      float alpha_acc = 0;

      float length_acc = 0;

      float4 color_sample;

      float alpha_sample;

      for(int i = 0; i < 800; i++){

           color_sample = tex3D(volumeTex,vec);

          alpha_sample = color_sample.a * stepsize;

          col_acc   += (1.0 - alpha_acc) * color_sample * alpha_sample * 3;

          alpha_acc += alpha_sample;

          vec += delta_dir;

          length_acc += delta_dir_len;

          if(length_acc >= len || alpha_acc > 1.0) break; // 采样循环控制条件

     }

           result.xyz = col_acc.xyz*2.0+float3(0.2,0.2,0.2);

           result.w = col_acc.w;  

    }

    15.5 本章小结

    本书的第14 、15 章阐述了体绘制中光线投射算法的基本原理和实现流程。实际上,在此基础上可以对光线投射算法加以扩展,例如将光线投射算法和阴影绘制算法相结合,可以渲染出真实感更强的图像。

    此外,有些体数据是中间是空的,在射线方向上进行采样时需要跳过空区域,这其中也需要额外的算法处理,在英文中称为“Object-Order Empty Space Skipping ”。

    目前我所发现关于体绘制以及光线投射算法最好的教材是Markus Hadwiger 等人所写的“Advanced Illumination Techniques for GPU-Based Volume Raycasting ”。此书发表在SIGGRAPH ASIA2008 上,是目前所能找到最新也是非常权威的教材,共166 页。英文阅读能力比较好的同学可以尝试着看一下。

    本章已经是此书的最后一章,最后希望中国的计算机科学可以真正上升到科学研究的层次,而不是一直在混沌中热衷做泥瓦匠的工作。

  • 相关阅读:
    ASP.NET Web 项目文件类型
    SQL Server 2008数据类型
    哎,终于还是在博客园安家了
    document.evaluate的详细用法
    Prototype1.5.1源代码解读分析4
    Prototype1.5.1源代码解读分析1
    每个.NET 开发人员应该下载的十个必备工具
    #Rgeion #End Region 中的关于折叠所有和不折叠的有的方法
    如何把web站点的所有.aspx.cs文件编译为.dll文件?
    Prototype1.5.1源代码解读分析3
  • 原文地址:https://www.cnblogs.com/zhizhan/p/3971750.html
Copyright © 2011-2022 走看看