反射

反射在上一篇的HDR中就已经用到了。简单说一下
反射发生的原理就是光线打到一个物体的面上之后,一部分光被弹回去的现象,

原理如下图

只要知道入射光线和发现,出射光线的方向就可以求出。通过这个方向对天空盒进行采样,就可以得到天空盒上的颜色了。

在vs中计算出射光线的方向

float4x4 view_proj_matrix;
float4 view_position;
struct VS_OUTPUT
{float4 Pos:       POSITION;float2 TexCoord:   TEXCOORD0;float3 Reflect:   TEXCOORD1;
};VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL,float2 inTxr: TEXCOORD0)
{VS_OUTPUT Out;// Compute the projected position and send out the texture coordinatesOut.Pos = mul(view_proj_matrix, inPos);Out.TexCoord = inTxr;// Compute the reflection vectorOut.Reflect = -reflect(view_position-inPos,inNormal);return Out;
}

在ps中对天空盒进行采样,同时和采自身贴图的结果相加。

sampler Wood;
sampler EnvMap;
float4 ps_main(float2 inTxr: TEXCOORD0,float3 inReflect: TEXCOORD1) : COLOR
{// Output texture color with reflection mapreturn 0.2*tex2D(Wood,inTxr)+0.8*texCUBE(EnvMap,inReflect);
}

折射

折射是光线穿过折射率不同的两种介质所产生的现象,其中入射角和出射角遵循斯涅尔定律(snell’s low)

下面列出了一些常用物质的折射率

当然,这个折射率是对某个特定波长的光来说的,对于波长不同的光,介质的折射率也是不一样的。

所以折射的实现最终就是求折射光线的问题了,这是一道三角函数题。

直接看vs吧,注释里面有计算的步骤

float4x4 view_proj_matrix;
float4 view_position;
float refractingPower;
struct VS_OUTPUT
{float4 Pos:       POSITION;float2 TexCoord:   TEXCOORD0;float3 Refract:   TEXCOORD1;
};VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL,float2 inTxr: TEXCOORD0)
{VS_OUTPUT Out;// Compute the projected position and send out the texture coordinates
//mvp矩阵变换Out.Pos = mul(view_proj_matrix, inPos);Out.TexCoord = inTxr;float3 viewVec = normalize(view_position - inPos);//根据斯涅尔法则计算反射角// n_i * sin(theta_i) = n_r  * sin(theta_r)// sin(theta_i)
//首先用向量点乘计算出cos,然后用勾股定理计算sin值float cosine = dot(viewVec, inNormal);float sine = sqrt(1 - cosine * cosine);// sin(theta_r)
//根据斯涅尔法则计算出射角的sin,saturate到0,1,所以当入射角足够大的时候,然后用勾股定理计算cos值float sine2 = saturate(refractingPower * sine);float cosine2 = sqrt(1 - sine2 * sine2);//首先构建一对正交基x,y 然后变换到标准的坐标轴上,cross是向量叉乘,a × b为一个新生成的向量,这个向量垂直于a 和 b展成的平面float3 x = -inNormal;float3 y = normalize(cross(cross(viewVec, inNormal), inNormal));Out.Refract = x * cosine2 + y * sine2;return Out;
}

折射率是1.14时候的结果

折射率是1.66时候的结果

反射+折射

光线和物质表面相交的时候,一部分光线发生了反射,一部分发生了折射。根据斯涅尔定律,当入射角大到一定程度的时候,折射现象就不会发生了,这个角就是临界角,任何超过这个角的入射光线都会被完全反射,称为全反射(total internal reflection)现象,示意图如下

当我们斜着看水面的时候,到一定角度就看不到水下的东西,而水面看起来就像一面镜子,原理就是这样。

Shader中vs需要同时计算反射光线和折射光线的向量,

float4x4 view_proj_matrix;
float4 view_position;
struct VS_OUTPUT
{float4 Pos:       POSITION;float2 TexCoord:   TEXCOORD0;float3 Refract:   TEXCOORD1;float3 Reflect:   TEXCOORD2;float2 Factors:   TEXCOORD3;
};VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL,float2 inTxr: TEXCOORD0)
{VS_OUTPUT Out;// Compute the projected position and send out the texture coordinatesOut.Pos = mul(view_proj_matrix, inPos);Out.TexCoord = inTxr;float3 viewVec = normalize(view_position - inPos);// Compute reflectionOut.Reflect = reflect(-viewVec,inNormal);// Compute the reflection vector using Snell's law// the refract HLSL function does not always work properly// n_i * sin(theta_i) = n_r  * sin(theta_r)// sin(theta_i)float cosine = dot(viewVec, inNormal);float sine = sqrt(1 - cosine * cosine);// sin(theta_r)float sine2 = saturate(1.14 * sine);float cosine2 = sqrt(1 - sine2 * sine2);// Determine the refraction vector be using the normal and tangent// vectors as basis to determine the refraction directionfloat3 x = -inNormal;float3 y = normalize(cross(cross(viewVec, inNormal), inNormal));Out.Refract = x * cosine2 + y * sine2;// Determine proper reflection and refraction factors through// a Fresnel approximation. (x = reflect, y = refract)Out.Factors.x = sine;Out.Factors.y = (1 - sine2);return Out;
}

同时根据近似的Fresnel,算出两者叠加的比例。

最后在Ps中叠加

sampler Wood;
sampler EnvMap;
float4 ps_main(float2 inTxr: TEXCOORD0,float3 inRefract: TEXCOORD1,float3 inReflect: TEXCOORD2,float2 inFct: TEXCOORD3) : COLOR
{// Output texture color with reflection mapreturn inFct.x * texCUBE(EnvMap,inReflect) +(inFct.y * texCUBE(EnvMap,inRefract) + 0.4)* tex2D(Wood,inTxr);
}

0.4是为了模拟ambient color

Shaders for Game Programmers and Artists(6) - 反射与折射相关推荐

  1. Shaders for Game Programmers and Artists(7) - Non-photorealistic rendering

    边缘提取 边缘提取有很多种,这里用的是屏幕空间的做法,首先把要提取边缘的物品用纯色绘制到一张rt上,然后用一个一个边缘检测的滤波器在ps中扫一遍. 绘制纯色的的ps float4 ps_main( f ...

  2. Shaders for Game Programmers and Artists(4) - 热雾效果

    一.原理 先看下面的图 产生的原理及其就是折射. 深入探究的话,可以去搜搜波粒二象性,斯涅尔定律等等. 当太阳照射地面的时候,靠近地面的空气会变得很热,热空气比较轻会往上走,冷的空气会往下沉.冷热空气 ...

  3. 物理光学4 反射与折射中的一些特殊现象

    物理光学4 反射与折射中的一些特殊现象 第一种情况:n1<n2n_1<n_2n1​<n2​ 也就是入射端的折射率小于折射端的折射率(也就是从光疏介质到光密介质,可以类比从空气中传播到 ...

  4. UA PHYS515A 电磁理论V 电磁波与辐射4 反射与折射

    UA PHYS515A 电磁理论V 电磁波与辐射4 反射与折射 假设平面z=0z=0z=0是两种不导电介质的交界面,z<0z<0z<0的空间中介质的介电常数与磁导率为ϵ1,μ1\ep ...

  5. OpenGL反射和折射

    OpenGL反射和折射 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include <math.h&g ...

  6. 【Unity3d】(二) Unity3D--光的反射与折射实现

    Unity3D--光的反射与折射实现 最近做老师的科研项目,主要方向是虚拟现实,重点是研究光学物理实验.在这里写一些自己开发过程中想法和实现细节,方便自己回顾和分享给需要的小伙伴! ☆☆☆☆☆☆☆☆☆ ...

  7. UnityShader---高级纹理(反射、折射、菲涅尔反射、镜子\玻璃效果)(内置渲染管线)---11

    反射:代码里有阴影和衰减计算 Shader "Unlit/17" {Properties{_Color("Color",Color)=(1,1,1,1)_Ref ...

  8. OpenGL基础37:反射与折射

    前置:OpenGL基础20:镜面光照 一.反射 不一定所有的光源都是简单的白光,不仅如此,光线也是可以多次反射的,例如一面镜子,可以从中看到远处的风景,一些金属材质的物体表面也会反射周围物体的光 这主 ...

  9. 反射,折射,菲涅尔反射总结

    立方体纹理(Cubemap)最常见的是用于天空盒子以及环境映射,通常被用作具有反射,折射属性物体的反射源.Lighting-Environment中添加对应的材质. 材质对应贴图的类型要选择Cube. ...

最新文章

  1. mmz-asio4delphi死链接的解决办法
  2. java swing 总结_java实验之swing图形用户界面程序设计及总结
  3. Google开发者模式调试css样式的方法
  4. 【LeetCode】【HOT 100】2. 两数相加
  5. Java 15 即将到来,新特性速览!
  6. mysql安全删除大表
  7. C# 中格式化字符串中包含 { 或者 } 如何转义?
  8. 程序员自学能学会吗?我是自学的,努力比天分重要
  9. 运算放大器的偏置电流
  10. PHP繁體,php如何实现转繁体
  11. 生成微信公众号二维码(动态,彩色)(python)
  12. 12.10.3 冻结窗格
  13. 台式计算机拆解与安装,台式机固态硬盘安装流程拆解
  14. unity 获取本地视频/下载网络视频
  15. AUTOMATE THE BORING STUFF WITH PYTHON读书笔记 - 第19章:MANIPULATING IMAGES
  16. 软件企业认定条件政策
  17. [渝粤教育] 宁波城市职业技术学院 Web服务器运维(从零搭建一个企业网站) 参考 资料
  18. JS中onpropertychange事件和onchange事件区别
  19. 自制Darknet Yolo目标快速标注工具
  20. python多线程执行同样代码_Python 多线程、多进程 (一)之 源码执行流程、GIL

热门文章

  1. (转载)验证下载下来的文件的完整性的方法
  2. mac远程登录虚拟机
  3. python执行方式和设置_03-Python执行方式和Pycharm设置
  4. Java课程设计基于SSM的出租房管理
  5. Oracle EBS 模拟登入
  6. [转]Google Linux Cluster的系统结构分析(余一娇)
  7. Matlab 预失真器放大,如何实现射频功率放大器的基带自适应预失真技术
  8. img预加载获取图片大小方法
  9. 误删除系统libselinux.so.1之后
  10. mysql高可用架构——MMM用群集架构