// This raymarcher is intended for use as a regular geometry shader, experimenting here. dvb15 wip. #version 410 in vec3 worldPosV; // the point on the screen through which the current camera position projects. flat in vec3 cameraPointV; // TODO camera point could be a uniform? flat in vec4 positionAndRadiusV; uniform mat4 cameraMatrix; uniform float time; out vec4 fragColor; #include "commonPostprocessHelpers.glsl" vec2 castToSphere(vec3 p0, vec3 p1, vec3 ctr, float r) { // derived from http://math.stackexchange.com/questions/311921/get-location-of-vector-circle-intersection /* derived from http://math.stackexchange.com/questions/311921/get-location-of-vector-circle-intersection A = (x1-x0)^2 + (y1-y0)^2 + (z1-z0)^2 B = 2(x1-x0)(x0-h) + 2(y1-y0)(y0-j) + 2(z1-z0)(z0-k) C = (x0-h)^2 + (y0-j)^2 + (z0-k)^2 t = (-b +- √(b^2-4ac)) / 2a */ vec3 rayDir = p1 - p0; vec3 cDir = p0 - ctr; float a = dot(rayDir, rayDir); float b = 2.0 * dot(rayDir, cDir); float c = dot(cDir, cDir) - r * r; // if this part of the quadratic formula is positive, there are real solutions. float quadPart = b * b - 4.0 * a * c; if(quadPart < 0.0) return vec2(-1, -1); vec2 result; result[0] = (-b - sqrt(quadPart)) / (2.0 * a); result[1] = (-b + sqrt(quadPart)) / (2.0 * a); return result; } float glint2(vec3 spherePoint, vec3 eyePoint) { // assume sphere is centered at origin vec3 surfaceNormal = normalize(spherePoint); // -sphereCenter vec3 eyeVector = normalize(eyePoint - spherePoint); float d = dot(surfaceNormal, eyeVector); float g = cos(d * 15.0); vec3 r = reflect(-eyeVector, surfaceNormal); vec3 lightPos = vec3(5,5,5); vec3 lightVector = normalize(lightPos - spherePoint); d = dot(r, lightVector); g = cos(d * 15.0); return g; } void main( void ) { // gl_FragDepth = 1.0; // fragColor = vec4(0,1,0,0.3); //return; vec2 t2 = castToSphere(cameraPointV, worldPosV, positionAndRadiusV.xyz, positionAndRadiusV.w); int inside = 0; float t = t2[0]; if(t < 0.0) { t = t2[1]; inside = 1; } if(t < 0) discard; // we are in the sphere! find a color & depth for it. vec3 s = cameraPointV + t * (worldPosV - cameraPointV); // s is in world space, not screen space... vec3 sScreen = (cameraMatrix * vec4(s,1)).xyz; float sphereDepth = sScreen.z; // Writing the actual sphere depth value kills performance on some // graphics cards. But eliminates some render errors where things // are visible inside the sphere when they should not be. // uncomment for betterness, but... dvb2016 // gl_FragDepth = adepthSample(-sphereDepth); fragColor.rgb = vec3(0.0, 0.1, 0.2); if(inside == 0) fragColor.b = mod(floor(s.x/0.1) + floor(s.y/0.1) + floor(s.z/0.1), 2.0); else fragColor.r = mod(floor(s.x/0.3) + floor(s.y/0.3) + floor(s.z/0.1), 2.0); float d = distance(cameraPointV, s); float g = glint2(s, cameraPointV); fragColor.rgb += vec3(g / 2.0); fragColor.a = 1.0; }