XDRender_Volumn_ImageRenderPass RayMarchine -1
XDRender_Volumn_ImageRenderPass RayMarchine -1
@Author:白袍小道
目录
前言
作为体积渲染,RayMachine是一种不错的选择,这里我们先用RayMachine来画一个球.
这里实现是作为ImageRenderPass的可选项
正文
理论
后续补上来
RayMachine定义
RayMarching:光线行进,从摄像机向屏幕上的每一个像素发射一条光线,光线按照一定步长前进,检测当前光线距离物体表面的距离(这里我们可以定义为距离形状函数或者有向距离场SDF),并且根据这个距离调整光线的步长,直到抵达物体表面.同时搞事情(填充部分)
RayMachine特性
不错的原因是由于可以处理一些
1、对于形状不固定,且比较离散
2、由于是动态计算出的形状,你可以理解为矢量边缘.
3、利用步进函数来确定形状或者结合其他
RayMachine的基础步骤
略:后面再补上
实现
1、确定处理阶段(Pass)
这里我是放在ImageRenderPass的FeaturePass部分, 因为不想和后处理冲突.且按照定义,作为基于图像的绘制. 毕竟Raymarchine的主实现还是像画家一样去描绘.
2、加入到对应的节点
3、加入对应的HLSL, 代码、Shader
顶点着色
XDArt_ImageRender.hlsl
ImageRender_Varyings ImageRenderPassVert(appdata v)
{
ImageRender_Varyings o;
float4 clipVec = UnityObjectToClipPos(v.vertex);
o.vertex = clipVec;
float3 viewPosition = mul(unity_CameraInvProjection, clipVec.xyzz).xyz;
// 这里深度为0
// float depth = UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, i.screenPos));
// float3 viewPos = viewPosition * Linear01Depth(depth);
float3 worldPos = mul(UNITY_MATRIX_I_V, float4(viewPosition, 1.0)).xyz;
o.worldPos = worldPos;
o.uv = v.uv;
return o;
}
片段
其中
mainColor + raymarch (_WorldSpaceCameraPos.xyz,viewDirection,lightDirection);是为了叠加原来的处理结果. 故而主函数判断若不在范围范围0.0
float4 fragRay (ImageRender_Varyings i ) : SV_TARGET
{
half4 mainColor = tex2D (_MainTex, i.uv);
float3 worldPosition = i.worldPos;
float3 viewDirection = normalize(i.worldPos - _WorldSpaceCameraPos.xyz);
float3 lightDirection = normalize(UnityWorldSpaceLightDir(i.worldPos).xyz);
return mainColor + raymarch (_WorldSpaceCameraPos.xyz,viewDirection,lightDirection);
}
主函数
float4 raymarch (float3 rayOrigin, float3 rayDirection,float3 lightDir)
{
for (int i=0; i<256; i++)
{
float ray = DistanceFunction(rayOrigin);
if(_Limit != 0)
{
if (distance(rayOrigin,ray*rayDirection)>250)
break;
}
if (ray < _MinDistance)
return float4 (lighting(rayOrigin,lightDir,rayDirection),1.0);
else
rayOrigin+=ray*rayDirection;
}
return float4 (0.0,0.0,0.0,0.0);
}
形状函数--有向距离场SDF
///
//距离函数-用来确定形状
///
float DistanceFunction (float3 p)
{
return length(p)-_Radius;
}
光照(颜色处理)
///
//光照函数-用来绘制
///
float3 lighting (float3 rayOrigin,float3 lightDir,float3 viewDir)
{
return lerp(0.2,1.0,dot(lightDir,viewDir)) * _Color.xyz;
}
数据
HLSLINCLUDE
#include "Packages/com.xdgameengine.unity/EngineResource/ShaderLibrary/CoreExtends/XDArt_ImageRender.hlsl"
float _Limit;
float _MinDistance;
float _Radius;
float4 _Color;
总结
还没想好如何表达感慨, 但确实很好就对了
备注
1、参考大全:ShaderToy
人生当苦,笑着看看