Shaders for Game Programmers and Artists(6) - 反射与折射
反射
反射在上一篇的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) - 反射与折射相关推荐
- Shaders for Game Programmers and Artists(7) - Non-photorealistic rendering
边缘提取 边缘提取有很多种,这里用的是屏幕空间的做法,首先把要提取边缘的物品用纯色绘制到一张rt上,然后用一个一个边缘检测的滤波器在ps中扫一遍. 绘制纯色的的ps float4 ps_main( f ...
- Shaders for Game Programmers and Artists(4) - 热雾效果
一.原理 先看下面的图 产生的原理及其就是折射. 深入探究的话,可以去搜搜波粒二象性,斯涅尔定律等等. 当太阳照射地面的时候,靠近地面的空气会变得很热,热空气比较轻会往上走,冷的空气会往下沉.冷热空气 ...
- 物理光学4 反射与折射中的一些特殊现象
物理光学4 反射与折射中的一些特殊现象 第一种情况:n1<n2n_1<n_2n1<n2 也就是入射端的折射率小于折射端的折射率(也就是从光疏介质到光密介质,可以类比从空气中传播到 ...
- UA PHYS515A 电磁理论V 电磁波与辐射4 反射与折射
UA PHYS515A 电磁理论V 电磁波与辐射4 反射与折射 假设平面z=0z=0z=0是两种不导电介质的交界面,z<0z<0z<0的空间中介质的介电常数与磁导率为ϵ1,μ1\ep ...
- OpenGL反射和折射
OpenGL反射和折射 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include <math.h&g ...
- 【Unity3d】(二) Unity3D--光的反射与折射实现
Unity3D--光的反射与折射实现 最近做老师的科研项目,主要方向是虚拟现实,重点是研究光学物理实验.在这里写一些自己开发过程中想法和实现细节,方便自己回顾和分享给需要的小伙伴! ☆☆☆☆☆☆☆☆☆ ...
- UnityShader---高级纹理(反射、折射、菲涅尔反射、镜子\玻璃效果)(内置渲染管线)---11
反射:代码里有阴影和衰减计算 Shader "Unlit/17" {Properties{_Color("Color",Color)=(1,1,1,1)_Ref ...
- OpenGL基础37:反射与折射
前置:OpenGL基础20:镜面光照 一.反射 不一定所有的光源都是简单的白光,不仅如此,光线也是可以多次反射的,例如一面镜子,可以从中看到远处的风景,一些金属材质的物体表面也会反射周围物体的光 这主 ...
- 反射,折射,菲涅尔反射总结
立方体纹理(Cubemap)最常见的是用于天空盒子以及环境映射,通常被用作具有反射,折射属性物体的反射源.Lighting-Environment中添加对应的材质. 材质对应贴图的类型要选择Cube. ...
最新文章
- mmz-asio4delphi死链接的解决办法
- java swing 总结_java实验之swing图形用户界面程序设计及总结
- Google开发者模式调试css样式的方法
- 【LeetCode】【HOT 100】2. 两数相加
- Java 15 即将到来,新特性速览!
- mysql安全删除大表
- C# 中格式化字符串中包含 { 或者 } 如何转义?
- 程序员自学能学会吗?我是自学的,努力比天分重要
- 运算放大器的偏置电流
- PHP繁體,php如何实现转繁体
- 生成微信公众号二维码(动态,彩色)(python)
- 12.10.3 冻结窗格
- 台式计算机拆解与安装,台式机固态硬盘安装流程拆解
- unity 获取本地视频/下载网络视频
- AUTOMATE THE BORING STUFF WITH PYTHON读书笔记 - 第19章:MANIPULATING IMAGES
- 软件企业认定条件政策
- [渝粤教育] 宁波城市职业技术学院 Web服务器运维(从零搭建一个企业网站) 参考 资料
- JS中onpropertychange事件和onchange事件区别
- 自制Darknet Yolo目标快速标注工具
- python多线程执行同样代码_Python 多线程、多进程 (一)之 源码执行流程、GIL