Render/RayMarchine/Base 1- 利用Frag绘制图形
@author: 白袍小道-胡言乱语
@Read: 转载说明
前言
1、RayMarching
*光线行进**,从摄像机向屏幕上的每一个像素发射一条光线,光线按照一定步长前进,检测当前光线距离物体表面的距离,并且根据这个距离调整光线的步长,直到抵达物体表面。
2、Frag绘制图形
在片段着色阶段去执行,这里注意一下
//1、片段后还有光栅,光栅的采样会有可能导致1-N 星盘
//2、片段还有机会可以改变SV_Depth
正文
这里强调一下RayMarching,更加关注的如何利用这个原理。是否从屏幕上每个Pixel出发,还是看需求。
RayMarching可以参考:
https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
https://zhuanlan.zhihu.com/p/90245545
目的
获取是否相交,相交的信息,我们就可以对该片元处理
Frag绘制图形
除了纹理和顶点描述,我们还可以有一种手段去做一些简单的图形。
这种手段基础:利用顶点到着色着色进行了线性的插值,然后在片元着色中,我们可以利用这些信息(如UV或者Proj, 坐标转到屏幕坐标),按照图形(求交)搞事情(非标准语言)。
绘制图形
这里因为是测试案例,直接作为特殊后期屏幕Quad绘制。
(偷懒一下,直接作为PostProcess阶段前插入一个RayMachineRCMD来执行。其中RCMD为XDGameEngine封装的一个,Quad为屏幕Mesh)
XDGameEngine_GraphicsUtility.BlitSRT(pPostContext.PostRenderCMD, pPostContext.SrcColorBuffer,BuiltinRenderTextureType.CameraTarget,_EffectMat,0);
其中BlitSRT就是一个向目标(这里由于不需要做DownSample什么的,就直接用了Context内置)绘制,
public void BlitSRT(CommandBuffer buffer, XDGTexture source, XDGRenderTargetIdentifier destination,
Material mat, int pass)
{
//buffer.SetGlobalTexture(XDGameEngine_GraphicsShaderID._MainTex, source);
mat.SetTexture(XDGameEngine_GraphicsShaderID._MainTex, source);
buffer.SetRenderTarget(destination);
buffer.DrawMesh(mesh, Matrix4x4.identity, mat, 0, pass);
}
备注:(直接用SV_Target,也可以自己包一个Struct包含SVDepth 后续来做脑洞)
求交
基础求交
直线包含公式:两点之间
float4 XD_Ray_Line2D(float2 pos, float2 point1, float2 point2, float width, float3 color, float antialias)
{
float k = (point1.y - point2.y)/(point1.x - point2.x);
float b = point1.y - k * point1.x;
float d = abs(k * pos.x - pos.y + b) / sqrt(k * k + 1);
float t = smoothstep(width/2.0, width/2.0 + antialias, d);
return float4(color, 1.0 - t);
}
圆形包含公式:距离圆心和半径
float4 XD_Ray_circle(float2 pos, float2 center, float radius, float3 color, float antialias)
{
float d = length(pos - center) - radius;
float t = smoothstep(0, antialias, d);
return float4(color, 1.0 - t);
}
三角形包含公式:三个DOT
float4 XD_Ray_Triangle(float2 p, float2 Pos1, float2 Pos2, float2 Pos3,float3 color)
{
float2 AB = Pos2-Pos1;
float2 BC = Pos3-Pos2;
float2 CA = Pos1-Pos3;
float2 AP = p - Pos1;
float2 BP = p - Pos2;
float2 CP = p - Pos3;
float3 cPAB = cross(float3(AP,.0),float3(AB,.0));
float3 cCAB = cross(float3(-CA,.0),float3(AB,.0));
bool bPA = dot(cPAB, cCAB) >= .0;
float3 cPAC = cross(float3(CP,.0), float3(CA,.0));
float3 cBAC = cross(float3(-BC,.0), float3(CA,.0));
bool bPC = dot(cPAC, cBAC) >= .0;
float3 cPBC = cross(float3(BP,.0), float3(BC,.0));
float3 cABC = cross(float3(-AB,.0), float3(BC,.0));
bool bPB = dot(cPBC, cABC) >= .0;
float t = bPC && bPB && bPA? 1:0;
return float4(color, t);
}
点和多边形求交
不只是这里有用,这里就不做展开。在Render/Acc(加速),和Render/Math部分会说明。
1、面积和判断
2、奇偶
射线法不仅仅适用于规则的矩形,也适用于多边形。
沿着点做多条射线,那么每条射线就会与多边形产生n个交点(0个交点也算)。若某一条射线产生奇数个交点,那么就认定点在多边形范围内。
3、转角累加法
多边形和多边形
1、分离轴定理
凸多边形的碰撞判断方式
2、凹多边形处理
把凹多边形进行分割,拆成凸多边形
3、基于四叉树
(https://zhuanlan.zhihu.com/p/83722268)
步进和二分
留作后续继续