/* point: Hit point view: View vector (camera ray) normal: Normal vector */ vec3 solve(vec3 hitPoint, vec3 view, vec3 normal) { // Lighting vec3 light_color = vec3(1.0, 1.0, 1.0); vec3 light_dir = normalize(hitPoint-vec3(0.0, 1.5, 4.0)); vec3 ambient = light_color * 0.1; vec3 diffuse = light_color * max(1.0-dot(normal, light_dir), 0.0); vec3 specular = light_color * pow(max(dot(view, reflect(-light_dir, normal)), 0.0), 32); // Combine colors vec3 object_color = vec3(0.0, 0.1, 0.5); return (ambient + diffuse + specular) * object_color; } /* * origin: Point hit on the node * dir: Camera view direction (ray direction) * addr: Number given by node, afaik brick offset in brick array */ vec4 castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr) { // Change scale origin = start - origin; origin += dir*0.00001; origin *= 32; // Same as in casting nodes vec3 pos = floor(origin); vec3 rayInv = 1.0/dir; vec3 raySign = sign(dir); vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv; ivec3 offset = ivec3(0, 0, (addr-1)*32); vec3 tmp = abs(raySign); for(int i=0;i<110;i++) { // Get brick uint brick = texelFetch(bricksTexture, offset+ivec3(pos), 0).r; if(brick != 0) { // Hit point vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv; float len = max(mini.x, max(mini.y, mini.z)); vec3 hitPoint = (origin + dir * len) / 32.0; // Normal vector (negate previous increment axis and mult by sign) vec3 normal = -incAxis * raySign; return vec4(solve(hitPoint, dir, normal), 1.0); } // Get new closest axis to increment incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy); dist += incAxis * raySign * rayInv; pos += incAxis * raySign; // Check for bounds if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; } if(pos.x > 31 || pos.y > 31 || pos.z > 31) { break; } } return vec4(0.5,0.5,0.5, 0.0); } /* * origin: Camera position * dir: Ray coming from camera position going through currently drawn pixel */ vec3 castNodes(vec3 origin, vec3 dir) { // Round input pos to nearest voxel vec3 pos = floor(origin); // Inverse ray direction vec3 rayInv = 1.0/dir; // Sign of the ray direction, to know where to increment pos vec3 raySign = sign(dir); // Distance to next voxel in grid vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv; // Closest axis to increment in grid will be stored here (x=1 or y=1 or z=1) vec3 incAxis = vec3(0,0,0); // Iterate for(int i=0;i<110;i++) { // Get node uint node = texelFetch(nodesTexture, ivec3(pos), 0).r; if(node != 0) { // Hit point vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv; float len = max(mini.x, max(mini.y, mini.z)); vec3 hitPoint = origin + dir * len; // Normal vector (negate previous increment axis and mult by sign) //vec3 normal = -incAxis * raySign; //return solve(hitPoint, dir, normal); // Cast brick vec4 result = castBricks(pos, hitPoint, dir, incAxis, node); if(result.a > 0.0) return result.rgb; //todo: continue if not hit } // Get new closest axis to increment incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy); dist += incAxis * raySign * rayInv; pos += incAxis * raySign; // Outside bounds //if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; } // if(pos.x > 1 || pos.y > 1 || pos.z > 1) { break; } } // Not found return vec3(0.0, 0.0, 0.0); }