diff --git a/build.gradle.kts b/build.gradle.kts index 4b61a0fb0..6660086d0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -95,11 +95,11 @@ dependencies { } } implementation("org.xerial.snappy:snappy-java:1.1.10.5") - implementation("com.fasterxml.jackson.core:jackson-databind:2.16.1") + implementation("com.fasterxml.jackson.core:jackson-databind:2.17.0") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.1") - implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.1") - implementation("org.zeromq:jeromq:0.5.4") - implementation("com.esotericsoftware:kryo:5.5.0") + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.0") + implementation("org.zeromq:jeromq:0.6.0") + implementation("com.esotericsoftware:kryo:5.6.0") implementation("de.javakaffee:kryo-serializers:0.45") implementation("org.msgpack:msgpack-core:0.9.8") implementation("org.msgpack:jackson-dataformat-msgpack:0.9.8") diff --git a/src/main/kotlin/graphics/scenery/backends/RenderConfigReader.kt b/src/main/kotlin/graphics/scenery/backends/RenderConfigReader.kt index 781600e97..06de2c9c4 100644 --- a/src/main/kotlin/graphics/scenery/backends/RenderConfigReader.kt +++ b/src/main/kotlin/graphics/scenery/backends/RenderConfigReader.kt @@ -183,11 +183,11 @@ class RenderConfigReader { mapper.registerModule( KotlinModule.Builder() .withReflectionCacheSize(512) - .configure(KotlinFeature.NullToEmptyCollection, false) - .configure(KotlinFeature.NullToEmptyMap, false) + .configure(KotlinFeature.NullToEmptyCollection, true) + .configure(KotlinFeature.NullToEmptyMap, true) .configure(KotlinFeature.NullIsSameAsDefault, false) - .configure(KotlinFeature.SingletonSupport, false) - .configure(KotlinFeature.StrictNullChecks, false) + .configure(KotlinFeature.SingletonSupport, true) + .configure(KotlinFeature.StrictNullChecks, true) .build() ) diff --git a/src/main/kotlin/graphics/scenery/controls/OpenVRHMD.kt b/src/main/kotlin/graphics/scenery/controls/OpenVRHMD.kt index 1f661221f..6de3f2828 100644 --- a/src/main/kotlin/graphics/scenery/controls/OpenVRHMD.kt +++ b/src/main/kotlin/graphics/scenery/controls/OpenVRHMD.kt @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.dataformat.yaml.YAMLFactory +import com.fasterxml.jackson.module.kotlin.KotlinFeature import com.fasterxml.jackson.module.kotlin.KotlinModule import graphics.scenery.* import graphics.scenery.backends.Display @@ -1271,7 +1272,15 @@ open class OpenVRHMD(val seated: Boolean = false, val useCompositor: Boolean = t compositeFile.exists() && compositeFile.length() > 1024 -> { logger.info("Loading model from composite JSON, ${compositeFile.absolutePath}") val mapper = ObjectMapper(YAMLFactory()) - mapper.registerModule(KotlinModule()) + mapper.registerModule( + KotlinModule.Builder() + .configure(KotlinFeature.NullToEmptyCollection, true) + .configure(KotlinFeature.NullToEmptyMap, true) + .configure(KotlinFeature.NullIsSameAsDefault, false) + .configure(KotlinFeature.SingletonSupport, true) + .configure(KotlinFeature.StrictNullChecks, true) + .build() + ) mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) diff --git a/src/main/kotlin/graphics/scenery/controls/ScreenConfig.kt b/src/main/kotlin/graphics/scenery/controls/ScreenConfig.kt index feeef21fc..8f5b9d2d9 100644 --- a/src/main/kotlin/graphics/scenery/controls/ScreenConfig.kt +++ b/src/main/kotlin/graphics/scenery/controls/ScreenConfig.kt @@ -5,6 +5,7 @@ import org.joml.Vector3f import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.dataformat.yaml.YAMLFactory +import com.fasterxml.jackson.module.kotlin.KotlinFeature import com.fasterxml.jackson.module.kotlin.KotlinModule import graphics.scenery.utils.JsonDeserialisers import graphics.scenery.utils.lazyLogger @@ -142,7 +143,15 @@ class ScreenConfig { */ @JvmStatic fun loadFromFile(path: String): ScreenConfig.Config { val mapper = ObjectMapper(YAMLFactory()) - mapper.registerModule(KotlinModule()) + mapper.registerModule( + KotlinModule.Builder() + .configure(KotlinFeature.NullToEmptyCollection, true) + .configure(KotlinFeature.NullToEmptyMap, true) + .configure(KotlinFeature.NullIsSameAsDefault, false) + .configure(KotlinFeature.SingletonSupport, true) + .configure(KotlinFeature.StrictNullChecks, true) + .build() + ) var stream = ScreenConfig::class.java.getResourceAsStream(path) diff --git a/src/main/kotlin/graphics/scenery/utils/extensions/TextureUtils.kt b/src/main/kotlin/graphics/scenery/utils/extensions/TextureUtils.kt index 152814757..2f9935865 100644 --- a/src/main/kotlin/graphics/scenery/utils/extensions/TextureUtils.kt +++ b/src/main/kotlin/graphics/scenery/utils/extensions/TextureUtils.kt @@ -3,21 +3,36 @@ package graphics.scenery.utils.extensions import graphics.scenery.backends.vulkan.VulkanTexture import graphics.scenery.textures.Texture import graphics.scenery.utils.lazyLogger +import org.jetbrains.annotations.ApiStatus.Experimental -fun Texture.fetchTexture(texture: Texture): Int { + +/** + * Fetches this [Texture] from the GPU. This replaced the texture's + * contents with whatever is fetched from the GPU and returns true. + * If the texture is not known to the renderer, or no storage buffer + * is available, it'll return false. + */ +@Experimental +fun Texture.fetchFromGPU(): Boolean { val logger by lazyLogger() - val ref = VulkanTexture.getReference(texture) - val buffer = texture.contents ?: return -1 + val buffer = this.contents + if(buffer == null) { + logger.error("Texture copy from GPU requested, but no storage available.") + return false + } + + val ref = VulkanTexture.getReference(this) if(ref != null) { val start = System.nanoTime() - texture.contents = ref.copyTo(buffer, true) + this.contents = ref.copyTo(buffer, true) val end = System.nanoTime() - logger.info("The request textures of size ${texture.contents?.remaining()?.toFloat()?.div((1024f*1024f))} took: ${(end.toDouble()-start.toDouble())/1000000.0}") + logger.info("The request textures of size ${this.contents?.remaining()?.toFloat()?.div((1024f*1024f))} took: ${(end.toDouble()-start.toDouble())/1000000.0}") } else { - logger.error("In fetchTexture: Texture not accessible") + logger.error("In fetchFromGPU: Texture not accessible") + return false } - return 0 + return true } diff --git a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIData.kt b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIData.kt index 0decdba04..97891d673 100644 --- a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIData.kt +++ b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIData.kt @@ -1,5 +1,6 @@ package graphics.scenery.volumes.vdi +import org.jetbrains.annotations.ApiStatus.Experimental import org.joml.Matrix4f import org.joml.Vector2i import org.joml.Vector3f @@ -18,6 +19,7 @@ import org.joml.Vector3f * * @author Aryaman Gupta and Ulrik Günther */ +@Experimental data class VDIMetadata( val version: Int = 1, var index: Int = 0, diff --git a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIDataIO.kt b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIDataIO.kt index 07761cf81..6d1204d83 100644 --- a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIDataIO.kt +++ b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIDataIO.kt @@ -3,6 +3,7 @@ package graphics.scenery.volumes.vdi import com.esotericsoftware.kryo.Kryo import com.esotericsoftware.kryo.io.Input import com.esotericsoftware.kryo.io.Output +import org.jetbrains.annotations.ApiStatus.Experimental import org.joml.Matrix4f import org.joml.Vector2i import org.joml.Vector3f @@ -15,6 +16,7 @@ import java.io.OutputStream * * @author Aryaman Gupta and Ulrik Günther */ +@Experimental class VDIDataIO { companion object { diff --git a/src/main/kotlin/graphics/scenery/volumes/vdi/VDINode.kt b/src/main/kotlin/graphics/scenery/volumes/vdi/VDINode.kt index fab8013b0..eae9b9557 100644 --- a/src/main/kotlin/graphics/scenery/volumes/vdi/VDINode.kt +++ b/src/main/kotlin/graphics/scenery/volumes/vdi/VDINode.kt @@ -12,6 +12,7 @@ import graphics.scenery.utils.Image import graphics.scenery.utils.extensions.applyVulkanCoordinateSystem import net.imglib2.type.numeric.integer.UnsignedIntType import net.imglib2.type.numeric.real.FloatType +import org.jetbrains.annotations.ApiStatus.Experimental import org.joml.Matrix4f import org.joml.Vector3f import org.joml.Vector3i @@ -29,6 +30,7 @@ import java.nio.ByteBuffer * @param[vdiData] The metadata ([VDIData]) associated with the VDI. */ +@Experimental class VDINode(windowWidth: Int, windowHeight: Int, val numSupersegments: Int, vdiData: VDIData) : RichNode() { /** The projection matrix of the camera viewport that was used to generate the VDI in the first (default) buffer */ diff --git a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIStreamer.kt b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIStreamer.kt index 638101cbf..2357875e6 100644 --- a/src/main/kotlin/graphics/scenery/volumes/vdi/VDIStreamer.kt +++ b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIStreamer.kt @@ -3,13 +3,12 @@ package graphics.scenery.volumes.vdi import graphics.scenery.Camera import graphics.scenery.Settings import graphics.scenery.backends.Renderer -import graphics.scenery.textures.Texture import graphics.scenery.utils.DataCompressor -import graphics.scenery.utils.extensions.fetchTexture +import graphics.scenery.utils.extensions.fetchFromGPU import graphics.scenery.utils.lazyLogger -import graphics.scenery.volumes.VDIVolumeManager import graphics.scenery.volumes.Volume import graphics.scenery.volumes.VolumeManager +import org.jetbrains.annotations.ApiStatus.Experimental import org.joml.Vector2i import org.joml.Vector3f import org.lwjgl.system.MemoryUtil @@ -29,6 +28,7 @@ import kotlin.system.measureNanoTime * Class to support streaming of Volumetric Depth Images (VDIs). Provides public functions to stream generated VDIs on the * server side and to receive and update them on the client side. */ +@Experimental class VDIStreamer { private val logger by lazyLogger() @@ -112,9 +112,9 @@ class VDIStreamer { if (!firstFrame && vdiStreaming.get()) { - Texture().fetchTexture(vdiColor) - Texture().fetchTexture(vdiDepth) - Texture().fetchTexture(gridCells) + vdiColor.fetchFromGPU() + vdiDepth.fetchFromGPU() + gridCells.fetchFromGPU() val model = volume.spatial().world diff --git a/src/main/kotlin/graphics/scenery/volumes/VDIVolumeManager.kt b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIVolumeManager.kt similarity index 98% rename from src/main/kotlin/graphics/scenery/volumes/VDIVolumeManager.kt rename to src/main/kotlin/graphics/scenery/volumes/vdi/VDIVolumeManager.kt index c00115ded..d44c86120 100644 --- a/src/main/kotlin/graphics/scenery/volumes/VDIVolumeManager.kt +++ b/src/main/kotlin/graphics/scenery/volumes/vdi/VDIVolumeManager.kt @@ -1,4 +1,4 @@ -package graphics.scenery.volumes +package graphics.scenery.volumes.vdi import bvv.core.shadergen.generate.SegmentTemplate import bvv.core.shadergen.generate.SegmentType @@ -12,9 +12,11 @@ import graphics.scenery.compute.InvocationType import graphics.scenery.textures.Texture import graphics.scenery.utils.Image import graphics.scenery.utils.lazyLogger +import graphics.scenery.volumes.VolumeManager import net.imglib2.type.numeric.integer.IntType import net.imglib2.type.numeric.integer.UnsignedIntType import net.imglib2.type.numeric.real.FloatType +import org.jetbrains.annotations.ApiStatus.Experimental import org.joml.Vector3f import org.joml.Vector3i import org.lwjgl.system.MemoryUtil @@ -32,6 +34,8 @@ import kotlin.math.ceil * * @author Aryaman Gupta and Wissal Salhi */ + +@Experimental class VDIVolumeManager (var hub: Hub, val windowWidth: Int, val windowHeight: Int, val maxSupersegments: Int, val scene: Scene) { private val logger by lazyLogger() diff --git a/src/main/resources/graphics/scenery/volumes/VolumeRenderer.cl b/src/main/resources/graphics/scenery/volumes/VolumeRenderer.cl deleted file mode 100644 index ef4aba633..000000000 --- a/src/main/resources/graphics/scenery/volumes/VolumeRenderer.cl +++ /dev/null @@ -1,581 +0,0 @@ -/* -volume and iso surface rendering - - volume rendering adapted from the Nvidia sdk sample - http://developer.download.nvidia.com/compute/cuda/4_2/rel/sdk/website/OpenCL/html/samples.html - - - Author: Martin Weigert (mweigert@mpi-cbg.de) - Loic Royer (royer@mpi-cbg.de) -*/ - - -// Loop unrolling length: -#define LOOPUNROLL 16 - -// Typedefs: -//typedef unsigned int uint; -//typedef unsigned char uchar; - -// random number generator for dithering -inline -float random(uint x, uint y) -{ - uint a = 4421 +(1+x)*(1+y) +x +y; - - for(uint i=0; i < 10; i++) - { - a = ((uint)1664525 * a + (uint)1013904223) % (uint)79197919; - } - - float rnd = (a*1.0f)/(79197919.f); - - return rnd-0.5f; -} - - -// intersect ray with a box -// http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm -inline -int intersectBox(float4 r_o, float4 r_d, float4 boxmin, float4 boxmax, float *tnear, float *tfar) -{ - // compute intersection of ray with all six bbox planes - float4 invR = (float4)(1.0f,1.0f,1.0f,1.0f) / r_d; - float4 tbot = invR * (boxmin - r_o); - float4 ttop = invR * (boxmax - r_o); - - // re-order intersections to find smallest and largest on each axis - float4 tmin = min(ttop, tbot); - float4 tmax = max(ttop, tbot); - - // find the largest tmin and the smallest tmax - float largest_tmin = max(max(tmin.x, tmin.y), max(tmin.x, tmin.z)); - float smallest_tmax = min(min(tmax.x, tmax.y), min(tmax.x, tmax.z)); - - *tnear = largest_tmin; - *tfar = smallest_tmax; - - return smallest_tmax > largest_tmin; -} - - -// convert float4 into uint: -inline -uint rgbaFloatToInt(float4 rgba) -{ - rgba = clamp(rgba,(float4)(0.f,0.f,0.f,0.f),(float4)(1.f,1.f,1.f,1.f)); - - return ((uint)(rgba.w*255)<<24) | ((uint)(rgba.z*255)<<16) | ((uint)(rgba.y*255)<<8) | (uint)(rgba.x*255); -} - -// convert float4 into uint and take the max with an existing RGBA value in uint form: -inline -uint rgbaFloatToIntAndMax(uint existing, float4 rgba) -{ - rgba = clamp(rgba,(float4)(0.f,0.f,0.f,0.f),(float4)(1.f,1.f,1.f,1.f)); - - const uint nr = (uint)(rgba.x*255); - const uint ng = (uint)(rgba.y*255); - const uint nb = (uint)(rgba.z*255); - const uint na = (uint)(rgba.w*255); - - const uint er = existing&0xFF; - const uint eg = (existing>>8)&0xFF; - const uint eb = (existing>>16)&0xFF; - const uint ea = (existing>>24)&0xFF; - - const uint r = max(nr,er); - const uint g = max(ng,eg); - const uint b = max(nb,eb); - const uint a = max(na,ea); - - return a<<24|b<<16|g<<8|r ; -} - - -// multiply matrix with vector -float4 mult(__constant float* M, float4 v){ - float4 res; - res.x = dot(v, (float4)(M[0],M[1],M[2],M[3])); - res.y = dot(v, (float4)(M[4],M[5],M[6],M[7])); - res.z = dot(v, (float4)(M[8],M[9],M[10],M[11])); - res.w = dot(v, (float4)(M[12],M[13],M[14],M[15])); - return res; -} - -__kernel void -dummy_render( - __global float4* d_output, - const uint imageW, - const uint imageH, - const float brightness, - const float trangemin, - const float trangemax, - const float gamma, - const float alpha_blending, - const int maxsteps, - const float dithering, - const float phase, - const int clear, - const float boxMin_x, - const float boxMax_x, - const float boxMin_y, - const float boxMax_y, - const float boxMin_z, - const float boxMax_z, - __constant float* invP, - __constant float* invM, - __read_only image3d_t volume) -{ - const uint x = get_global_id(0); - const uint y = get_global_id(1); - - d_output[x + y*imageW] = (float4)(0.0f, 0.0f, 1.0f, 1.0f); -} - -// Render function, -// performs max projection and then uses the transfert function to obtain a color per pixel: -__kernel void -maxproj_render( - __global float4 *d_output, - const uint imageW, - const uint imageH, - const float brightness, - const float trangemin, - const float trangemax, - const float gamma, - const float alpha_blending, - const int maxsteps, - const float dithering, - const float phase, - const int clear, - const float boxMin_x, - const float boxMax_x, - const float boxMin_y, - const float boxMax_y, - const float boxMin_z, - const float boxMax_z, - __read_only image2d_t transferColor4, - __constant float* invP, - __constant float* invM, - __read_only image3d_t volume) -{ - // samplers: - const sampler_t volumeSampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR ; - const sampler_t transferSampler = CLK_NORMALIZED_COORDS_TRUE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR ; - - // convert range bounds to linear map: - const float ta = 1.f/(trangemax-trangemin); - const float tb = trangemin/(trangemin-trangemax); - - // box bounds using the clipping box - const float4 boxMin = (float4)(boxMin_x,boxMin_y,boxMin_z,1.f); - const float4 boxMax = (float4)(boxMax_x,boxMax_y,boxMax_z,1.f); - - // thread int coordinates: - const uint x = get_global_id(0); - const uint y = get_global_id(1); - - if ((x >= imageW) || (y >= imageH)) return; - - // thread float coordinates: - const float u = (x / (float) imageW)*2.0f-1.0f; - const float v = (y / (float) imageH)*2.0f-1.0f; - - // front and back: - const float4 front = (float4)(u,v,-1.f,1.f); - const float4 back = (float4)(u,v,1.f,1.f); - - // calculate eye ray in world space - float4 orig0, orig; - float4 direc0, direc; - - orig0.x = dot(front, ((float4)(invP[0],invP[1],invP[2],invP[3]))); - orig0.y = dot(front, ((float4)(invP[4],invP[5],invP[6],invP[7]))); - orig0.z = dot(front, ((float4)(invP[8],invP[9],invP[10],invP[11]))); - orig0.w = dot(front, ((float4)(invP[12],invP[13],invP[14],invP[15]))); - - orig0 *= 1.f/orig0.w; - - orig.x = dot(orig0, ((float4)(invM[0],invM[1],invM[2],invM[3]))); - orig.y = dot(orig0, ((float4)(invM[4],invM[5],invM[6],invM[7]))); - orig.z = dot(orig0, ((float4)(invM[8],invM[9],invM[10],invM[11]))); - orig.w = dot(orig0, ((float4)(invM[12],invM[13],invM[14],invM[15]))); - - orig *= 1.f/orig.w; - - direc0.x = dot(back, ((float4)(invP[0],invP[1],invP[2],invP[3]))); - direc0.y = dot(back, ((float4)(invP[4],invP[5],invP[6],invP[7]))); - direc0.z = dot(back, ((float4)(invP[8],invP[9],invP[10],invP[11]))); - direc0.w = dot(back, ((float4)(invP[12],invP[13],invP[14],invP[15]))); - - direc0 *= 1.f/direc0.w; - - direc0 = normalize(direc0-orig0); - - direc.x = dot(direc0, ((float4)(invM[0],invM[1],invM[2],invM[3]))); - direc.y = dot(direc0, ((float4)(invM[4],invM[5],invM[6],invM[7]))); - direc.z = dot(direc0, ((float4)(invM[8],invM[9],invM[10],invM[11]))); - direc.w = 0.0f; - -// printf("%f %f %f %f\n", invP[0], invP[5], invP[10], invP[15]); -//printf("orig: %f %f %f\n", orig.x, orig.y, orig.z); -//printf("dir: %f %f %f\n", direc.x, direc.y, direc.z); - - // find intersection with box - float tnear, tfar; - const int hit = intersectBox(orig,direc, boxMin, boxMax, &tnear, &tfar); - if (!hit || tfar<=0) - { -// d_output[x+imageW*y] = (float4)(orig.x, orig.y, orig.z, 1.0f); - d_output[x+imageW*y] = (float4)(0.0f, 0.0f, 0.0f, 1.0f); - return; - } - -// d_output[x+imageW*y] = (float4)(tnear, tfar, 0.0f, 1.0f); -// return; - - // clamp to near plane: - if (tnear < 0.0f) tnear = 0.0f; - - // compute step size: - const float tstep = fabs(tnear-tfar)/((maxsteps/LOOPUNROLL)*LOOPUNROLL); - - // apply phase: - orig += phase*tstep*direc; - - // randomize origin point a bit: - const uint entropy = (uint)( 6779514*fast_length(orig) + 6257327*fast_length(direc) ); - orig += dithering*tstep*random(entropy+x,entropy+y)*direc; - - // precompute vectors: - const float4 vecstep = 0.5f*tstep*direc; - float4 pos = orig*0.5f+0.5f + tnear*0.5f*direc; - - // Loop unrolling setup: - const int unrolledmaxsteps = (maxsteps/LOOPUNROLL); - - // raycasting loop: - float maxp = 0.0f; - - float mappedVal; - - if (alpha_blending<=0.f) - { - // No alpha blending: - for(int i=0; i= imageW) || (y >= imageH)) return; - - // thread float coordinates: - const float u = (x / (float) imageW)*2.0f-1.0f; - const float v = (y / (float) imageH)*2.0f-1.0f; - - // front and back: - const float4 front = (float4)(u,v,-1.f,1.f); - const float4 back = (float4)(u,v,1.f,1.f); - - // calculate eye ray in world space - float4 orig0, orig; - float4 direc0, direc; - - orig0.x = dot(front, ((float4)(invP[0],invP[1],invP[2],invP[3]))); - orig0.y = dot(front, ((float4)(invP[4],invP[5],invP[6],invP[7]))); - orig0.z = dot(front, ((float4)(invP[8],invP[9],invP[10],invP[11]))); - orig0.w = dot(front, ((float4)(invP[12],invP[13],invP[14],invP[15]))); - - orig0 *= 1.f/orig0.w; - - orig.x = dot(orig0, ((float4)(invM[0],invM[1],invM[2],invM[3]))); - orig.y = dot(orig0, ((float4)(invM[4],invM[5],invM[6],invM[7]))); - orig.z = dot(orig0, ((float4)(invM[8],invM[9],invM[10],invM[11]))); - orig.w = dot(orig0, ((float4)(invM[12],invM[13],invM[14],invM[15]))); - - orig *= 1.f/orig.w; - - direc0.x = dot(back, ((float4)(invP[0],invP[1],invP[2],invP[3]))); - direc0.y = dot(back, ((float4)(invP[4],invP[5],invP[6],invP[7]))); - direc0.z = dot(back, ((float4)(invP[8],invP[9],invP[10],invP[11]))); - direc0.w = dot(back, ((float4)(invP[12],invP[13],invP[14],invP[15]))); - - direc0 *= 1.f/direc0.w; - - direc0 = normalize(direc0-orig0); - - direc.x = dot(direc0, ((float4)(invM[0],invM[1],invM[2],invM[3]))); - direc.y = dot(direc0, ((float4)(invM[4],invM[5],invM[6],invM[7]))); - direc.z = dot(direc0, ((float4)(invM[8],invM[9],invM[10],invM[11]))); - direc.w = 0.0f; - - - // find intersection with box - float tnear, tfar; - const int hit = intersectBox(orig,direc, boxMin, boxMax, &tnear, &tfar); - if (!hit || tfar<=0) - { - d_output[x+imageW*y] = 0.f; - return; - } - - // clamp to near plane: - if (tnear < 0.0f) tnear = 0.0f; - - // compute step size: - const float tstep = fabs(tnear-tfar)/((maxsteps/LOOPUNROLL)*LOOPUNROLL); - - // randomize origin point a bit: - const uint entropy = (uint)( 6779514*fast_length(orig) + 6257327*fast_length(direc) ); - orig += dithering*tstep*random(entropy+x,entropy+y)*direc; - - // precompute vectors: - const float4 vecstep = 0.5f*tstep*direc; - float4 pos = orig*0.5f+0.5f + tnear*0.5f*direc; - - // Loop unrolling setup: - const int unrolledmaxsteps = (maxsteps/LOOPUNROLL); - - // iso value: - float isoVal = mad(1.0f/ta,pow(0.5f,1.0f/gamma),-tb); - - // starting value: - float newVal = 0; //read_imagef(volume, volumeSampler, pos).x; - - // is iso surface value greater or lower: - bool isGreater = newVal>isoVal; - - bool hitIso = false; - - // first pass: - for(int i=0; iisoVal) != isGreater) - { - hitIso = true; - break; - } - - pos+=vecstep; - } - if (hitIso) break; - } - - - //early termination if iso surface not hit: - if (!hitIso) - { - d_output[x+imageW*y] = 0.f; - return; - } - - //second pass: - hitIso = false; - pos-=2*vecstep; - const float4 finevecstep = 3*vecstep/maxsteps; - for(int i=0; iisoVal) != isGreater) - { - hitIso = true; - break; - } - pos+=finevecstep; - } - if (hitIso) break; - } - /**/ - - - // find the real intersection point - float oldVal = read_imagef(volume, volumeSampler, pos-finevecstep).x; - float lam = (newVal - isoVal)/(newVal-oldVal); - pos += lam*vecstep; - - - // getting the normals and do some nice phong shading - - // build light vector: - float4 light = (float4)(-lightX,-lightY,-lightZ,0); - - float c_diffuse = 0.2; - float c_specular = 0.6; - - light = mult(invM,light); - light = fast_normalize(light); - - // compute lateral step for normal calculation: - const float latx = 1.0f/(get_image_width(volume)); - const float laty = 1.0f/(get_image_height(volume)); - const float latz = 1.0f/(get_image_depth(volume)); - - - // robust 2nd order normal estimation: - float4 normal; - normal.x = 2.f*read_imagef(volume,volumeSampler,pos+(float4)(latx,0,0,0)).x- - 2.f*read_imagef(volume,volumeSampler,pos+(float4)(-latx,0,0,0)).x+ - read_imagef(volume,volumeSampler,pos+(float4)(2.f*latx,0,0,0)).x- - read_imagef(volume,volumeSampler,pos+(float4)(-2.f*latx,0,0,0)).x; - - normal.y = 2.f*read_imagef(volume,volumeSampler,pos+(float4)(0,laty,0,0)).x- - 2.f*read_imagef(volume,volumeSampler,pos+(float4)(0,-laty,0,0)).x+ - read_imagef(volume,volumeSampler,pos+(float4)(0,2.f*laty,0,0)).x- - read_imagef(volume,volumeSampler,pos+(float4)(0,-2.f*laty,0,0)).x; - - normal.z = 2.f*read_imagef(volume,volumeSampler,pos+(float4)(0,0,latz,0)).x- - 2.f*read_imagef(volume,volumeSampler,pos+(float4)(0,0,-latz,0)).x+ - read_imagef(volume,volumeSampler,pos+(float4)(0,0,2.f*latz,0)).x- - read_imagef(volume,volumeSampler,pos+(float4)(0,0,-2.f*latz,0)).x; - - normal.w = 0; - - // flip normal if we are comming from values greater than isoVal... - normal = (1.f-2*isGreater)*fast_normalize(normal); - - // Blinn-Phong specular reflection: - //float diffuse = fmax(0.f,dot(light,normal)); - //float specular = native_powr(fmax(0.f,dot(fast_normalize(light+fast_normalize(direc)),fast_normalize(normal))),45); - - // Phong specular reflection: - float diffuse = fmax(0.f,dot(light,normal)); - float4 reflect = 2*dot(light,normal)*normal-light; - float specular = native_powr(fmax(0.f,dot(fast_normalize(reflect),fast_normalize(direc))),10); - - // Mapping to transfert function range and gamma correction: - const float mappedVal = gamma; - - // lookup in transfer function texture: - float4 color = read_imagef(transferColor4, transferSampler, (float2)(mappedVal,0.0f)); - - const float lighting = (c_diffuse*diffuse + (diffuse>0)*c_specular*specular); - - // Apply lighting: - const float3 lightcolor = (float3)(1.0f,1.0f,1.0f); - color.x = mad(lightcolor.x,lighting,color.x); - color.y = mad(lightcolor.y,lighting,color.y); - color.z = mad(lightcolor.z,lighting,color.z); - - color = brightness*color; - - //d_output[x + y*imageW] = rgbaFloatToIntAndMax(0,color); - d_output[x + y*imageW] = rgbaFloatToIntAndMax(clear*d_output[x + y*imageW],color); - -} - - - - -// clears a buffer -__kernel void -clearbuffer(__global uint *buffer, - uint imageW, - uint imageH) -{ - - // thread int coordinates: - const uint x = get_global_id(0); - const uint y = get_global_id(1); - - // clears buffer: - if ((x < imageW) || (y < imageH)) - buffer[x + y*imageW] = 0; -} diff --git a/src/main/resources/graphics/scenery/volumes/AccumulateVDI.comp b/src/main/resources/graphics/scenery/volumes/vdi/AccumulateVDI.comp similarity index 100% rename from src/main/resources/graphics/scenery/volumes/AccumulateVDI.comp rename to src/main/resources/graphics/scenery/volumes/vdi/AccumulateVDI.comp diff --git a/src/main/resources/graphics/scenery/volumes/GridCellsToZero.comp b/src/main/resources/graphics/scenery/volumes/vdi/GridCellsToZero.comp similarity index 100% rename from src/main/resources/graphics/scenery/volumes/GridCellsToZero.comp rename to src/main/resources/graphics/scenery/volumes/vdi/GridCellsToZero.comp diff --git a/src/main/resources/graphics/scenery/volumes/VDIGenerator.comp b/src/main/resources/graphics/scenery/volumes/vdi/VDIGenerator.comp similarity index 100% rename from src/main/resources/graphics/scenery/volumes/VDIGenerator.comp rename to src/main/resources/graphics/scenery/volumes/vdi/VDIGenerator.comp diff --git a/src/test/java/graphics/scenery/tests/applications/vdi/ServerApplication.kt b/src/test/java/graphics/scenery/tests/applications/vdi/ServerApplication.kt index 2a3d4386d..bb9407e01 100644 --- a/src/test/java/graphics/scenery/tests/applications/vdi/ServerApplication.kt +++ b/src/test/java/graphics/scenery/tests/applications/vdi/ServerApplication.kt @@ -5,6 +5,7 @@ import graphics.scenery.backends.Renderer import graphics.scenery.controls.TrackedStereoGlasses import graphics.scenery.volumes.* import graphics.scenery.volumes.vdi.VDIStreamer +import graphics.scenery.volumes.vdi.VDIVolumeManager import org.joml.Vector3f import org.zeromq.ZContext import java.nio.file.Paths diff --git a/src/test/java/graphics/scenery/tests/applications/vdi/VDIStreamingExample.kt b/src/test/java/graphics/scenery/tests/applications/vdi/VDIStreamingExample.kt index 93fbfc6a4..7c810562b 100644 --- a/src/test/java/graphics/scenery/tests/applications/vdi/VDIStreamingExample.kt +++ b/src/test/java/graphics/scenery/tests/applications/vdi/VDIStreamingExample.kt @@ -7,6 +7,7 @@ import graphics.scenery.Settings import graphics.scenery.backends.Renderer import graphics.scenery.volumes.* import graphics.scenery.volumes.vdi.VDIStreamer +import graphics.scenery.volumes.vdi.VDIVolumeManager import org.joml.Vector3f import java.nio.file.Paths import kotlin.concurrent.thread diff --git a/src/test/kotlin/graphics/scenery/tests/examples/volumes/VolumeManagerSwitchingExample.kt b/src/test/kotlin/graphics/scenery/tests/examples/volumes/VolumeManagerSwitchingExample.kt index 17c5c3b44..9ed8250f8 100644 --- a/src/test/kotlin/graphics/scenery/tests/examples/volumes/VolumeManagerSwitchingExample.kt +++ b/src/test/kotlin/graphics/scenery/tests/examples/volumes/VolumeManagerSwitchingExample.kt @@ -3,6 +3,7 @@ package graphics.scenery.tests.examples.volumes import graphics.scenery.* import graphics.scenery.backends.Renderer import graphics.scenery.volumes.* +import graphics.scenery.volumes.vdi.VDIVolumeManager import org.joml.Vector3f import java.nio.file.Paths import kotlin.concurrent.thread