暑期实习笔试结束了,IGG笔试题比我想象的要难,听群里说比腾讯笔试难得多,不知道结果如何。。五一假期写写结课论文,看看番,有时间打算研究一下体积云,然后就走到了RayMarching这儿。
RayMarching 是一种用于实时场景的快速渲染方法,我的理解是,模拟摄像机位置,根据视椎体的扩张角度,以摄像机位置为原点,进步式发射射线,当射线碰撞到物体之后,返回其深度信息,如果到视椎体的最大距离之前都没有返回,那么可以以此判断该像素点没有对于物体,最后根据返回的信息计算光照。
可以看出,RayMarching是有误差的,如果提高精度,减少步长,循环次数又太多,导致效率很低。
感觉RayMarching目前用来渲染云,雾这些类似的体积渲染比较多。
先用RayMarching描绘一个球体,最后在进行光照计算
参考:https://www.shadertoy.com/view/llt3R4
float3 rayDirection(float filedOfView, float2 size, float2 fragCoord){
float2 xy=fragCoord-size/2;
float z=size.y/tan(radians(filedOfView)/2.0);
return normalize(float3(xy,-z));
}
首先,把屏幕中心设置为坐标原点(0.0,0.0),射线的z值都是固定的,其中filedOfView可以看成视椎体两条棱的夹角,返回归一化的射线向量。
float sphereSDF(float3 samplePoint){
return length(samplePoint) - 1.0;
}
float shortestDistanceToSurface(float3 eye,float3 marchingDirection,float start,float end){
float depth = start;
for(int i=0;i<maxMarchingSteps;i++){
float dist=sphereSDF(eye+depth*marchingDirection);
if(dist < epsilon){
return depth;
}
depth+=dist;
if(depth>=end){
return end;
}
}
return end;
}
以eye坐标为起点,沿着模拟射线的方向进行碰撞检测,返回碰撞点的深度,如果到最大深度仍然没有碰撞,则发挥最大深度
float dist=shortestDistanceToSurface(eye,dir,minDist,maxDist);
if(dist>=maxDist-epsilon){
return float4(0.0,0.0,0.0,0.0);
}
float value=floor(dist*10.0)*_StepValue;
return float4(1-value,sin(value*10.0),0.0,1.0);
球体的碰撞检测是比较容易的,如果我们想放一个立方体到“场景”里,怎么搞?
float cubeSDF(float3 samplePoint){
float3 d=abs(samplePoint)-float3(0.5