.constf myconst(0.0, 1.0, 0.01, 1000.0) .constf myconst2(0.5, 999.0, 0.0, 0.0) .alias zeros myconst.xxxx .alias halfs myconst2.xxxx .alias ones myconst.yyyy .alias near myconst.zzzz .alias far myconst.wwww .alias noHit myconst2.yyyy .consti bounceLoopParams(3, 0, 1, 0) .consti calcSphereLoopParams(2, 0, 1, 0) .setb b0 true .alias true b0 ; xyz center (in world space) ; w radius (in world space) .fvec spheres[3] ; material albedo .fvec sphereColors[3] ; random numbers .fvec rand[4] .in inOrigin v0 .in inLowerLeftCorner v1 .in inHorizontal v2 .in inVertical v3 .in inST v4 .in inPos v5 .in inUV v6 .out outPos position .out outUV texcoord0 .out outColor color .proc main ; outPos = inPos mov outPos, inPos ; outUV = inUV mov outUV, inUV ; r1 = inOrigin mov r1, inOrigin ; r2 = inDirection mov r2.xyz, inLowerLeftCorner mov r3.xy, inST.xy mad r2.xyz, inHorizontal, r3.x, r2.xyz mad r2.xyz, inVertical, r3.y, r2.xyz ; set initial color to (1, 1, 1) ; as lights are not implemented yet mov r4.xyz, ones ; calculate light bounces for bounceLoopParams ; setup random numbers for this iteration mov r11, rand[aL] ; reset max ray distance mov r4.w, far ; set albedo to a large number for sphere hit check mov r10.xyz, far ; for each sphere for calcSphereLoopParams ; r3 = spheres[i] mov r3, spheres[aL] ; do calculation ; call calcSphere ; vec3 oc = origin - center add r8.xyz, r1.xyz, -r3.xyz ; float a = dot(direction, direction) dp3 r9.x, r2.xyz, r2.xyz ; float halfB = dot(oc, direction) dp3 r9.y, r8.xyz, r2.xyz ; float radiusSquared = radius * radius mul r8.w, r3.w, r3.w ; float c = dot(oc, oc) - radius * radius dp3 r9.z, r8.xyz, r8.xyz add r9.z, r9.z, -r8.w ; float halfBSquared = halfB * halfB; mul r8.w, r9.y, r9.y ; float ac = a * c; mul r9.w, r9.x, r9.z ; float discriminant = bSquared - ac add r8.w, r8.w, -r9.w ; if discriminant < 0, exit procedure early cmp zeros, gt, gt, r8.w jmpc cmp.x, calcSphereExit ; calculate t ; float sqrtDiscriminant = sqrt(discriminant) rsq r8.w, r8.w rcp r8.w, r8.w ; a = 1 / a rcp r9.x, r9.x ; float root = (-halfB - sqrtDiscriminant) / a add r9.z, -r9.y, -r8.w mul r9.z, r9.z, r9.x ; if root < min distance, check other root cmp near, gt, gt, r9.z jmpc cmp.x, calcSphereCheckOtherRoot ; if root > max distance, check other root cmp r9.z, gt, gt, r4.w jmpc cmp.x, calcSphereCheckOtherRoot ; if root is in range, finalize calculations jmpu true, calcSphereFin calcSphereCheckOtherRoot: ; float root = (-halfB + sqrtDiscriminant) / a add r9.z, -r9.y, r8.w mul r9.z, r9.z, r9.x ; if root < min distance, check other root cmp near, gt, gt, r9.z jmpc cmp.x, calcSphereExit ; if root > max distance, check other root cmp r9.z, gt, gt, r4.w jmpc cmp.x, calcSphereExit calcSphereFin: ; change max distance to closest hit mov r4.w, r9.z ; calculate new origin mul r5.xyz, r2.xyz, r9.zzz add r5.xyz, r5.xyz, r1.xyz ; calculate normal add r7.xyz, r5.xyz, -r3.xyz rcp r3.w, r3.w mul r7.xyz, r7.xyz, r3.w ; set albedo mov r10.xyz, sphereColors[aL].xyz ; early exit label calcSphereExit: nop ; done with calculation .end ; check if noHit > albedo cmp noHit.xyz, le, le, r10.xyz breakc cmp.x jmpc cmp.x, noHitLabel ; multiply color by albedo mul r4.xyz, r4.xyz, r10.xyz ; set r1 to new ray origin mov r1.xyz, r5.xyz ; set r2 to new ray direction add r2.xyz, r7.xyz, r11.xyz .end noHitLabel: ; copy final color to output mov outColor.xyz, r4.xyz ; set alpha to 1 mov outColor.w, ones end .end ; Calculate Sphere Intersection ; ----------------------------- ; ; Inputs ; ------ ; r1.xyz: ray origin ; r2.xyz: ray direction ; r3.xyz: sphere origin ; r3.w: sphere radius ; r4.w: min distance ; r11.xyzw: random numbers ; ; Outputs ; ------- ; r4.w: new min distance ; r10.xyz: albedo ; ; Temporaries ; ----------- ; r5.xyz: new origin ; r6.xyz: new direction ; r7.xyz: hit normal ; r8.xyzw: used for calculations ; r9.xyzw: used for calculations