yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
371438027
master
1//TEST:LANG_SERVER(filecheck=CHECK): 2 3RWTexture2D<float4> texFrame; // Output texture 4uniform float iTime; 5// In seconds 6uniform float2 iResolution; // Screen size 7 8static const float kInfinity = asfloat(0x7f800000); 9static const uint32_t kIdNone = 0xFFFFFFFF; 10 11struct Intersection 12{ 13 float t = kInfinity; 14 uint32_t id = kIdNone; 15 16 bool missed() { 17 return id == kIdNone; 18 } 19 20 [mutating] 21 void update(uint32_t newId, float newT) 22 { 23 if(newT >= 0 && newT < t) 24 { 25 t = newT; 26 id = newId; 27 } 28 } 29}; 30 31struct Ray 32{ 33 float3 origin; 34 float3 direction; 35 float3 at(float t) 36 { 37 return mad(origin, direction, float3(t)); 38 } 39}; 40 41// Returns the t-value of the intersection of the infinite line 42// with the plane given by 43// `dot(planeNormal, p) == planeDist`. 44float intersectPlane(Ray ray, float3 planeNormal, float planeDist) 45{ 46 // dot(planeNormal, o + d * t) == planeDist 47 // -> dot(planeNormal, o) + t * dot(planeNormal, d) == planeDist 48 // -> t = (planeDist - dot(planeNormal, o)) / dot(planeNormal, d) 49 return (planeDist - dot(planeNormal, ray.origin)) 50 / dot(planeNormal, ray.direction); 51} 52 53float2 sortLoHi(float2 v) 54{ 55 56 57struct OBB 58{ 59 // Note that these are more parameters than we need; 60 // technically, the sides of an OBB must all be perpendicular, 61 // so there's only 3 (position) + 3 (side lengths) + 3 (rotation) 62 // degrees of freedom. 63 float3 corner; 64 float3 edges[3]; 65 66 // Returns the t-value of the intersection of the OBB with 67 // the ray. 68 // The returned t-value may be negative; i.e. this assumes 69 // the camera is outside of the box. 70 // On miss, returns infinity. 71 float intersect(Ray ray) 72 { 73 ray.origin -= corner; 74 75 float2 tCloseFar; 76 float tFar; 77 [ForceUnroll] 78 for(int i = 0; i < 3; i++) 79 { 80 const float3 edge = edges[i]; 81 const float edgeDist = dot(edge, ray.origin); 82 const float factor = rcp(dot(edge, ray.direction)); 83 float2 slab = (float2(0, dot(edge, edge)) - edgeDist) 84 * factor; 85 slab = 86 if(i == 0) 87 { 88 tClose = min(slab.x, slab.y); 89 tFar = max(slab.x, slab.y); 90 } 91 else 92 { 93 tClose = min3(tClose, slab.x, slab.y); 94 tFar = max3(tFar, slab.x, slab.y); 95 } 96 thisSlab = sortLoHi(thisSlab); 97 tCloseFar.x = 98 } 99 return kInfinity; 100 } 101}; 102 103[shader("compute")] 104[numthreads(16, 16, 1)] 105void main(uint2 thread: SV_DispatchThreadID) 106{ 107 float2 uv = (2.0 * float2(thread) - iResolution.xy) / iResolution.y; 108 109 // Right-handed Z-up coordinate system, same as Blender's 110 Ray ray; 111 ray.origin = float3(0, -4, 4); 112 static const float kSqrtP5 = sqrt(.5); 113 ray.direction = float3( 114 uv.x, 115 kSqrtP5 -kSqrtP5 * uv.y, 116 -kSqrtP5 -kSqrtP5 * uv.y 117 ); 118 119 Intersection intersection; 120 intersection.update(0, intersectPlane(ray, float3(0,0,1), 0)); 121 OBB obb = OBB(float3(-1,-1,-1),{float3(2,0,0),float3(0,2,0), float3(0,0,2)}); 122 intersection.update(1, obb.intersect(ray)); 123 124 float3 color; 125 if(intersection.missed()) 126 { 127 color = float3(0.0, 0.0, 1.0); 128 } 129 else 130 { 131 color = float3(intersection.t / 10.0); 132 } 133//COMPLETE:134,31 134 texFrame[thread] = float4(color, 1.0); 135} 136 137// CHECK: color