体绘制(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 页。英文阅读能力比较好的同学可以尝试着看一下。

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

时间: 2024-10-16 13:58:50

体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)的相关文章

39. Volume Rendering Techniques

Milan Ikits University of Utah Joe Kniss University of Utah Aaron Lefohn University of California, Davis Charles Hansen University of Utah This chapter presents texture-based volume rendering techniques that are used for visualizing three-dimensional

体绘制(Volume Rendering)概述之3:光线投射算法(Ray Casting)原理和注意要点(强烈推荐呀,讲的很好)

转自:http://blog.csdn.net/liu_lin_xm/article/details/4850609 摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文 名“GPU编程与CG语言之阳春白雪下里巴人” 15.1 光线投射算法原理 光线投射方法是基于图像序列的直接体绘制算法.从图像的每一个像素,沿固定方向(通常是视线方向)发射一条光线,光线穿越整个图像序列,并在这个过程中,对图像序列进行采样获取颜色信息,同时依据光线吸收

光线投射算法与光线跟踪算法

原文:http://blog.csdn.net/changbaolong/article/details/8461704 光线跟踪计算机算法的一般描述 为了生成在三维计算机图形环境中的可见图像,光线跟踪是一个比光线投射或者扫描线渲染更加逼真的实现方法.这种方法通过逆向跟踪与假象的照相机镜头相交的光路进行工作,由于大量的类似光线横穿场景,所以从照相机角度看到的场景可见信息以及软件特定的光照条件,就可以构建起来.当光线与场景中的物体或者媒介相交的时候计算光线的反射.折射以及吸收. 光线跟踪的场景经常

【优化算法】Greedy Randomized Adaptive Search算法 超详细解析,附代码实现TSP问题求解

01 概述 Greedy Randomized Adaptive Search,贪婪随机自适应搜索(GRAS),是组合优化问题中的多起点元启发式算法,在算法的每次迭代中,主要由两个阶段组成:构造(construction)和局部搜索( local search). 构造(construction)阶段主要用于生成一个可行解,而后该初始可行解会被放进局部搜索进行邻域搜索,直到找到一个局部最优解为止. 02 整体框架 如上面所说,其实整一个算法的框架相对于其他算法来说还算比较简单明了,大家可以先看以

基本算法思想Java实现的详细代码

基本算法思想Java实现的详细代码 算法是一个程序的灵魂,一个好的算法往往可以化繁为简,高效的求解问题.在程序设计中算法是独立于语言的,无论使用哪一种语言都可以使用这些算法,本文笔者将以Java语言为例介绍一些常用的算法思想. 分类 穷举算法思想 递推算法思想 递归算法思想 分治算法思想 概率算法思想  穷举算法思想 穷举算法的基本思想 从所有可能情况中搜索正确答案 1. 对于一种可能情况,计算其结果. 2. 判断结果是否满足,如不能满足者执行第一步来搜索下一个可能的情况:如满足则表示选找到一个

排序算法的基本思想和OC代码实现

算法的基本思想和OC代码实现 一 .冒泡排序   (平均时间复杂度 o(N*N))  基本思想:两个数比较大小,较大的数下沉,较小的数冒起来. 过程:比较相邻的两个数据,如果第二个数小,就交换位置 从后向前两两比较,一直到比较最前两个数据.最终最小数被交换到起始的位置,这样第一个最小数的位置就排好了. 继续重复上述过程,依次将第2,3,….,n-1个最小数排好位置. int arr[5]={23,21,45,23,64}; int temp; for (int i=0; i<4; i++) {

编程算法 - 数组中的逆序对 代码(C)

数组中的逆序对 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 在数组中的两个数字如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对. 输入一个数组, 求出这个数组中的逆序对的总数. 使用归并排序的方法, 辅助空间一个排序的数组, 依次比较前面较大的数字, 算出整体的逆序对数, 不用逐个比较. 时间复杂度: O(nlogn) 代码: /* * main.cpp * * Created on: 2014.6.12 * Author:

第2章 rsync算法原理和工作流程分析

本文通过示例详细分析rsync算法原理和rsync的工作流程,是对rsync官方技术报告和官方推荐文章的解释. 以下是rsync系列篇: 1.rsync(一):基本命令和用法 2.rsync(二):inotify+rsync详细说明和sersync 3.rsync算法原理和工作流程分析 4.rsync技术报告(翻译) 5.rsync工作机制(翻译) 6.man rsync翻译(rsync命令中文手册) 本文目录: 1.1 需要解决的问题 1.2 rsync增量传输算法原理 1.3 通过示例分析r

改进的二值图像像素标记算法及程序实现(含代码)

笔者实现了一个论文里面的算法程序,论文(可以网上搜索到,实在搜不到可以联系笔者或留下邮箱发给你)讲解比较到位,按照作者的思路写完了代码,测试效果很好,在此分享一下算法思路及实现代码. 此算法优于一般的像素标记算法,只需扫描一遍就可以得出图像边界.面积等等,大大减少了计算量. 算法描述: 一.全图扫描 对二值图像全图扫描,左到右,上到下,一遇到像素边界就进行判断.像素边界指当前像素灰度为1,其他8领域至少有一个灰度值为0. 1.先依次判断当前像素(i,j)的左侧.左上侧.上侧像素和右上侧像素是否被