1 / 17

Programmazione grafica in Java

Programmazione grafica in Java. Creare effetti di luce tramite il filtro LightOp Redazione a cura di Luca Imperatore. Nell’esempio che segue vogliamo creare degli effetti di luce su di una composizione utilizzando il filtro LightOp di GLF.

alisa
Download Presentation

Programmazione grafica in Java

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Programmazione grafica in Java Creare effetti di luce tramite il filtro LightOp Redazione a cura di Luca Imperatore

  2. Nell’esempio che segue vogliamo creare degli effetti di luce su di una composizione utilizzando il filtro LightOp di GLF. L’uso di questo filtro ci permette di dare alla composizione un aspetto realistico grazie all’utilizzo di mappe di rilievo e di luci opportunamente posizionate. La composizione è formata da tre livelli: lo sfondo, il testo e l’ombra del testo. Il livello di sfondo è realizzato caricando l’immagine di una tessitura. Per dare un aspetto realistico allo sfondo facciamo agire su di esso il filtro LightOp. Prepariamo per questo una mappa di rilievo tramite la classe ElevationMap. Diamo al parametro boolean il valore true in modo da interpretare i valori di luminosità come rilievo a sporgere. Prepariamo le luci che illuminano la composizione: una luce direzionale (DirectionalLight) proveniente dall’angolo in alto a sinistra e delle luci spot (SpotLight) provenienti dall’alto e dal basso. Possiamo scegliere quali luci “accendere” agendo sui valori true e false delle rispettive variabili in fase di inizializzazione come vedremo successivamente in un esempio. Creare effetti di lucetramite il filtro LightOp

  3. Quindi possiamo creare la LitSurface alla quale passiamo come parametro la mappa di rilievo e alla quale aggiungiamo le luci precedentemente create. Infine trasformiamo lo sfondo in un livello di forma (ShapeLayer) necessario per far agire il filtro LightOp su di esso. La realizzazione del livello di testo segue gli stessi passi. Per avere un aspetto tridimensionale trasformiamo il testo in un livello di forma. Creiamo un nuovo filtro LightOp nel quale i parametri della LitSurface sono una nuova ElevationMap e le stesse luci create precedentemente. Quindi facciamo agire il filtro sulla ShapeLayer. Aggiungiamo infine un livello di ombra creato traslando la Shape del testo e sfocandola con il filtro ConvolveOp. Il risultato finale è il seguente:

  4. Come prima cosa inizializziamo le variabili che ci serviranno per la composizione: //Font e colori del testo, colore dello sfondo e dell’ombra String text = "Java 2D is Hot!"; Color backgroundColor = new Color(204, 102, 51); Color textColor = new Color(118, 114, 195); Dimension size = new Dimension(600, 200); Font font = new Font("Curlz MT", Font.PLAIN, 90); File textureFile = new File("res/images/syberia/syberia35.jpg"); Color shadowColor = new Color(0, 0, 0); double lightIntensity = 2; //Posizionamento dell’ombra del testo int shadowOffsetX = 5, shadowOffsetY = 5; float shadowShearX = 0, shadowShearY = 0; //Luce spot dall’alto Color lightTopRampColor = Color.white; boolean lightTopRamp = true; //Luce spot dal basso Color lightBottomRampColor = Color.white; boolean lightBottomRamp = false;

  5. //Luce direzionale Color lightSunColor = Color.white; boolean lightSun = true; Trasformiamo il testo in un oggetto di tipo Shape che ci servirà successivamente per creare l’ombra e il livello del testo da filtrare: Shape shape = TextLayer.makeTextBlock(text, font, w, textTextAlignment); Position textPosition = new Position(textAnchor, 0, 0); shape = textPosition.createTransformedShape(shape, cmp.getBounds()); Creiamo il livello di sfondo caricando l’immagine in una BufferedImage e modelliamo un rilievo tramite una mappa di rilievo (ElevationMap): String textureFileName = textureFile.getPath(); BufferedImage texture = Toolbox.loadImage(textureFileName, BufferedImage.TYPE_BYTE_GRAY);

  6. ElevationMap map = new ElevationMap(texture, true, 5); Creiamo una LitSurface per lo sfondo alla quale aggiungiamo la luce direzionale proveniente dall’angolo in alto a sinistra: LitSurface bkgSurface = new LitSurface(.3, 1, 1, materialType, map); if(lightSun) bkgSurface.addLight(new DirectionalLight(new double[]{-40, -40, 40}, lightSunIntensity, lightSunColor)); A questo punto prepariamo le luci spot (SpotLight) dall’alto e dal basso che aggiungiamo alla LitSurface appena creata: //Creiamo la luce spot dall’alto SpotLight[] topSpots = LightsStudio.getLightRamp(lightBounds, 4, Anchor.TOP, new double[]{lightIntensity, lightIntensity, lightIntensity, lightIntensity},

  7. new Color[] {lightTopRampColor, lightTopRampColor, lightTopRampColor, lightTopRampColor}, .5); if(lightTopRamp) bkgSurface.addLights(topSpots); //Creiamo la luce spot dal basso SpotLight[] bottomSpots = LightsStudio.getLightRamp(lightBounds, 3, Anchor.BOTTOM, new double[]{lightIntensity, lightIntensity, lightIntensity}, new Color[]{lightBottomRampColor, lightBottomRampColor, lightBottomRampColor}, 0); if(lightBottomRamp) bkgSurface.addLights(bottomSpots); Infine creiamo il filtro LightOp e lo facciamo agire sul livello di sfondo dopo averlo opportunamente trasformato in un livello di forma: LightOp op = new LightOp(bkgSurface); ShapeLayer backgroundLayer = new ShapeLayer(cmp, cmp.getBounds(), new FillRenderer(backgroundColor)); backgroundLayer.setRasterFilter(op);

  8. E’ interessante notare come possiamo modificare la luminosità dello sfondo solamente agendo sui valori true e false delle variabili della luce direzionale e delle luci spot in fase di inizializzazione: Luci spot dall’alto “accese” e dal basso “spente”. Luce direzionale “spenta” Luci spot dall’alto”spente” e dal basso “accese”. Luce direzionale “spenta” Luci spot dall’alto “spente” e dal basso “accese”. Luce direzionale “accesa”

  9. Creiamo ora l’ombra del testo. Per dare un effetto realistico all’ombra utilizziamo il filtro ConvolveOp per ottenere un effetto di sfocatura e una AffineTransform per traslare la Shape del testo: ConvolveOp blurOp = new ConvolveOp(new GaussianKernel(5)); AffineTransform shadowTransform = AffineTransform.getShearInstance(shadowShearX, shadowShearY); ShapeLayer shadowLayer = new ShapeLayer(cmp, shape, new FillRenderer(shadowColor)); shadowLayer.setRasterFilter(blurOp, new Dimension(5, 5)); shadowTransform.setToTranslation(shadowOffsetX, shadowOffsetY); shadowLayer.setTransform(shadowTransform); Dobbiamo ora dare un effetto tridimensionale al testo. Come per l’immagine di sfondo creiamo una ElevationMap per modellare un rilievo: ElevationMap textMap = new ElevationMap(shape, 7, true, 10);

  10. Creiamo una LitSurface per il testo alla quale aggiungiamo la luce direzionale e le luci spot create precedentemente: LitSurface textSurface = new LitSurface(.3, 1, 1, materialType, textMap); if(lightSun) textSurface.addLight(new DirectionalLight(new double[]{-40, -40, 40}, lightSunIntensity, lightSunColor)); if(lightTopRamp) textSurface.addLights(topSpots); if(lightBottomRamp) textSurface.addLights(bottomSpots); Quindi trasformiamo il testo in un livello di forma sul quale facciamo agire un nuovo filtro LightOp: ShapeLayer embossedText = new ShapeLayer(cmp, cmp.getBounds(), new FillRenderer(textColor)); embossedText.setRasterFilter(new LightOp(textSurface));

  11. Per far agire il filtro solo sul livello di testo dobbiamo usare l'oggetto shape per creare una maschera ed eseguire un ritaglio (clipping). Tutto ciò che si trova all'interno dello shape rimane visibile ciò che sta al di fuori viene mascherato. embossedText.setLayerMask(shape); L’ultima operazione consiste nel posizionare in una pila i tre livelli che abbiamo creato. Il livello più basso è quello di background, più su viene quello con l’ombra, ed infine il testo: cmp.setLayers(new Layer[]{ backgroundLayer, shadowLayer, embossedText }); Di seguito il codice completo del programma.

  12. Lights.java import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import javax.swing.*; import com.sun.glf.*; import com.sun.glf.goodies.*; import com.sun.glf.util.*; public class Lights implements CompositionFactory { //Inizializziamo le variabili String text = "Java 2D is Hot!"; Color backgroundColor = new Color(204, 102, 51); Color textColor = new Color(118, 114, 195); Dimension size = new Dimension(600, 200); Font font = new Font("Curlz MT", Font.PLAIN, 90); File textureFile = new File("res/images/syberia/syberia35.jpg"); Color shadowColor = new Color(0, 0, 0); double lightIntensity = 2; //Posizionamento dell’ombra del testo int shadowOffsetX = 5, shadowOffsetY = 5; float shadowShearX = 0, shadowShearY = 0; //Luce spot dall’alto Color lightTopRampColor = Color.white; boolean lightTopRamp = true; //Luce spot dal basso Color lightBottomRampColor = Color.white; boolean lightBottomRamp = false;

  13. //Luce direzionale Color lightSunColor = Color.white; boolean lightSun = true; double lightSunIntensity = 0.2; int materialType = 16; //Posizione del testo Anchor textAnchor = Anchor.CENTER; TextAlignment textTextAlignment = TextAlignment.CENTER; public Composition build(){ LayerComposition cmp = new LayerComposition(size); int w = size.width; int h = size.height; //Trasformiamo il testo in una forma che ci servirà successivamente per creare l'ombra e il livello del testo Shape shape = TextLayer.makeTextBlock(text, font, w, textTextAlignment); Position textPosition = new Position(textAnchor, 0, 0); shape = textPosition.createTransformedShape (shape , cmp.getBounds()); //Creiamo il livello di sfondo caricando l’immagine in una BufferedImage String textureFileName = textureFile.getPath(); BufferedImage texture = Toolbox.loadImage(textureFileName, BufferedImage.TYPE_BYTE_GRAY);

  14. //Creiamo la mappa di rilievo long curTime = System.currentTimeMillis(); ElevationMap map = null; if(texture != null){ System.out.print("\nProcessing background elevations .... "); map = new ElevationMap(texture, true, 5); System.out.println("... Done : " + (System.currentTimeMillis()- curTime)/1000 + "(s)"); } //Creiamo la LitSurface per lo sfondo LitSurface bkgSurface = new LitSurface(.3, 1, 1, materialType, map); if(lightSun) bkgSurface.addLight(new DirectionalLight(new double[]{-40, -40, 40}, lightSunIntensity,lightSunColor)); //Creiamo la luce spot dall'alto int hm = 1; Rectangle lightBounds = new Rectangle(0, hm, w, h-2*hm); SpotLight[] topSpots = LightsStudio.getLightRamp(lightBounds, 4, Anchor.TOP, new double[]{lightIntensity, lightIntensity, lightIntensity, lightIntensity}, new Color[] {lightTopRampColor, lightTopRampColor, lightTopRampColor, lightTopRampColor}, .5);

  15. if(lightTopRamp) bkgSurface.addLights(topSpots); //Creiamo la luce spot dal basso SpotLight[] bottomSpots = LightsStudio.getLightRamp(lightBounds, 3, Anchor.BOTTOM, new double[]{lightIntensity, lightIntensity, lightIntensity}, new Color[]{lightBottomRampColor, lightBottomRampColor, lightBottomRampColor,}, 0); if(lightBottomRamp) bkgSurface.addLights(bottomSpots); LightOp op = new LightOp(bkgSurface); //Trasformiamo lo sfondo in un livello di forma sul quale facciamo agire il filtro LightOp ShapeLayer backgroundLayer = new ShapeLayer(cmp, cmp.getBounds(), new FillRenderer(backgroundColor)); backgroundLayer.setRasterFilter(op); //Creiamo il livello dell'ombra ConvolveOp blurOp = new ConvolveOp(new GaussianKernel(5)); AffineTransform shadowTransform = AffineTransform.getShearInstance (shadowShearX, shadowShearY); ShapeLayer shadowLayer = new ShapeLayer(cmp, shape, new FillRenderer(shadowColor)); shadowLayer.setRasterFilter(blurOp, new Dimension(5, 5));

  16. shadowTransform.setToTranslation (shadowOffsetX, shadowOffsetY); shadowLayer.setTransform(shadowTransform) ; //Diamo un effetto tridimensionale al testo creando una mappa di rilievo curTime = System.currentTimeMillis(); System.out.print("\nCreating text elevation map .... "); ElevationMap textMap = new ElevationMap(shape, 7, true, 10); //Creiamo una LitSurface per il testo alla quale aggiungiamo la luce direzionale e le luci spot create precedentemente LitSurface textSurface = new LitSurface(.3, 1, 1, materialType, textMap); if(lightSun) textSurface.addLight(new DirectionalLight(new double[]{-40, -40, 40}, lightSunIntensity, lightSunColor)); if(lightTopRamp) textSurface.addLights(topSpots); if(lightBottomRamp) textSurface.addLights(bottomSpots); System.out.println("... Done : " + (System.currentTimeMillis()-curTime)/1000 + "(s)"); //Trasformiamo il testo in un livello di forma sul quale facciamo agire un nuovo filtro LightOp ShapeLayer embossedText = new ShapeLayer(cmp, cmp.getBounds(), new FillRenderer(textColor));

  17. embossedText.setRasterFilter(new LightOp(textSurface)); //Per far agire il filtro solo sul livello di testo usiamo l'oggetto shape per creare una maschera ed eseguire un ritaglio embossedText.setLayerMask(shape); //Posizioniamo i livelli nella pila cmp.setLayers(new Layer[]{ backgroundLayer, shadowLayer, embossedText }); return cmp; } public static void main(String args[]){ JFrame f = new JFrame(); f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); Lights sf = new Lights(); CompositionComponent cc = new CompositionComponent(sf.build()); f.getContentPane().add(cc); f.pack(); f.setVisible(true); } }

More Related