In this tutorial we will see how to get started with a FluxModel in GroIMP. Go [[:groimp-platform:gpuflux|here]] to see more about how the FluxModel is defined in GroIMP. ====== Light Model ====== First, we setup of the Flux Light Model: import de.grogra.gpuflux.tracer.FluxLightModelTracer.MeasureMode; import de.grogra.gpuflux.scene.experiment.Measurement; const int RAYS = 10000000; const int DEPTH = 10; const FluxLightModel LM = new FluxLightModel(RAYS, DEPTH); protected void init () { LM.setMeasureMode(MeasureMode.FULL_SPECTRUM); LM.setSpectralBuckets(81); LM.setSpectralDomain(380, 780); } This is: - importing of the needed classes - initializing the model with 10 million rays and a recursion depth of 10 - setting the parameters with 400nm divided into 80 buckets of 5nm. Then, run the light model and determine the amount of sensed radiation or of absorbed power for an object-type. public void run () [ { LM.compute(); } x:SensorNode ::> { Measurement spectrum = LM.getSensedIrradianceMeasurement(x); float absorbedPower = spectrum.integrate(); //... } x:Box ::> { Measurement spectrum = LM.getAbsorbedPowerMeasurement(x); float absorbedPower = spectrum.integrate(); //... } ] This is: - computing the model - computing the integration of the whole absorbed spectrum for both - sensor nodes - box objects Demonstration of the method for the determination of the amount of absorbed power per bucket or integration over a certain spectral range. Measurement spectrum = LM.getAbsorbedPowerMeasurement(x); //absorbed power for the first bucket: 380-385 nm float ap380_385 = spectrum.data[0]; //accumulate absorbed power for the first four 50 nm buckets float b0 = 0, b1 = 0, b2 = 0, b3 = 0; for (int i:(0:10)) { b0 += spectrum.data[i]; b1 += spectrum.data[i + 10]; b2 += spectrum.data[i + 20]; b3 += spectrum.data[i + 30]; } //integrate the whole spectrum float ap = spectrum.integrate(); This is: - Getting the absorbed spectrum - Storing the first bucket in a variable - building four integrals, each of 50 nm (10 buckets of 5 nm) and sum up the first 40 buckets. - calculating the integral over the whole spectrum. ====== Light Sources ====== Now let's set up a parameterisable light node – with explicit definition of physical light and spectral power distribution by simple arrays: import de.grogra.imp3d.spectral.IrregularSpectralCurve; const double[][] DISTRIBUTION = { {131.25, 131.67, 132.37, ...}, {131.36, 131.81, ...}, ... }; static const float[] WAVELENGTHS = {380,385, ...}; static const float[] AMPLITUDES = {0.000967,0.000980, ...}; module MyLamp extends LightNode() { { setLight(new SpectralLight( new IrregularSpectralCurve(WAVELENGTHS, AMPLITUDES)).( setPower(10), //[W] setLight(new PhysicalLight(DISTRIBUTION)))); } } This is : - importing the required classes - defining of the physical light distribution - defining of the spectral power distribution - defining of a lamp using the specified parameters The light distribution and spectral distribution (i.e. the ''DISTRIBUTION'', ''WAVELENGTHS'' and ''AMPLITUDES'' arrays) can also be provided from ''.ies'' files. See [[:groimp-platform:input-and-output-in-groimp|here]] for more information on the supported file formats. Then, let's create a parameterizable light node – using file references for physical and spectral power distribution. const LightDistributionRef DISTRIBUTION = light(" distribution1"); const SpectrumRef SPECTRUM = spectrum("equal"); module MyLamp1 extends LightNode { { setLight(new SpectralLight(new PhysicalLight( DISTRIBUTION), SPECTRUM, 10)); // 10 W } } module MyLamp2 extends LightNode { { setLight( new SpectralLight().( setPower(10), //[W] setLight(new PhysicalLight(DISTRIBUTION)), setSpectrum(SPECTRUM))); } } This is: - Defining a file reference. This file can be included or linked to a project - Applying a concrete lamp to the reference by: - using the constructor - using the set-methods of the //LightNode// class ====== Illumination Model ====== Definition of a Phong shader by textures, by colours and by a user-defined spectral power distribution. Phong myShader = new Phong(); ImageMap image = new ImageMap(); image.setImageAdapter(new FixedImageAdapter(image("leaf").toImageAdapter().getBufferedImage())); myShader.setDiffuse(image); Phong myShader = new Phong(); myShader.setDiffuse(new RGBColor(0,1,0)); //myShader.setSpecular(new Graytone(0.5)); //myShader.setShininess(new Graytone(0.5)); myShader.setDiffuseTransparency(new RGBColor(0.5,0,0)); //myShader.setAmbient(new Graytone(0.5)); //myShader.setEmissive(new Graytone(0.5)); ChannelSPD MySPD = new ChannelSPD(new IrregularSpectralCurve( new float[] {400,410, ....,740,750}, //WAVELENGTHS new float[] {0.1,0, .... ,0.4,0.25} //AMPLITUDES )); Phong myShader = new Phong(); myShader.setDiffuse(MySPD); This is: - Setting an image as texture: Values for reflection depend on the colour of the texture at each pixel of the image. - Setting specific properties: At this configuration green will be reflected to 100 % and red will be transmitted to 50 % for the whole surface of the object. - A user-defined SPD is used to define the diffuse colour.