Efficiente illuminazione 2D per pixel su Android [chiuso]

1

Sto cercando di creare un semplice gioco 2D da imparare da solo. Il mio attuale compito è la creazione di uno schema di illuminazione.

Il mio obiettivo è di far apparire lo schermo scuro tranne dove creo le luci. Ho una classe di luce che traccia solo la posizione e il raggio della luce. Il codice che sento di aver bisogno di aiuto per migliorare è la mia illuminazione per pixel delle immagini che arrivano nel raggio di luce.

Il codice che ho caricato due immagini. La vera immagine e una bumpmap. Crea anche una copia dell'originale per essere l'immagine che deve essere modificata dalla luce (facendo riferimento ai pixel originali) e disegnata. Il mio codice imposta anche due array. Uno trattiene i pixel originali in modo che il rgb venga tirato da loro in seguito. L'altro memorizza le normali calcolate dei pixel da utilizzare successivamente nella classe.

Il mio problema è il metodo di aggiornamento che passa attraverso ogni pixel usando la posizione, il prodotto del punto e le normali per determinare in che modo la luce ombreggia il pixel. Il metodo di aggiornamento estrae la frequenza dei fotogrammi da 60 a circa 10 su una singola immagine 100x100.

Mi aspetto che venga detto che è troppo per un Android e che è meglio usarlo su un gioco desktop, ma è un'ipotesi corretta? Se sì, quali sono le mie alternative? Codice in questione di seguito.

package com.sevensoftware.simple2d;
import org.apache.http.*;
import android.graphics.*;
import android.content.*;
import android.util.*;

public class MyImage
{
  Bitmap image;
  Bitmap imageC;

  private Bitmap imageB;

  private int width;

  private int height;

  private int[][] map;

  private Point[][] nmap;

  private int power;

  private double softness;
  public MyImage(String name, Context context){

      //Load display image as original reference
      image = ImageLoader.loadImage(name,context);

      width = image.getWidth();
      height = image.getHeight();

      //Create a copy of display image to be our modifyable image
      imageC = image;
      //imageC.setConfig(Bitmap.Config.ARGB_8888);
      //Load Bumpmap
      Log.d("@myImage","loading bumpmap");
      imageB = ImageLoader.loadImage(name+"b", context);
      Log.d("@myImage","loaded bumpmap");
      power = 14;
      softness = Math.pow(2,power);
      map = new int[height][width];
      nmap = new Point[height][width];
      //Create normals
      createNormals();

  }

  public void setImage(Bitmap newImage){
      image = newImage;
  }

  public Bitmap getImage()
  {

      return imageC;
  }

  public int getHeight()
  {

      return height;
  }

  public int getWidth()
  {

      return width;
  }

  private void createNormals(){
      Log.d("@myImage","beginning normals");
      for(int i = 0; i < height; i++){
          for(int j = 0; j < width; j++){
              int c = (imageB.getPixel(j,i)>>16) &0xff;

              map[i][j] = c;

              nmap[i][j] = new Point(c, c);
          }
      }
      for(int i = 0; i < height; i++){
          for(int j = 0; j < width; j++){
              if(i==0|i==height-1|j==0|j==width-1){
                  continue;
                  }
              nmap[i][j].x = map[i][j-1]-map[i][j+1];
              nmap[i][j].y = map[i-1][j]-map[i+1][j];
              }
          }

      Log.d("@myImage","Created normals");

  }

  public void update(Light light, int imagePosX, int imagePosY){

      Log.d("@myImage","beginning update");
      int lx = light.x;
      int ly = light.y;
      int rad = light.radius;

      for(int i = 0; i < height; i++){
          for(int j = 0; j < width; j++){
      //normal vectors
      double AX = nmap[i][j].x;
      double AY = nmap[i][j].y;
              Log.d("@myImage","retrieved normal vetors");

      //light vector
      double BX = lx - (imagePosX+j);
      double BY = ly - (imagePosY+i);
              Log.d("@myImage","light vectors complete");

      //Dot product
      double dp = AX*BX + AY*BY;
              Log.d("@myImage","dp complete");

      int pixel = image.getPixel(j,i);
              Log.d("@myImage","got pixel");
      //int a = (pixel>>24) & 0xff;
      int r = (pixel>>16) & 0xff;
      int g = (pixel>>8) & 0xff;
      int b = (pixel) & 0xff;
              Log.d("@myImage","found rgb");

      double dist = Math.sqrt(BX * BX + BY * BY);
      double percent = (dp+softness/2)/softness;
      double percent2 = dist/rad;

      int lumen = (int)(percent*255);
      int shade = (int)(percent2*255);

      r+=lumen;
      g+=lumen;
      b+=lumen;
      r-=shade;
      g-=shade;
      b-=shade;

      if(r<0){r=0;}
      if(g<0){g=0;}
      if(b<0){b=0;}
      if(r>255){r=255;}
      if(g>255){g=255;}
      if(b>255){b=255;}

      Log.d("@myImage","attempting to set pixel");
      imageC.setPixel(j,i,Color.argb(255,r,g,b));
      Log.d("@myImage", "updated pixel");
      }
      }

  }
}
    
posta Jager7 15.09.2015 - 03:01
fonte

1 risposta

0

Ci sono un paio di cose in questo codice che mi sembrano sbagliate o inefficienti:

Primo, imageC = image; //Create a copy of display image to be our modifyable image in realtà non crea una copia dell'immagine. Crea una copia del riferimento all'immagine, quindi stai modificando l'immagine reale, piuttosto che una copia. Questo in realtà è una cosa su Java, solo i valori primitivi possono essere copiati in questo modo, gli oggetti richiedono più lavoro. In particolare, il modo corretto di creare una copia di una bitmap è descritto qui (ignora la risposta accettata e guarda invece quella votata più alta)

Secondo, setPixel e getPixel sono metodi nativi che fanno un bel po 'di roba. Esistono molti metodi di caricamento più performanti per questo: setPixels e getPixels . Sarebbe meglio ottenere tutti i pixel necessari all'inizio del metodo e impostarli tutti alla fine, una volta eseguito il calcolo.

    
risposta data 16.09.2015 - 15:58
fonte