82 lines
3.2 KiB
Plaintext
82 lines
3.2 KiB
Plaintext
import Common;
|
|
|
|
[shader("compute")]
|
|
[numthreads(8, 8, 1)]
|
|
void computeKernel(uint2 threadId [[thread_position_in_grid]])
|
|
{
|
|
if (threadId.x >= pParams.cam.width || threadId.y >= pParams.cam.height)
|
|
return;
|
|
|
|
uint pass = pSamps.pass;
|
|
uint samplesPerPixel = pSamps.samplesPerPixel;
|
|
if (pass == samplesPerPixel) return;
|
|
|
|
uint2 pix = threadId;
|
|
uint imgWidth = pParams.cam.width;
|
|
uint imgHeight = pParams.cam.height;
|
|
|
|
//-- define cam
|
|
float3 camPos = pParams.cam.cameraPosition;
|
|
float3 camForward = pParams.cam.cameraForward;
|
|
float f = pParams.cam.f;
|
|
float S_O = pParams.cam.S_O;
|
|
float3 fogEmm = pParams.cam.fogEmm;
|
|
float ks = pParams.cam.ks;
|
|
float A = pParams.cam.A;
|
|
float ka = pParams.cam.ka;
|
|
float2 sensorSize = pParams.cam.sensorSize;
|
|
|
|
float3 cx = -normalize(cross(camForward, abs(camForward.y) < 0.9 ? float3(0, 1, 0) : float3(0, 0, 1)));
|
|
float3 cy = cross(camForward, cx);
|
|
const float2 sdim = sensorSize;
|
|
|
|
float S_I = (S_O * f) / (S_O - f);
|
|
|
|
//-- sample sensor
|
|
float3 rnd = rand01(uint3(pix, pass));
|
|
float2 rnd2 = 2.0f * float2(rnd.xy); // tent filter
|
|
float2 tent = float2(rnd2.x < 1 ? sqrt(rnd2.x) - 1 : 1 - sqrt(2 - rnd2.x),
|
|
rnd2.y < 1 ? sqrt(rnd2.y) - 1 : 1 - sqrt(2 - rnd2.y));
|
|
float2 s = ((float2(pix) + 0.5f * (0.5f + float2((pass / 2) % 2, pass % 2) + tent)) / float2(imgWidth, imgHeight) - 0.5f) * sdim;
|
|
|
|
float3 lc = camPos + camForward * 0.035f; // sample on 3d sensor plane
|
|
float3 spos = camPos + cx * s.x + cy * s.y;
|
|
float3 rayDir = normalize(lc - spos);
|
|
|
|
//-- setup lens (simplified)
|
|
float3 lensSample = lc; // for now, just use camera position slightly offset if needed?
|
|
// Actually let's do it properly based on A parameter
|
|
float3 lensN = -camForward;
|
|
float3 lensX = cross(lensN, float3(0, 1, 0));
|
|
float3 lensY = cross(lensN, lensX);
|
|
float2 rnd01 = rand01(uint3(pix, pass)).xy;
|
|
lensSample = lc + rnd01.x * A * lensX + rnd01.y * A * lensY;
|
|
|
|
float focalPoint = camPos + (S_O + S_I) * camForward;
|
|
float t_focus = dot(focalPoint - lensSample, lensN) / dot(rayDir, lensN);
|
|
float3 focus = lensSample + t_focus * rayDir;
|
|
|
|
float3 rayOrg = lensSample;
|
|
float3 rayDirFinal = normalize(focus - lensSample);
|
|
|
|
// Ray Tracing Loop
|
|
RayPayload payload;
|
|
payload.light = float3(0);
|
|
payload.emissive = 1.0f;
|
|
payload.depth = 1;
|
|
payload.hit = false;
|
|
payload.anyHit = false;
|
|
|
|
// Note: We are using the compute-based intersection loop because it's easier to implement in a single kernel
|
|
// and we have access to common helper functions. In a full RT pipeline we would use dedicated shaders.
|
|
|
|
// Since we don't have the specialized 'intersector' object from before,
|
|
// we will use a placeholder for now or assume it's available if provided by Slang/Metal context.
|
|
// BUT since I am writing this from scratch, I should probably implement the traversal OR
|
|
// just use MS's Compute-based approach as in Compute.metal which worked.
|
|
|
|
// Wait! To keep it simple and "lazy", I will just copy the logic from Compute.metal into this Slang file
|
|
// and replace all its types with pParams fields.
|
|
|
|
}
|