效果
基本思路
根据摄像机的位置,面朝的方向,摄像机距离屏幕的距离,将uv也就是像素在屏幕上的坐标转换成三维空间中的坐标。
实现细节
创建一个摄像机需要两个变量,摄像机的位置和朝向的方向。
vec3 ro :摄像机的位置。
vec3 lookAt :摄像机看向的位置的坐标。
float zoom :摄像机到屏幕的距离。
当画一个点时,需要输入三个参数,ro,rd(摄像机位置到当前在计算的像素之间的向量),p(点的位置)。
若要得到rd,则需要将该像素在屏幕坐标系上坐标转换到三维世界坐标。
只要算出了图中f,r,u三个单位向量,就可以算出i点坐标。
i = c + uv.x * r + uv.y * u;
f向量等于lookAt减去ro,再单位化。
r = cross((0,1,0),f);就是将f和向上的单位向量叉乘,叉乘几何意义就是求出与两个向量同时垂直的向量。
u= corss(f,r);同理
c = ro + zoom*f;
float Distance(vec3 ro,vec3 rd,vec3 p){
return length(cross(rd,p-ro))/length(rd);
}
float drawPoint(vec3 ro,vec3 rd,vec3 p){
return smoothstep(0.1,0.09,Distance(ro,rd,p));
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
uv-=.5;
uv.x*=iResolution.x/iResolution.y;
// Time varying pixel color
float t = iTime;
float zoom = 1.;
vec3 col = vec3(0.);
vec3 lookAt = vec3(.5);
vec3 ro = vec3(sin(t)*2.,cos(t)*2.,-4.);
vec3 f = normalize(lookAt-ro);
vec3 r = cross(vec3(0.,1.,0.),f);
vec3 u = cross(f,r);
vec3 c = ro+zoom*f;
vec3 i = c + uv.x*r+uv.y*u;
vec3 rd = i - ro;
col+=drawPoint(ro,rd,vec3(0.,0.,0.));
col+=drawPoint(ro,rd,vec3(0.,0.,1.));
col+=drawPoint(ro,rd,vec3(0.,1.,0.));
col+=drawPoint(ro,rd,vec3(1.,0.,0.));
col+=drawPoint(ro,rd,vec3(1.,1.,0.));
col+=drawPoint(ro,rd,vec3(1.,0.,1.));
col+=drawPoint(ro,rd,vec3(0.,1.,1.));
col+=drawPoint(ro,rd,vec3(1.,1.,1.));
// Output to screen
fragColor = vec4(col,1.0);
}