rt3DS/source/vshader.v.pica

328 lines
6.5 KiB
Plaintext

.constf myconst(0.0, 1.0, 0.001, 1000.0)
.constf myconst2(0.5, 999.0, 1.1, 2.0)
.constf myconst3(0.5, 0.0, 0.0, 0.0)
.alias zeros myconst.xxxx
.alias halfs myconst2.xxxx
.alias ones myconst.yyyy
.alias twos myconst2.wwww
.alias tooclose myconst.zzzz
.alias far myconst.wwww
.alias noHit myconst2.yyyy
.alias samplesRCP myconst3.xxxx
.alias diffuseID myconst.xxxx
.alias metallicID myconst.yyyy
.alias dielectricID myconst2.wwww
.consti sampleLoopParams(4, 0, 1, 0)
.consti bounceLoopParams(9, 0, 1, 0)
; (NUM_SPHERES, 0, 1, 0)
.ivec calcSphereLoopParams
.setb b0 true
.alias true b0
; xyz center (in world space)
; w radius (in world space)
.fvec spheres[25]
; material albedo (xyz)
; material id (w)
.fvec sphereColors[25]
; material emitted light (xyz)
; extra material params (w)
.fvec sphereLights[25]
; random numbers
.fvec rand[10]
.fvec sampleRand[5]
.in inOrigin v0
.in inLowerLeftCorner v1
.in inHorizontal v2
.in inVertical v3
.in inST v4
.in inPos v5
.in inUV v6
.in inRand v7
.out outPos position
.out outUV texcoord0
.out outColor color
.proc main
mov r15.xyz, zeros
for sampleLoopParams
; 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 multiplier to (1, 1, 1)
mov r4.xyz, ones
; set initial color to (0, 0, 0)
mov r13.xyz, zeros
mov r14.xyz, sampleRand[aL].xyz
; calculate light bounces
for bounceLoopParams
; setup random numbers for this iteration
mov r11, rand[aL]
add r11.xyz, r11.xyz, r14.xyz
add r11.xyz, r11.xyz, inRand.xyz
dp3 r14.w, r11.xyz, r11.xyz
rsq r14.w, r14.w
mul r11.xyz, r11.xyz, r14.w
; 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
.end
; check if noHit < albedo
; and exit early if true
; as albedo has not been set
; after the initial set
; which only happens when
; a ray does not hit any spheres
cmp noHit.xyz, lt, lt, r10.xyz
; not using breakc. it behaves weird.
jmpc cmp.x, labl
; multiply color by albedo
mul r4.xyz, r4.xyz, r10.xyz
; add emitted light
mad r13.xyz, r4.xyz, r12.xyz, r13.xyz
; set r1 to new ray origin
mov r1.xyz, r5.xyz
; set r2 to new ray direction
; try diffuse material
cmp diffuseID.w, eq, eq, r10.w
callc cmp.x, diffuse
jmpc cmp.x, materialFound
; try metallic material
cmp metallicID.w, eq, eq, r10.w
callc cmp.x, metallic
jmpc cmp.x, materialFound
; try dielectric material
cmp dielectricID.w, eq, eq, r10.w
callc cmp.x, dielectric
jmpc cmp.x, materialFound
; material doesn't reflect light
; used mostly for light-emitting objects
jmpu true, labl
materialFound:
nop
.end
labl:
; add final color to output
add r15.xyz, r13.xyz, r15.xyz
.end
; divide by sample count
mul outColor.xyz, samplesRCP, r15.xyz
; set alpha to 1
mov outColor.w, ones
mov outPos, inPos
mov outUV, inUV
end
.end
; -----------------------------
; Calculate Sphere Intersection
; -----------------------------
; Performs a ray-sphere intersection test.
;
; Inputs
; ------
; r1.xyz: ray origin
; r2.xyz: ray direction
; r3.xyz: sphere origin
; r3.w: sphere radius
; r4.w: min distance
; r11.xyz: random unit vector
; r11.w: random number
;
; Outputs
; -------
; r4.w: new min distance
; r10.xyz: albedo
; r10.w: material id
; r12.xyz: light emitted
; r12.w: extra material info
;
; Temporaries
; -----------
; r5.xyz: new origin
; r7.xyz: hit normal
; r7.w: ray is outside sphere (1) or inside sphere (0)
; r8.xyzw: used for calculations
; r9.xyzw: used for calculations
.proc 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 tooclose, 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 tooclose, 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
mad r5.xyz, r2.xyz, r9.zzz, 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 and material type
mov r10.xyzw, sphereColors[aL].xyzw
; set light emitted and extra material info
mov r12.xyzw, sphereLights[aL].xyzw
; early exit label
calcSphereExit:
nop
.end
; ---------
; Materials
; ---------
; Calculates the new ray direction for a given material.
;
; Inputs
; ------
; r1.xyz: ray origin
; r2.xyz: ray direction
; r3.xyz: sphere origin
; r3.w: sphere radius
; r4.w: min distance
; r11.xyz: random unit vector
; r11.w: random number
;
; Outputs
; -------
; r2.xyz: new ray direction
; Diffuse Material
; ----------------
.proc diffuse
add r2.xyz, r7.xyz, r11.xyz
.end
; Metallic Material
; -----------------
.proc metallic
dp3 r6.xyz, r2, r7
mul r6.xyz, twos, r6.xyz
mad r2.xyz, -r6.xyz, r7.xyz, r2.xyz
; add a bit of random "fuzziness" to the metal
mad r2.xyz, r11.xyz, r12.w, r2.xyz
.end
; Dielectric Material
; -------------------
.proc dielectric
; currently diffuse material, implement fr later
add r2.xyz, r7.xyz, r11.xyz
.end