shadertoy上的第二个关于ray marching的教程
关于viewspace 转 worldspace 的推导:http://blog.csdn.net/silangquan/article/details/50987196
float minDist=0.0;
float maxDist=100.0;
/**
* Signed distance function for a cube centered at the origin
* with width = height = length = 2.0
*/
float cubeSDF(vec3 p) {
// If d.x < 0, then -1 < p.x < 1, and same logic applies to p.y, p.z
// So if all components of d are negative, then p is inside the unit cube
vec3 d = abs(p) - vec3(1.0, 1.0, 1.0);
// Assuming p is inside the cube, how far is it from the surface?
// Result will be negative or zero.
float insideDistance = min(max(d.x, max(d.y, d.z)), 0.0);
// Assuming p is outside the cube, how far is it from the surface?
// Result will be positive or zero.
float outsideDistance = length(max(d, 0.0));
return insideDistance + outsideDistance;
}
float getDist(vec3 cameraOrign , vec3 dir ){
float depth=minDist;
for(int i =0;i<255;i+=1){
vec3 rayPosition=cameraOrign+depth*dir;
float dist=cubeSDF(rayPosition);
if(dist<0.01){
return depth;
}
depth+=dist;
if(depth>=maxDist){
return maxDist;
}
}
return maxDist;
}
/**
* Return a transform matrix that will transform a ray from view space
* to world coordinates, given the eye point, the camera target, and an up vector.
*
* This assumes that the center of the camera is aligned with the negative z axis in
* view space when calculating the ray marching direction. See rayDirection.
*/
mat4 viewMatrix(vec3 eye, vec3 center, vec3 up) {
// Based on gluLookAt man page
vec3 f = normalize(center - eye);
vec3 s = normalize(cross(f, up));
vec3 u = cross(s, f);
return mat4(
vec4(s, 0.0),
vec4(u, 0.0),
vec4(-f, 0.0),
vec4(0.0, 0.0, 0.0, 1)
);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 size= iResolution.xy;
vec2 rayMarchXY=fragCoord-size/2.;
float fieldOfView=45.0;
float z = size.y / tan(radians(fieldOfView) / 2.0);
vec3 rayDir=normalize( vec3(rayMarchXY,-z) );
vec3 cameraOrign=vec3( -8,5 , 20);
mat4 viewToWorld = viewMatrix(cameraOrign, vec3(0.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
vec3 worldDir = (viewToWorld * vec4(rayDir, 0.0)).xyz;
float dist=getDist(cameraOrign,worldDir);
if(dist>maxDist-0.001){
fragColor=vec4(0.0,0.0,0.0,1.0);
return;
}
vec3 p = cameraOrign + dist * worldDir;
vec3 K_a = vec3(0.2, 0.2, 0.2);
vec3 K_d = vec3(0.7, 0.2, 0.2);
vec3 K_s = vec3(1.0, 1.0, 1.0);
float shininess = 10.0;
vec3 color = vec3 (0.25,0.25,0.25);
vec3 light1Pos = vec3(4.0 * sin(iGlobalTime),
2.0,
4.0 * cos(iGlobalTime));
float EPSILON=0.001;
vec3 N = normalize(vec3(
cubeSDF(vec3(p.x + EPSILON, p.y, p.z)) - cubeSDF(vec3(p.x - EPSILON, p.y, p.z)),
cubeSDF(vec3(p.x, p.y + EPSILON, p.z)) - cubeSDF(vec3(p.x, p.y - EPSILON, p.z)),
cubeSDF(vec3(p.x, p.y, p.z + EPSILON)) - cubeSDF(vec3(p.x, p.y, p.z - EPSILON))
));
vec3 L = normalize(light1Pos - p);
float dotLN = dot(L, N);
if (dotLN < 0.0) {
color+= vec3(0.0, 0.0, 0.0);
}
color+= vec3( dotLN,dotLN,dotLN);
fragColor = vec4(color, 1.0);
}