首页 > 其他分享 >osg 使用整理 (6):体渲染效果

osg 使用整理 (6):体渲染效果

时间:2023-08-26 11:12:24浏览次数:42  
标签:渲染 0.0 float t0 vec4 vec3 整理 te osg

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混合技术。如果有多个透明物体,通常需要对物体进行排序。从背面到前面进行采样合成的公式为:

\[C_i^Δ=(1-A_i)C_{i+1}^Δ+C_i\\ A_i^Δ=(1-A_i)C_{i+1}^Δ+A_i \]

​ 直到透明度累加超过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;
};

标签:渲染,0.0,float,t0,vec4,vec3,整理,te,osg
From: https://www.cnblogs.com/wangxydela/p/17658509.html

相关文章

  • 微信小程序的渲染层与逻辑层
    1为什么小程序中的渲染层和逻辑层进行分离在之前的网页一般开发流程中,我们通常使用js操作DOM,以引起页面的一些变化响应用户的行为。varname2=document.getElementById("name")这样子当你的项目越来越大的时候代码会充斥着非常多的交互逻辑和程序的各种状态的变量,是比较混乱......
  • math---多元函数积分方法整理
    复习到了这里,解题方法有点多,脑子有点乱,遂整理一下一、常规的三重积分解法1、先一后二法:用x,y表示z2、先二后一法:用z表示x,y3、球形积分4、常用技巧对称性、轮换对称、换元法(补行列式),其中球形积分就是用到了换元的思想:二、第一型曲线积分第一型曲线积分主要解决......
  • 吃透这份阿里P7大佬整理的《Android Framework源码笔记》,还怕找不到工作?
    前言随着Android开发行业的快速发展,市场需求也在不断提升,导致低端Android开发市场就业大环境不好、行业趋势下滑,使得不少初中级的Android开发开始失业,找不到工作。对于大部分的开发者来说,找不到工作的一大部分原因,是因为AndroidFramework无法做到精通。想要成为真正的高级Androi......
  • 解析直播美颜SDK功能算法:肤色识别、特征增强与实时渲染
    在这个数字化时代,美颜技术在直播中的应用愈发受到重视,为主播和观众创造更加美好的视觉体验。本文将深入探讨直播美颜SDK 的核心功能算法,包括肤色识别、特征增强与实时渲染,揭示其背后的技术原理与工作机制。一、肤色识别算法肤色识别是直播美颜的基础,它能够自动检测图像中的肤色区......
  • chatgpt 的术语整理
     问题:  希望对语言进行翻译,并且整合成自己想要的格式描述字段  “多久关机”这个字段进行英语、德语、法语、意大利语、波兰语、捷克语进行缩写翻译,并且对翻译内容前面加上LANG0=", 其中0根据语言依次递增,并且在每个翻译后的字段加上", 合并成一行,不需要显示语......
  • 【知识整理】基于Springboot的Kafka消费者动态操作
    基于Springboot的Kafka消费者动态操作1.问题​ 在基于Springboot开发Kafka相关业务时,遇到如下业务场景:执行部分操作时,如停止服务替换镜像、执行特殊业务处理等,需要先停止Consumer接收Kafka消息,待处理完成后再开启Consumer接续接收Kafka消息为并发消费Kafka消息,可通过配置sp......
  • 【知识整理】Springboot启动扩展点
    SpringBoot启动扩展点整理1.前言​ 在Springboot服务启动阶段,Springboot提供了许多扩展点。在实际的业务开发过程中,部分特殊的业务需求需要再Springboot服务启动过程中动态的加载配置或者执行业务处理,特此将常用的Springboot启动扩展点做一个简单的整理。2.准备阶段2.1Env......
  • 嵌入式开源库交叉编译整理
    本文将不定期更新,主要是整理统计遇到的开源库,交叉编译的方法。这里的交叉编译平台主要是ARM32的芯片平台。首先在交叉编译目录上一层创建文件夹,方便后续开源库的依赖和链接mkdir../rv1126这里我使用的是,rv1126的平台,因此创建了一个rv1126的目录。后续所有开源库的编译,输......
  • [20230809]ora-04030问题分析整理.txt
    [20230809]ora-04030问题分析整理.txt--//生产系统同事使用toad连接经常出现ora-04030错误。ORA-04030:outofprocessmemorywhentryingtoallocate123416bytes(QERHJhash-joi,kllcqas:kllsltba)--//仔细看joi确实不是join,开始猜测可能某个程序的sql语句选择hash-join,......
  • 【双目相机产品调研整理】22/12/01
    ......