Vulkan_片元着色器特效2(反射、折射、色散)

47 篇文章 9 订阅
20 篇文章 6 订阅

反射与折射的效果我们可以参照之前Vulkan_Shader—环境映射天空盒查看,之前也有简述过两者原理,今天除了上述两种效果外,我们主要来看一下色散的效果:
在这里插入图片描述
,在此之前我们首先来简单的回顾一下反射与折射,首先我们得理解立方体贴图:
立方图纹理是一种特殊的纹理映射技术,主要包括如下两个要点。

  • 立方图纹理的单位是套,一套立方图纹理包括 6 幅尺寸相同的正方形纹理图。与构造天空盒的思路相同,这 6 幅图正好包含了周天360º全部的场景内容。
  • 对立方图纹理进行采样时,需要给出的不再是 S、 T两个轴的纹理坐标,而是一个规格化的向量。此规格化向量代表采样的方向,用来确定在代表全周天 360º的 6幅图中的哪一幅的哪个位置进行采样。

一、反射

在这里插入图片描述
从图中可以看出,本案例中实现茶壶反射周围环境的内容有两项关键工作要做,具体如下所列。

  • 根据摄像机位置及被观察点位置计算出观察方向(视线)向量,并参照被观察点的法向量计算视线反射方向向量。
  • 根据视线反射方向向量确定采样点,实施立方图纹理采样。这与现实世界中人眼观察光滑物体,其表面有反射是完全一致的。
vec3 cR = reflect (cI, normalize(inNormal));//反射

运行效果如下:
在这里插入图片描述

二、折射

现实世界中很多场合都会有这样的情况,透过透明物体观察周围的环境时会有折射的现象。平时使用的很多光学设备利用的就是光线的折射,例如放大镜、眼镜、望远镜、显微镜等。

上一部分反射的案例均采用立方体纹理技术,所不同的是本节中的采样向量是视线经玻璃球表面折射后的向量,而不再是被表面反射后的向量。立方体纹理技术本身已经在上一节详细介绍过,因此本节仅介绍采用立方图纹理技术实现折射效果的原理,如下图所示。
在这里插入图片描述
从图中可以看出,本案例中为了实现玻璃球折射出周围环境的内容也有两项关键工作要做,具体如下所列。

  • 根据摄像机位置及被观察点位置计算出观察方向(视线)向量,并参照被观察点的法向量计算视线折射方向向量。
  • 根据视线折射方向向量确定采样点,实施立方图纹理采样。这与现实世界中人眼观察透明物体,其折射出观察的环境内容是完全一致的。

  • 折射方向的计算遵循斯涅尔定律,具体情况如图下所示。
    在这里插入图片描述
    从图中可以看出,入射向量与折射向量共面,且入射角α、折射角β与两种材质的折射率满足如下公式:
    A×sin(α) = B×sin(β)
vec3 cR = refract(cI,inNormal,zsl);//折射

运行效果如下:
在这里插入图片描述

三、色散

上一小节通过玻璃球实现放大镜效果的案例介绍了折射效果的开发,读者应该觉得案例的整体效果还是非常逼真的。但还有一点不够真实的地方,那就是现实世界中不同颜色的光对于同一种材质的折射率是不完全相同的。因此,透过玻璃球观察现实世界时会产生色散的效果。

色散的原因是不同颜色的光对于同一种材质的折射率不完全相同。这就是说一束由不同颜色的光组成的光线经过折射后,不同颜色的组成部分出射方向会有发散,形成彩虹一样的效果,下图很好地说明了这个问题。
在这里插入图片描述
因此,我们需要将rgb不同颜色的光分量以不同的折射系数单独进行了折射计算。
在这里插入图片描述

四、反射、折射、色散片元着色器代码

#version 450

layout (binding = 1) uniform samplerCube samplerColor;

layout (binding = 0) uniform UBO
{
	mat4 projection;
	mat4 model;
	mat4 invModel;
	float lodBias;
} ubo;

layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in float inLodBias;
layout (location = 3) in vec3 inViewVec;
layout (location = 4) in vec3 inLightVec;

layout (location = 0) out vec4 outFragColor;

//根据法向量、视线向量及斯涅尔定律计算立方图纹理采样的方法
vec4 refraction(in float coefficient){

	 //根据斯涅尔定律计算折射后的视线向量
 	vec3 cI = normalize (inPos);
	//vec3 cR = reflect (cI, normalize(inNormal));//反射
	vec3 cR = refract(cI,inNormal,coefficient );//折射

	cR = vec3(ubo.invModel * vec4(cR, 0.0));
	cR.x *= -1.0;

	vec4 color = texture(samplerColor, cR, inLodBias);
	return color;
 }


void main()
{	
	//折射、反射
	vec4 color =refraction(0.94);

	//色散
	//vec4 color = vec4(0,0,0,0);
	//color.r = refraction(0.95).r;
	//color.g = refraction(0.945).g;
	//color.b = refraction(0.94).b;

	//光照模型
	vec3 N = normalize(inNormal);
	vec3 L = normalize(inLightVec);
	vec3 V = normalize(inViewVec);
	vec3 R = reflect(-L, N);
	vec3 ambient = vec3(0.5) * color.rgb;
	vec3 diffuse = max(dot(N, L), 0.0) * vec3(1.0);
	vec3 specular = pow(max(dot(R, V), 0.0), 16.0) * vec3(0.5);
	outFragColor = vec4(ambient + diffuse * color.rgb + specular, 1.0);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值