FabricateDirectLighting.kt
src/jvmMain/kotlin/afield/graphics/scene/fabricated/FabricateDirectLighting.kt · 54 lines
package afield.graphics.scene.fabricated
import afield.graphics.render.lighting.*
import afield.math.linalg.Matrix4f
import afield.math.linalg.Vector3f
import afield.math.linalg.Vector4f
What connects StandardRenderer's raster bundle to the ray-traced DirectLighting pass.
That pass needs a G-buffer and a ray-visibility scene that agree about where the surfaces are.
registerOpaqueTriangles fills the raster G-buffer from the same indexed OpaqueTriangles
snapshot the ray acceleration structure keeps, expanding it once for the pulling shader instead
of uploading geometry every frame. directLighting then hands the bundle's G-buffer images and
its post-stack output to the pass, and rtxdiSettings supplies the camera contract the
optional RTXDI path wants, read from the bundle's own raster projection.
Opaque diffuse surfaces only: transparency, textured emission and latent pigments want an adapter nothing here provides yet.
fun StandardRenderer.Bundle.directLighting(visibility: OpaqueRayScene, name: String = "direct-light"): DirectLighting
Build the experiment from Fabricate's existing G-buffer. Call bundle.attachTo first, then lighting.attach; present lighting.output. SOURCE reads the unchanged post-stack output. Opaque diffuse only: transparency, textured emission and latent pigments require a future adapter.
fun StandardRenderer.Bundle.directLighting(visibility: OpaqueRayScene, name: String = "direct-light"): DirectLighting {
val source=postStack.output()
return DirectLighting(gBuffer.renderer,DirectLightSurfaces(gBuffer.imageViewArray[2],gBuffer.imageViewArray[1],
gBuffer.imageViewArray[0],source,gBuffer.imageViewArray[3]),visibility,gBuffer.width,gBuffer.height,name)
}
fun StandardRenderer.Bundle.rtxdiSettings()
Camera contract for the optional RTXDI pass, matching this bundle's raster projection.
fun StandardRenderer.Bundle.rtxdiSettings() = RtxdiSettings(
{ scene.camera.modelView() }, { scene.projection.evaluateUniform() })
fun StandardRenderer.Bundle.registerOpaqueTriangles(name: String, geometry: OpaqueTriangles,
Populate the existing raster G-buffer from the SAME indexed snapshot used for ray visibility. Fabricate's current pulling shader consumes expanded vec4 triangles; the adapter expands once. The ray BLAS keeps indexed XYZ data. No per-frame geometry upload or silent alpha approximation.
fun StandardRenderer.Bundle.registerOpaqueTriangles(name: String, geometry: OpaqueTriangles,
color: Vector3f = Vector3f(0.7f), transform: Matrix4f = Matrix4f()): StandardRenderer.Bundle.PullingMeshPair {
val mesh=registerPullingMesh(name,geometry.indexData.size,gBuffer.renderer)
for(t in geometry.indexData.indices step 3) {
fun point(i: Int): Vector3f { val n=geometry.indexData[t+i]*3;return Vector3f(geometry.vertexData[n],geometry.vertexData[n+1],geometry.vertexData[n+2]) }
val a=point(0);val b=point(1);val c=point(2)
val n=Vector3f(b).sub(a).cross(Vector3f(c).sub(a)).normalize()
for(p in listOf(a,b,c)) {
mesh.gBuffer.position.append { put(p.x,p.y,p.z,1f) }
mesh.gBuffer.normal.append { put(n.x,n.y,n.z,0f) }
}
}
mesh.setVertexCount(geometry.indexData.size).setModel(transform)
mesh.gBuffer.mesh.push["baseColor"]=Vector4f(color,1f)
return mesh
}