Unity3D-RayMarch-几何图元-3添加阴影
效果图:

在RayMarch渲染算法中计算阴影非常简单,当射线碰撞到物体,从碰撞点逆着光源方向再次执行射线步进算法,如果这一过程中碰撞到了其他物体,则碰撞点被其他物体遮挡,该处具有阴影。
shader代码:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "RayMarch/Primitives1_phong"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
LOD
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#define PointLightPos fixed3(0, 6, 0)
#define LightColor float3(1,1,1)
#define GlobalAmibent float3(0.01,0.01,0.01)
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//###################################################################################
//sdf:define primitives
float sdPlane(float3 p,float planeYPos)
{
return p.y - planeYPos;
}
float sdSphere(float3 p, float3 spherePos, float radius)
{
return length(p - spherePos) - radius;
}
//###################################################################################
//###################################################################################
//primitives boolean operation
//求并集
float2 opU(float2 d1, float2 d2)
{
return (d1.x<d2.x) ? d1 : d2;
}
//###################################################################################
// define the scene
float2 map(in float3 pos)
{
//plane
//float2(x,y)的第二个参数定义了该物体的材质id,在render环节,可以根据id做不同处理
float2 plane = float2(sdPlane(pos, -);
float2 ball_1 = float2(sdSphere(pos, float3(, , ), );
float2 ball_2 = float2(sdSphere(pos, float3(, , ), );
float2 ball_3 = float2(sdSphere(pos, float3(-, , ), );
//求物体的并集
float2 res = opU(opU(opU(ball_1, ball_2), ball_3),plane);
return res;
}
float2 castRay(in float3 ro, in float3 rd)
{
float tmin = 1.0;
//射线最大允许经过的距离
float tmax = 100.0;
;
//当前已经过的距离
float t = tmin;
//材质id
float m = -1.0;
//最大迭代次数定位64
; i<; i++)
{
//距离精度随距离的增加而减小
float precis = 0.0005*t;
//获得场景中物体距离该点的距离,及距离最近物体的材质id
float2 res = map(ro + rd*t);
//如果与场景物体发生碰撞,或者射线行进距离超出最大范围,则跳出迭代
if (res.x<precis || t>tmax) break;
t += res.x;
m = res.y;
}
if (t > tmax) {
m = -clamp((t - tmax) / (tmaxmax - tmax), , );
}
return float2(t, m);
}
int IsInShadow(in float3 ro, in float3 rd) {
;
float tmax = distance(ro, PointLightPos);
;
; i < ; i++) {
float precis = 0.0005*t;
float2 res = map(ro + rd*t);
if (res.x < precis) {
result = ;
break;
}
if (t >= tmax) {
result = ;
break;
}
t += res.x;
}
return result;
}
//计算碰撞点处物体表面的法线
float3 calcNormal(in float3 pos)
{
float3 eps = float3(0.0005, 0.0, 0.0);
float3 nor = float3(
map(pos + eps.xyy).x - map(pos - eps.xyy).x,
map(pos + eps.yxy).x - map(pos - eps.yxy).x,
map(pos + eps.yyx).x - map(pos - eps.yyx).x);
return normalize(nor);
}
void BasicPhong(fixed3 lightDir, fixed3 normalDir, fixed3 viewDir, float matIndex, out float3 color1, out float3 color2) {
, Kd = , Ks = , Shininess = ;
float3 matColor = float3();
switch (matIndex) {
:
//极远处
matColor = float3(, , );
Ka = ; Ks = ; Kd = ;
break;
:
matColor = float3(0.1, 0.1, 0.1);
Ks = ;
break;
:
matColor = float3(); Shininess = ;
break;
:
matColor = float3(, 0.5, 0.5);
break;
:
matColor = float3(, 0.5);
break;
default:
break;
}
&& matIndex >-) {
Kd = lerp(Kd, , -matIndex);
Ks = lerp(Ks, , -matIndex);
Ka = lerp(Ka, , -matIndex);
}
float3 amibent = Ka * GlobalAmibent * matColor;
float3 diffuse = Kd * LightColor * clamp(dot(normalDir, lightDir), , ) * matColor;
fixed3 reflectDir = reflect(-lightDir, normalDir);
float3 specular = Ks * LightColor * pow(clamp(dot(viewDir, reflectDir), , ), Shininess) * matColor;
color1 = amibent;
color2 = diffuse + specular;
}
float3 render(in float3 ro, in float3 rd)
{
//投掷射线,获得与所场景物体的碰撞信息
float2 res = castRay(ro, rd);
float t = res.x;
float m = res.y;
float3 pos = ro + t*rd;
float3 nor = calcNormal(pos);
fixed3 lightPos = PointLightPos;
fixed3 lightDir = normalize(lightPos - pos);
float3 c1, c2;
BasicPhong(lightDir, nor, rd, m, c1, c2);
float isInShadow = IsInShadow(pos, lightDir);
float3 color = c1 + isInShadow * c2;
return color;
}
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//虚拟摄像机坐标
float3 ro = float3(,,-);
//投影面某点坐标
float3 p = float3(i.uv - float2();
//投掷射线
float3 rd = normalize(p - ro);
fixed4 col = fixed4(render(ro, rd).rgb, );
// gamma校正
col.rgb = pow(col.rgb, float3(0.4545, 0.4545, 0.4545));
return col;
}
ENDCG
}
}
}
Unity3D-RayMarch-几何图元-3添加阴影的更多相关文章
- TextView的一些高级应用(自定义字体、显示多种颜色、添加阴影)
1. 自定义字体可以使用setTypeface(Typeface)方法来设置文本框内文本的字体,而android的Typeface又使用TTF字体文件来设置字体所以,我们可以在程序中放入TTF字 ...
- osg 基本几何图元
转自:osg 基本几何图元 //osg 基本几何图元 // ogs中所有加入场景中的数据都会加入到一个Group类对象中,几何图元作为一个对象由osg::Geode类来组织管理. // 绘制几何图元对 ...
- iOS--为视图添加阴影
iOS–为视图添加阴影 情况一:视图添加圆角,在添加阴影 //阴影视图 self.viewShadow = [[UIView alloc]initWithFrame:CGRectMake(0, 0, ...
- view添加阴影无效
需求:需要给cell里的imageview添加阴影 问题:按照标准的代码添加阴影,然并卵:代码如下: imageview.layer.shadowColor = [[UIColor blackColo ...
- Swift - 给图片和按钮添加阴影边框
最近比较忙,想要做的事情有很多,能做出来的就只有一部份,我觉得也许是我没有计划和规律造成的,我需要坚持下去,今天写了一个swift2.0给按钮或者图片添加阴影的效果,就当做笔记吧:-) Swift C ...
- iOS TabBar添加阴影
效果图如下所示: 直接上代码 //移除顶部线条 self.tabBar.backgroundImage = [UIImage new]; self.tabBar.shadowImage = [UIIm ...
- CSS3 --添加阴影(盒子阴影、文本阴影的使用)
CSS3 - 给div或者文字添加阴影(盒子阴影.文本阴影的使用)CSS3定义了两种阴影:盒子阴影和文本阴影.其中盒子阴影需要IE9及其更新版本,而文本阴影需要IE10及其更新版本.下面分别介绍两种 ...
- css 添加阴影
添加阴影,分为内阴影和外阴影. inset:内阴影. 不写默认外阴影. box-shadow: 水平位移 垂直位移 模糊半径 #box-shadow{ -moz-box-shadow:5px 5p ...
- ios开发之--为父view上的子view添加阴影
项目中碰到一个问题,在tableview的headerview里面有很一个子view,设计师的要求是在下方添加一个阴影,效果如下: 以前的实现思路就是,代码如下: 添加阴影 调用视图的 layer C ...
随机推荐
- html 常用button事件
<input onclick="document.all.WebBrowser.ExecWB(1,1)" type="button" value=&quo ...
- C#递归生成HTML树,C#递归生成xml树
C#递归生成HTML树 public StringBuilder str = new StringBuilder(); //定义一个字符串 private void get_navigation_ ...
- setsockopt详解
Socket描述符选项[SOL_SOCKET] #include <sys/socket.h> int setsockopt( int socket, int level, int op ...
- 通过SID查找历史执行的SQL语句
这次某系统发生严重的阻塞,但是去查顶级会话,发现已经没有该对应的sql_id了,于是我们只用通过 v$active_session_history 视图来寻找.下面是查找的过程: 1.查找顶层ASH历 ...
- 关于Float.parseFloat()的一点探讨
最近在解决线上的bug时,遇到一个问题. 第三方传过来的课程编码时4214410000,然而我们存进数据库的值却变成了4214409980.查遍了所有的代码都查不到有对这个值修改的代码.最后,通过打印 ...
- django settings多环境配置
通常我们会把本地.线上的配置拆分,django不同环境的配置可如下: 1.在settings.py同级目录添加settings文件夹 2.把settings.py移到settings文件夹内,并重命名 ...
- centos病毒
#!/bin/bash exec &>/dev/null {echo,ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYm ...
- JSON Web Token(缩写 JWT) 目前最流行的跨域认证解决方案
一.跨域认证的问题 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和密码. 2.服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色.登录时间等等. ...
- css 动态线条制作方案
利用 :before or :after 在元素中添加线条样式: 设置样式的过渡效果属性值: 改变width,left,transform等属性值,设置鼠标移入:hover 效果: li: ...
- Spring 配置 定时任务
官档地址:https://docs.spring.io/spring/docs/5.1.4.RELEASE/spring-framework-reference/integration.html#sc ...