osg 使用整理 (6):体渲染效果
osg 使用整理 (6):体渲染效果
体渲染技术可用于医学成像、计算流体力学、有限元、地球物理学、遥感等领域,数据通常来源于CT扫描、核磁共振MRI、卫星成像和声纳等设备,大概分为三种:直接体渲染技术(光线投射法、抛雪球法、错切变形法)、间接体绘制技术和最大密度投影技术。
1 光线投射法(ray casting)
re:《GPU编程与CG语言之阳春白雪下里巴人》
光线投射法是基于图像序列的直接体绘制算法。从图像的每一个像素,沿着视线方向发射一条光线,光线穿越整个图像序列,并在这个过程中,对图像序列进行采样获取颜色信息,同时依据光线吸收模型将颜色值进行累加,直至光线穿越整个图像序列,最后得到的颜色值就是渲染图像的颜色。
1.1 投射方向
首先创建立方体几何,作为体纹理载体,体纹理通过三维纹理坐标和模型一一对应,然后由视点向模型上的点连射线,该射线穿越模型空间等价于射线穿越了体纹理,需要注意OpenGL和Direct3D使用的体纹理坐标并不相同。
射线起始点为相机位置,终止于立方体背面点,射线方向由此求出。开启OpengGL正面剔除设置:
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);//GL_BACK 背面 GL_FRONT 正面 GL_FRONT_AND_BACK 正面和反面
穿越体数据过程中做等距采样,采样密度由外界设置,根据视点和出射点计算投射距离,除以采样密度得到采样次数,这样在每一次采样循环过程中按照颜色合成公式进行反复累加。
1.2 透明度合成公式
透明度代表光穿透物体的能力,如果穿透多个物体,则这种变化是累加的,称为alpha混合技术。如果有多个透明物体,通常需要对物体进行排序。从背面到前面进行采样合成的公式为:
直到透明度累加超过1或者采样距离大于投射距离或者采样次数超过设置最大采样次数时,结束颜色混合迭代。
1.3 osg中光线投射法shader实现
顶点着色器代码:
#version 330
layout(location = 0) in vec3 Postion;
layout(location = 1) in vec4 Color;
layout(location = 8) in vec3 TexCoord;
uniform mat4 osg_ModelViewProjectionMatrix;
uniform mat4 osg_ViewMatrixInverse;
uniform mat4 toTextureMatrix;
out vec4 cameraPos;
out vec4 vertexPos;
out vec4 baseColor;
out vec3 lightDir;
void main(void)
{
gl_Position=osg_ModelViewProjectionMatrix*vec4(Postion,1.0);
cameraPos = toTextureMatrix*osg_ViewMatrixInverse * vec4(0,0,0,1);
vertexPos=vec4(TexCoord,1.0);
baseColor=Color;
vec4 lightPosition = osg_ViewMatrixInverse * gl_LightSource[0].position;
if (lightPosition[3]==0.0)
{
lightDirection = -normalize(lightPosition.xyz);
}
else
{
lightDirection = normalize((lightPosition-vertexPos).xyz);
}
}
片段着色器代码 (带颜色转移函数)
#version 330
uniform sampler3D baseTexture;
uniform sampler1D tfTexture;
uniform float tfScale;
uniform float tfOffset;
uniform float SampleDensityValue;
uniform float TransparencyValue;
uniform float AlphaFuncValue;
in vec4 cameraPos;
in vec4 vertexPos;
in vec4 baseColor;
out vec4 FragColor;
void main(void)
{
vec4 t0 = vertexPos;
vec4 te = cameraPos;
if (te.x>=0.0 && te.x<=1.0 &&
te.y>=0.0 && te.y<=1.0 &&
te.z>=0.0 && te.z<=1.0)
{
// do nothing... te inside volume
}
else
{
if (te.x<0.0)
{
float r = -te.x / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.x>1.0)
{
float r = (1.0-te.x) / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.y<0.0)
{
float r = -te.y / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.y>1.0)
{\n"
float r = (1.0-te.y) / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.z<0.0)
{
float r = -te.z / (t0.z-te.z);
te = te + (t0-te)*r;
}
if (te.z>1.0)
{
float r = (1.0-te.z) / (t0.z-te.z);
te = te + (t0-te)*r;
}
}
const float min_iteratrions = 2.0;
const float max_iteratrions = 2048.0;
float num_iterations = ceil(length((te-t0).xyz)/SampleDensityValue);
if (num_iterations<min_iteratrions) num_iterations = min_iteratrions;
else if (num_iterations>max_iteratrions) num_iterations = max_iteratrions;
vec3 deltaTexCoord=(t0-te).xyz/float(num_iterations-1.0);
vec3 texcoord = te.xyz;
vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);
while(num_iterations>0.0)
{
float v = texture( baseTexture, texcoord).a * tfScale + tfOffset;
vec4 color = texture1D( tfTexture, v);
float r = color[3]*TransparencyValue;
if (r>AlphaFuncValue)
{
fragColor.xyz = fragColor.xyz*(1.0-r)+color.xyz*r;
fragColor.w += r;
}
if(fragColor.w>1.0)break;
texcoord += deltaTexCoord;
--num_iterations;
}
fragColor.w *= TransparencyValue;
if (fragColor.w>1.0) fragColor.w = 1.0;
fragColor *= baseColor;
if (fragColor.w<AlphaFuncValue) discard;
FragColor = fragColor;
};
iso等值面片段着色器
#version 330
uniform sampler3D baseTexture;
uniform sampler1D tfTexture;
uniform float tfScale;
uniform float tfOffset;
uniform float SampleDensityValue;
uniform float TransparencyValue;
uniform float IsoSurfaceValue;
in vec4 cameraPos;
in vec4 vertexPos;
in vec4 baseColor;
in vec3 lightDirection;
out vec4 FragColor;
void main(void)
{
vec4 t0 = vertexPos;
vec4 te = cameraPos;
if (te.x>=0.0 && te.x<=1.0 &&
te.y>=0.0 && te.y<=1.0 &&
te.z>=0.0 && te.z<=1.0)
{
// do nothing... te inside volume
}
else
{
if (te.x<0.0)
{
float r = -te.x / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.x>1.0)
{
float r = (1.0-te.x) / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.y<0.0)
{
float r = -te.y / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.y>1.0)
{\n"
float r = (1.0-te.y) / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.z<0.0)
{
float r = -te.z / (t0.z-te.z);
te = te + (t0-te)*r;
}
if (te.z>1.0)
{
float r = (1.0-te.z) / (t0.z-te.z);
te = te + (t0-te)*r;
}
}
const float min_iteratrions = 2.0;
const float max_iteratrions = 2048.0;
float num_iterations = ceil(length((te-t0).xyz)/SampleDensityValue);
if (num_iterations<min_iteratrions) num_iterations = min_iteratrions;
else if (num_iterations>max_iteratrions) num_iterations = max_iteratrions;
vec3 deltaTexCoord=(t0-te).xyz/float(num_iterations-1.0);
vec3 texcoord = te.xyz;
float previousV = texture( baseTexture, texcoord).a;
float normalSampleDistance = 1.0/512.0;
vec3 deltaX = vec3(normalSampleDistance, 0.0, 0.0);
vec3 deltaY = vec3(0.0, normalSampleDistance, 0.0);
vec3 deltaZ = vec3(0.0, 0.0, normalSampleDistance);
vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);
while(num_iterations>0.0)
{
float v = texture3D( baseTexture, texcoord).a;
float m = (previousV-IsoSurfaceValue) * (v-IsoSurfaceValue);
if (m <= 0.0)
{
float r = (IsoSurfaceValue-v)/(previousV-v);
texcoord = texcoord - r*deltaTexCoord;
v = texture( baseTexture, texcoord).a * tfScale + tfOffset;
vec4 color = texture( tfTexture, v);
float px = texture( baseTexture, texcoord + deltaX).a;
float py = texture( baseTexture, texcoord + deltaY).a;
float pz = texture( baseTexture, texcoord + deltaZ).a;
float nx = texture( baseTexture, texcoord - deltaX).a;
float ny = texture( baseTexture, texcoord - deltaY).a;
float nz = texture( baseTexture, texcoord - deltaZ).a;
vec3 grad = vec3(px-nx, py-ny, pz-nz);
if (grad.x!=0.0 || grad.y!=0.0 || grad.z!=0.0)
{
vec3 normal = normalize(grad);
float lightScale = 0.1 + max(0.0, dot(normal.xyz, lightDirection))*0.9;
color.x *= lightScale;
color.y *= lightScale;
color.z *= lightScale;
}
color *= baseColor;
FragColor = color;
return ;
}
previousV=v;
texcoord += deltaTexCoord;
--num_iterations;
}
discard;
};
light光照片段着色器
#version 330
uniform sampler3D baseTexture;
uniform sampler1D tfTexture;
uniform float tfScale;
uniform float tfOffset;
uniform float SampleDensityValue;
uniform float TransparencyValue;
uniform float AlphaFuncValue;
in vec4 cameraPos;
in vec4 vertexPos;
in vec4 baseColor;
in vec3 lightDirection;
out vec4 FragColor;
void main(void)
{
vec4 t0 = vertexPos;
vec4 te = cameraPos;
if (te.x>=0.0 && te.x<=1.0 &&
te.y>=0.0 && te.y<=1.0 &&
te.z>=0.0 && te.z<=1.0)
{
// do nothing... te inside volume
}
else
{
if (te.x<0.0)
{
float r = -te.x / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.x>1.0)
{
float r = (1.0-te.x) / (t0.x-te.x);
te = te + (t0-te)*r;
}
if (te.y<0.0)
{
float r = -te.y / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.y>1.0)
{\n"
float r = (1.0-te.y) / (t0.y-te.y);
te = te + (t0-te)*r;
}
if (te.z<0.0)
{
float r = -te.z / (t0.z-te.z);
te = te + (t0-te)*r;
}
if (te.z>1.0)
{
float r = (1.0-te.z) / (t0.z-te.z);
te = te + (t0-te)*r;
}
}
const float min_iteratrions = 2.0;
const float max_iteratrions = 2048.0;
float num_iterations = ceil(length((te-t0).xyz)/SampleDensityValue);
if (num_iterations<min_iteratrions) num_iterations = min_iteratrions;
else if (num_iterations>max_iteratrions) num_iterations = max_iteratrions;
vec3 deltaTexCoord=(t0-te).xyz/float(num_iterations-1.0);
vec3 texcoord = te.xyz;
float normalSampleDistance = 1.0/512.0;
vec3 deltaX = vec3(normalSampleDistance, 0.0, 0.0);
vec3 deltaY = vec3(0.0, normalSampleDistance, 0.0);
vec3 deltaZ = vec3(0.0, 0.0, normalSampleDistance);
vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);
while(num_iterations>0.0)
{
float v = texture( baseTexture, texcoord).a * tfScale + tfOffset;
vec4 color = texture1D( tfTexture, v);
float a=v;
float px = texture( baseTexture, texcoord + deltaX).a;
float py = texture( baseTexture, texcoord + deltaY).a;
float pz = texture( baseTexture, texcoord + deltaZ).a;
float nx = texture( baseTexture, texcoord - deltaX).a;
float ny = texture( baseTexture, texcoord - deltaY).a;
float nz = texture( baseTexture, texcoord - deltaZ).a;
vec3 grad = vec3(px-nx, py-ny, pz-nz);
if (grad.x!=0.0 || grad.y!=0.0 || grad.z!=0.0)
{
vec3 normal = normalize(grad);
float lightScale = 0.1 + max(0.0, dot(normal.xyz, lightDirection))*0.9;
color.x *= lightScale;
color.y *= lightScale;
color.z *= lightScale;
}
float r = color[3]*TransparencyValue;
if (r>AlphaFuncValue)
{
fragColor.xyz = fragColor.xyz*(1.0-r)+color.xyz*r;
fragColor.w += r;
}
if (fragColor.w<color.w)
{
fragColor = color;
}
texcoord += deltaTexCoord;
--num_iterations;
}
fragColor.w *= TransparencyValue;
if (fragColor.w>1.0) fragColor.w = 1.0;
fragColor *= baseColor;
if (fragColor.w<AlphaFuncValue) discard;
FragColor = fragColor;
};
原文地址:https://www.cnblogs.com/wangxydela/p/17658509.html
- Flash/Flex学习笔记(53):利用FMS快速创建一个文本聊天室
- 28家银行用户体验调研报告:洞见银行业的“进化论”
- 性能计数器数据收集服务
- SQL SERVER 内存分配及常见内存问题 DMV查询
- 6 利用Docker .NET应用程序模板制作您的容器应用程序(第2部分)
- Mesos+Zookeeper+Marathon的Docker管理平台部署记录(1)
- git review报错一例
- Nginx采用https加密访问后出现的问题
- 对比git rm和rm的使用区别
- Gerrit日常操作命令收集
- 轻型的ORM类Dapper
- [原创]Gerrit中文乱码问题解决方案分享
- 获奖案例:国航&百度“微笑启航”AI主题航班
- MySQL高可用架构-MMM环境部署记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Destoon 6.0 guestbook.php 通用SQL注入漏洞
- Hadoop2.7.6_01_部署
- Hadoop2.7.6_02_HDFS常用操作
- Bottle HTTP 头注入漏洞探究
- Hadoop2.7.6_03_HDFS原理
- Hadoop2.7.6_04_HDFS的Shell操作与常见问题
- Hadoop2.7.6_05_mapreduce-Yarn
- Hadoop2.7.6_06_mapreduce参数优化
- NFS服务搭建与配置
- Hadoop2.7.6_07_HA高可用
- Hadoop2.7.6_08_Federation联邦机制 1.1. HDFS-federation图解2.1. 注意事项3.1. 部署3.2. 环境变量3.3. c
- ThinkPHP5 SQL注入漏洞 && PDO真/伪预处理分析
- Hive-1.2.1_01_安装部署
- Supervisord远程命令执行漏洞(CVE-2017-11610)
- Hive-1.2.1_02_简单操作与访问方式