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 ...
随机推荐
- NodeJS-静态服务器
静态服务器 代码 const http = require('http') const chalk = require('chalk') const conf = require('./config/ ...
- Python for循环之图像练习
矩形 # 控制行 for i in range(1,5): # 控制列 for j in range(1,8): # 用end在末尾传入空格串,这样print函数就不会自动换行了 print('*', ...
- linux gcc 静态 动态链接库
静态链接库 首先生成依赖函数的目标文件 gcc -c source1.c source2.c; 然后归档目标文件到静态库 ar -rcs libYourID.a obj1.o obj2.o; 然后我们 ...
- 从 注解和继承 到 JAXB中的注意事项
从 注解和继承 到 JAXB中的注意事项 注解在继承中的行为 如果一个父类添加了一个注解,子类是否能取到这个注解呢?如下 package inheritance; import java.lang.a ...
- Python科学计算结果的存储与读取
Python科学计算结果的存储与读取 总结于2019年3月17日 荆楚理工学院 计算机工程学院 一.前言 显然,作为一名工科僧,执行科学计算,需用Python.PS:快忘记Matlab吧.我用了二十 ...
- React列表
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((numbers) => <li>{numbers}&l ...
- 运行UMAT:+ABQ和VS、IVF绑定
运行UMAT: 1.run-script----xxxx.py2.属性---编辑材料---通用---非独立变量---用户材料3.job---编辑作业---通用----用户子程序.for4.parall ...
- 用phpstudy配置网站遇到的一些问题
第一次是配置在我本机,总是连不上数据库,后来查看到mysql.ini配置文件里面端口号有一个不是3306,更改之后就好了. 第二次是配置在笔记本电脑上,安装的时候比较顺利,也就遇到80端口被占用还有缺 ...
- Oracle 批量修改字段长度
Oracle 批量修改字段长度 SELECT 'alter table '||a.table_name||' MODIFY '||A.COLUMN_NAME||' VARCHAR2(100);' ...
- js前台计算两个日期的间隔时间
js前台计算两个日期的间隔时间(时间差)原创 2017年08月28日 16:09:43 标签:javascript 1144在后台传来两个时间字段,从中解析出两个字符串类型的日期格式 需要在前台解析出 ...