Android Open Source - abstract-art Renderer






From Project

Back to project page abstract-art.

License

The source code is released under:

GNU General Public License

If you think the Android project abstract-art listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package net.georgewhiteside.android.abstractart;
/*w  w  w.ja v a  2  s .  co m*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.Buffer;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;

import net.georgewhiteside.android.abstractart.Wallpaper;
import net.georgewhiteside.android.abstractart.Wallpaper.AbstractArtEngine;

import org.jf.GLWallpaper.GLWallpaperService;

// float refreshrate = getWindowManager().getDefaultDisplay().getRefreshRate();

// "The PowerVR 530/535 is very slow. Andreno 200 and PowerVR 530/535 are first GPU generation
// (OpenGL ES 2.x) for hdpi resolution. You can't redraw a full screen at 60FPS with a simple texture."

public class Renderer implements GLWallpaperService.Renderer, GLSurfaceView.Renderer
{
  private static final String TAG = "Renderer";
  private Context context;
  
  private SharedPreferences sharedPreferences;
  
  public BattleGroup battleGroup;
  private ShaderFactory shader;
  
  private FPSCounter mFPSCounter = new FPSCounter();
  
  private FloatBuffer quadVertexBuffer;
  private FloatBuffer textureVertexBuffer;
  private FloatBuffer textureOutputBuffer;
  
  private int mProgram, hFXProgram;
  private int mPositionHandle, hPosition;
  private int mTextureHandle, hTexture;
  private int mBaseMapTexId;
  private int mBg3TextureLoc, hTextureA;
  private int mBg4TextureLoc;
  private int hBaseMap;
  private int mPaletteLoc;
  
  private int mPaletteRotation;
  
  private int mResolutionLoc;
  private int mCompressionLoc;
  private int mBg3DistTypeLoc, mBg4DistTypeLoc;
  private int mBg3DistLoc, mBg4DistLoc;
  private int mDistTypeLoc;
  private int mBg3Scroll, mBg4Scroll;
  private int mBg3PaletteLoc, mBg4PaletteLoc;
  private int mBg3CompressionLoc, mBg4CompressionLoc;
  private int mBg3RotationLoc, mBg4RotationLoc;
  private int mCycleTypeLoc;
  
  private int mSurfaceWidth;
  private int mSurfaceHeight;
  private float mRenderWidth;
  private float mRenderHeight;
  
  private int mSurfaceVerticalOffset = 0;
  private int mSurfaceHorizontalOffset = 0;
  
  private int hMVPMatrix;
  private float[] mProjMatrix = new float[16];
  
  private int[] mFramebuffer = new int[1];
  private int[] mRenderTexture = new int[1];
  
  private Boolean mFilterBackgrounds = false;
  private Boolean mFilterOutput = false;
  
  private Boolean mRenderEnemies = true;
  private int mEnemyPositionHandle;
  private int mEnemyTextureHandle;
  private int mEnemyTextureLoc;
  private FloatBuffer enemyVertexBuffer;
  private FloatBuffer enemyTextureVertexBuffer;
  
  private float mLetterBoxSize;
  
  private int[] mTextureId = new int[3];
  private ByteBuffer mTextureA, mTextureB;
  private ByteBuffer mPalette;
  
  private int[] mBattleSpriteId = new int[1];
  private int mBattleSpriteProgramId;
  
  private int currentBackground;
  private boolean persistBackgroundSelection;
  
  public boolean isPreview;
  
  private long startTime, endTime;
  
  Random rand = new Random();
  
  private boolean mHighRes = false;
  private long frameTime = 60;
  
  private boolean mirrorVertical = false;
  
  private Object lock = new Object();
  
  public int getRomBackgroundIndex(int address)
  {
    return battleGroup.battleBackground.getRomBackgroundIndex(address);
  }
  
  public int getCacheableImagesTotal()
  {
    int images = 103; // TODO: don't hardcode this
    
    return images;
  }
  
  public int getBackgroundsTotal()
  {
    return battleGroup.battleBackground.getNumberOfBackgrounds();
  }
  
  public void cacheImage(int index)
  {
    battleGroup.load(index);
  }
  
  public void setRandomBackground()
  {
    int number = Wallpaper.random.nextInt(battleGroup.battleBackground.getNumberOfBackgrounds() - 1) + 1;
    loadBattleBackground(number);
  }
  
  public void setPersistBackgroundSelection(boolean value)
  {
    persistBackgroundSelection = value;
  }
  
  public void setIsPreview(boolean value)
  {
    isPreview = value;
  }
  
  public Renderer(Context context)
  {
    this.context = context;
    sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    battleGroup = new BattleGroup(context);
    shader = new ShaderFactory(context);
    mTextureA = ByteBuffer.allocateDirect(256 * 256 * 1);
    mTextureB = ByteBuffer.allocateDirect(256 * 256 * 1);
    mPalette = ByteBuffer.allocateDirect(16 * 16 * 4);
    
    startTime = endTime = 0;
    
    isPreview = false;
    
    currentBackground = -1;
    persistBackgroundSelection = false;
    
    Log.i(TAG, "Renderer created");
  }
  
  public Renderer(Context context, boolean mirrorVertical)
  {
    this(context);
    this.mirrorVertical = mirrorVertical;
  }
  
  public Renderer(Context context, int initialBackground)
  {
    this(context);
    this.currentBackground = initialBackground;
  }
  
  public void onDrawFrame(GL10 unused)
  {
    endTime = System.currentTimeMillis();
    long delta = endTime - startTime;
    if(delta < frameTime)
    {
      try {
        Thread.sleep(frameTime - delta);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
    startTime = System.currentTimeMillis();
    
    mFPSCounter.logStartFrame();
    
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); // target screen
    //GLES20.glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
    //mRenderWidth = mSurfaceWidth;
    //mRenderHeight = mSurfaceHeight;
    
    renderScene();
      
    battleGroup.battleBackground.doTick();
    
    mFPSCounter.logEndFrame();
  }

  public void onSurfaceChanged(GL10 unused, int width, int height)
  {
    mSurfaceWidth = width;
    mSurfaceHeight = height;
    
    float surfaceRatio = (float) mSurfaceWidth / mSurfaceHeight;
    float textureRatio = 256.0f / 224.0f;
    
    mSurfaceHorizontalOffset = 0;
    mSurfaceVerticalOffset = 0;
    mLetterBoxSize = 0.0f;
    
    if(surfaceRatio == textureRatio) // thumbnail hack (won't scale if someone actually uses an 8:7 screen ratio)
    {
      
    }
    else
    {
        int outputScaler = 1;
        
        if(surfaceRatio > textureRatio)
            outputScaler = (int)(mSurfaceWidth / 256) + 1; // landscape
        
        if(surfaceRatio < textureRatio)
            outputScaler = (int)(mSurfaceHeight / 224) + 1; //portrait
        
        int bestWidthFit = outputScaler * 256;
            int bestHeightFit = outputScaler * 224;
            
            mSurfaceWidth = bestWidthFit;
            mSurfaceHeight = bestHeightFit;
            mSurfaceVerticalOffset = (height - bestHeightFit) / 2;
            mSurfaceHorizontalOffset = (width - bestWidthFit) / 2;
    }
    
    Matrix.orthoM(mProjMatrix, 0, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
  }
  
  private void setupScreenQuad()
  {
    float quadVertices[] =
    {
      -1.0f,  -1.0f,   0.0f,
       1.0f,  -1.0f,   0.0f,
      -1.0f,   1.0f,   0.0f,
       1.0f,   1.0f,   0.0f       
    };
    
    float textureMap[] =
    {
        0.0f,   0.875f,
         1.0f,   0.875f,
         0.0f,   0.0f,
         1.0f,   0.0f 
    };
    
    float textureMapFlip[] =
    {
        0.0f,   0.0f,
         1.0f,   0.0f,
         0.0f,   0.875f,
         1.0f,   0.875f 
    };

    quadVertexBuffer = ByteBuffer
        .allocateDirect(quadVertices.length * 4) // float is 4 bytes
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer(); 
    quadVertexBuffer.put(quadVertices);
    quadVertexBuffer.position(0);
    
    textureVertexBuffer = ByteBuffer
        .allocateDirect(textureMap.length * 4) // float is 4 bytes
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer(); 
    textureVertexBuffer.put(textureMap);
    textureVertexBuffer.position(0);
    
    textureOutputBuffer = ByteBuffer
        .allocateDirect(textureMap.length * 4) // float is 4 bytes
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer(); 
    textureOutputBuffer.put(textureMapFlip);
    textureOutputBuffer.position(0);
  }

  public void onSurfaceCreated( GL10 unused, EGLConfig config )
  {
    //queryGl(unused);
    
    setupScreenQuad();
    
    GLES20.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );  // set surface background color
    GLES20.glDisable(GLES20.GL_DITHER); // dithering causes really crappy/distracting visual artifacts when distorting the textures
    
    GLES20.glGenFramebuffers(1, mFramebuffer, 0);
    GLES20.glGenTextures(1, mRenderTexture, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mRenderTexture[0]);
    GLES20.glTexImage2D( GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256, 256, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null );//GLES20.GL_UNSIGNED_SHORT_5_6_5, null ); //GLES20.GL_UNSIGNED_BYTE, null );
    int filter = mFilterOutput ? GLES20.GL_LINEAR : GLES20.GL_NEAREST;
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, filter );
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR );
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
    GLES20.glTexParameteri( GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer[0]); // do I need to do this here?
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mRenderTexture[0], 0); // specify texture as color attachment
    
    if(isPreview)
    {
      setRandomBackground();
    }
    else if(persistBackgroundSelection && currentBackground >= 0 && currentBackground < getBackgroundsTotal())
    {
      loadBattleBackground(currentBackground);
    }
    else
    {
      //setRandomBackground();
      Wallpaper.setNewBackground(this);
    }
    
    /* shader for final output texture (the "low res") output */
    
    hFXProgram = createProgram(readTextFile(R.raw.passthrough_vert), readTextFile(R.raw.passthrough_frag));
    if(hFXProgram == 0) { throw new RuntimeException("[...] shader compilation failed"); }
    
    hPosition = GLES20.glGetAttribLocation(hFXProgram, "a_position"); // a_position
    hTexture = GLES20.glGetAttribLocation(hFXProgram, "a_texCoord"); // a_texCoord
    hBaseMap = GLES20.glGetUniformLocation(hFXProgram, "s_texture"); // get sampler locations
    
    // used when rendering to the GLOffscreenSurface to mirror screenshots about the horizontal axis
    
    if(mirrorVertical) {
      Matrix.scaleM(mProjMatrix, 0, 1, -1, 1);
    }
    
    // handle the rendering knobs
    
    frameTime = 1000 / 60; //frameTime = 1000 / Integer.valueOf(sharedPreferences.getString("intFramerate", null));
    
    
    Log.i(TAG, "Surface created");
  }

  private void updateShaderVariables()
  {
    // glUniform* calls always act on the current program that is bound with glUseProgram
    // have this method take an argument to determine which program to apply to
    
    Layer bg3 = battleGroup.battleBackground.getBg3();
    Layer bg4 = battleGroup.battleBackground.getBg4();
    
    // update shader resolution
    
    GLES20.glUniform2f(mResolutionLoc, mRenderWidth, mRenderHeight);
    
    // update distortion effect variables for the shader program
    
    GLES20.glUniform1i(mBg3DistTypeLoc, bg3.distortion.getType());
    GLES20.glUniform1i(mBg4DistTypeLoc, bg4.distortion.getType());
    GLES20.glUniform3f(mBg3DistLoc, bg3.distortion.computeShaderAmplitude(), bg3.distortion.computeShaderFrequency(), bg3.distortion.computeShaderSpeed());
    GLES20.glUniform3f(mBg4DistLoc, bg4.distortion.computeShaderAmplitude(), bg4.distortion.computeShaderFrequency(), bg4.distortion.computeShaderSpeed());
    GLES20.glUniform1f(mBg3CompressionLoc, bg3.distortion.computeShaderCompression());
    GLES20.glUniform1f(mBg4CompressionLoc, bg4.distortion.computeShaderCompression());
    
    // update translation effect variables for the shader program
    
    GLES20.glUniform2f(mBg3Scroll, bg3.translation.getHorizontalOffset(), bg3.translation.getVerticalOffset());
    GLES20.glUniform2f(mBg4Scroll, bg4.translation.getHorizontalOffset(), bg4.translation.getVerticalOffset());
    
    // update palette
    
    GLES20.glUniform4f(mBg3PaletteLoc, (float)bg3.getPaletteCycle1Begin(), (float)bg3.getPaletteCycle1End(), (float)bg3.getPaletteCycle2Begin(), (float)bg3.getPaletteCycle2End());
    GLES20.glUniform4f(mBg4PaletteLoc, (float)bg4.getPaletteCycle1Begin(), (float)bg4.getPaletteCycle1End(), (float)bg4.getPaletteCycle2Begin(), (float)bg4.getPaletteCycle2End());
    GLES20.glUniform1f(mBg3RotationLoc, (float)bg3.getPaletteRotation());
    GLES20.glUniform1f(mBg4RotationLoc, (float)bg4.getPaletteRotation());
    
    // old stuff
    GLES20.glUniform2i(mDistTypeLoc, bg3.distortion.getType(), bg4.distortion.getType());
    GLES20.glUniform2i(mCycleTypeLoc, bg3.getPaletteCycleType(), bg4.getPaletteCycleType());
  }
  
  public void loadBattleBackground(int index)
  {  
    synchronized(lock) {
      currentBackground = index;
      Log.i(Wallpaper.TAG, "Loading battle group " + index);
      battleGroup.load(index);
      
      byte[] dataA = battleGroup.battleBackground.getBg3().getImage();
      byte[] dataB = battleGroup.battleBackground.getBg4().getImage();
      byte[] paletteBg3 = battleGroup.battleBackground.getBg3().getPalette();
      byte[] paletteBg4 = battleGroup.battleBackground.getBg4().getPalette();
      int filter = mFilterBackgrounds ? GLES20.GL_LINEAR : GLES20.GL_NEAREST;
      
      //bbg.layerA.distortion.dump(0);
      //bbg.layerA.translation.dump(0);
      
      // http://code.google.com/p/android/issues/detail?id=6641
      mRenderEnemies = sharedPreferences.getBoolean("enableEnemies", false); // set instance variable here once so we're not loading the preference every frame
      boolean enablePaletteEffects = sharedPreferences.getBoolean("enablePaletteEffects", false);
      boolean enableLetterboxing = sharedPreferences.getBoolean("enableLetterboxing", false);
      
      int bufferSize;
      int format;
      if(enablePaletteEffects == true) {
        bufferSize = 256 * 256 * 1;
        format = GLES20.GL_LUMINANCE;
      } else {
        bufferSize = 256 * 256 * 4;
        format = GLES20.GL_RGBA;
      }
      
      if(mTextureA.capacity() != bufferSize) {
        mTextureA = ByteBuffer.allocateDirect(bufferSize);
        mTextureB = ByteBuffer.allocateDirect(bufferSize);
      }
      
      try {
            mTextureA.put(dataA).position(0);
            mTextureB.put(dataB).position(0);
      } catch(BufferOverflowException e) {
        
      }
          
          mPalette.position(0);
          mPalette.put(paletteBg3).position(0);
          
          mPalette.position(16 * 1 * 4);
          mPalette.put(paletteBg4).position(0);
          
          GLES20.glGenTextures(3, mTextureId, 0);
          
          // BG3 background layer
          
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[0]);
  
          GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, format, 256, 256, 0, format, GLES20.GL_UNSIGNED_BYTE, mTextureA);
          
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, filter);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, filter);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
          
          // BG4 background layer
  
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[1]);
  
          GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, format, 256, 256, 0, format, GLES20.GL_UNSIGNED_BYTE, mTextureB);
  
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, filter);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, filter);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
          
          // palettes
          
          GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[2]);
  
          GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 16, 16, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPalette);
  
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
          GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        
          // set up output display letterbox values for the shader
          
          if(enableLetterboxing == true)
          {
            String letterboxSize = sharedPreferences.getString("letterboxSize", null);
            
            if(letterboxSize.equals("variable"))
            {
              // attempt to include the existing extra space as a portion of the background's specified letter box
              // mLetterBoxSize = (battleGroup.getLetterBoxPixelSize() - outputPadding / outputScaler);
              mLetterBoxSize = battleGroup.getLetterBoxPixelSize();
            }
            else if(letterboxSize.equals("none")) {
              mLetterBoxSize = 0;
            } else if(letterboxSize.equals("small")) {
              mLetterBoxSize = 48;
            } else if(letterboxSize.equals("medium")) {
              mLetterBoxSize = 58;
            } else if(letterboxSize.equals("large")) {
              mLetterBoxSize = 68;
            }
          }
          else
          {
            mLetterBoxSize = 0;
      }
      
          /* shader for effects, update program uniforms */
      
      mProgram = shader.getShader(battleGroup.battleBackground, mLetterBoxSize);
      
      mPositionHandle = GLES20.glGetAttribLocation(mProgram, "a_position"); // a_position
      mTextureHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord"); // a_texCoord
      mBg3TextureLoc = GLES20.glGetUniformLocation(mProgram, "bg3_texture"); // get sampler locations
      mBg4TextureLoc = GLES20.glGetUniformLocation(mProgram, "bg4_texture"); // get sampler locations
      mPaletteLoc = GLES20.glGetUniformLocation(mProgram, "s_palette");
      
      mResolutionLoc = GLES20.glGetUniformLocation(mProgram, "resolution");
      mBg3DistTypeLoc = GLES20.glGetUniformLocation(mProgram, "bg3_dist_type");
      mBg4DistTypeLoc = GLES20.glGetUniformLocation(mProgram, "bg4_dist_type");
      mBg3DistLoc = GLES20.glGetUniformLocation(mProgram, "bg3_dist");
      mBg4DistLoc = GLES20.glGetUniformLocation(mProgram, "bg4_dist");
      mBg3Scroll = GLES20.glGetUniformLocation(mProgram, "bg3_scroll");
      mBg4Scroll = GLES20.glGetUniformLocation(mProgram, "bg4_scroll");
      mBg3PaletteLoc = GLES20.glGetUniformLocation(mProgram, "bg3_palette");
      mBg4PaletteLoc = GLES20.glGetUniformLocation(mProgram, "bg4_palette");
      mBg3CompressionLoc = GLES20.glGetUniformLocation(mProgram, "bg3_compression");
      mBg3RotationLoc = GLES20.glGetUniformLocation(mProgram, "bg3_rotation");
      mBg4CompressionLoc = GLES20.glGetUniformLocation(mProgram, "bg4_compression");
      mBg4RotationLoc = GLES20.glGetUniformLocation(mProgram, "bg4_rotation");
      
      // old stuff
      mCycleTypeLoc = GLES20.glGetUniformLocation(mProgram, "u_cycle_type");
      mDistTypeLoc = GLES20.glGetUniformLocation(mProgram, "u_dist_type");
      
      
      
      /* enemy loading stuff */
      if(mRenderEnemies)
      {
        byte[] spriteData = battleGroup.enemy.getBattleSprite();
        ByteBuffer sprite = ByteBuffer.allocateDirect(spriteData.length);
        
            sprite.put(spriteData).position(0);
        
        GLES20.glGenTextures(1, mBattleSpriteId, 0);
        
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBattleSpriteId[0]);
        
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, battleGroup.enemy.getBattleSpriteWidth(), battleGroup.enemy.getBattleSpriteHeight(), 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, sprite);
            
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        
            mBattleSpriteProgramId = shader.getSpriteShader();
            
            mEnemyPositionHandle = GLES20.glGetAttribLocation(mBattleSpriteProgramId, "a_position"); // a_position
        mEnemyTextureHandle = GLES20.glGetAttribLocation(mBattleSpriteProgramId, "a_texCoord"); // a_texCoord
        mEnemyTextureLoc = GLES20.glGetUniformLocation(mBattleSpriteProgramId, "s_texture");
        
        float rowOffset = 0.0f;
        if(battleGroup.enemy.getCurrentName().equals("Giygas")) {
          // quick hack to get the one Giygas background aligned properly in lieu of supporting multiple enemies
          // and their rows (for now)
          rowOffset = battleGroup.enemy.getRow() * (1.0f / 224.0f) * 32.0f;
        }
        
        float x = (1.0f / 256.0f) * (battleGroup.enemy.getBattleSpriteWidth());
        float y = (1.0f / 224.0f) * (battleGroup.enemy.getBattleSpriteHeight());

        float quadVertices[] =
        {
          -x,  -y + rowOffset,   0.0f,
           x,  -y + rowOffset,   0.0f,
          -x,   y + rowOffset,   0.0f,
           x,   y + rowOffset,   0.0f       
        };
        
        float textureMap[] =
        {
          0.0f,   1.0f,
          1.0f,   1.0f,
          0.0f,   0.0f,
          1.0f,   0.0f 
        };
        
        enemyVertexBuffer = ByteBuffer
            .allocateDirect(quadVertices.length * 4) // float is 4 bytes
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer(); 
        enemyVertexBuffer.put(quadVertices);
        enemyVertexBuffer.position(0);
        
        enemyTextureVertexBuffer = ByteBuffer
            .allocateDirect(textureMap.length * 4) // float is 4 bytes
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer(); 
        enemyTextureVertexBuffer.put(textureMap);
        enemyTextureVertexBuffer.position(0);
      }
      
      if(mRenderEnemies) {
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
      } else {
        GLES20.glDisable(GLES20.GL_BLEND);
      }
      
    }
  }
  
  private void renderScene()
  {
    mRenderWidth = 256.0f;
    mRenderHeight = 256.0f;
    
    GLES20.glViewport(0, 0, 256, 224);  // render to native texture size, scale up later
    
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer[0]);
    
    /* it may be prudent to check the framebuffer status here before continuing... */
    
    renderBattleBackground();
    if(mRenderEnemies) renderEnemy();
    
    /* now, try to render the texture? */
    
    GLES20.glUseProgram(hFXProgram);
    
    GLES20.glViewport(mSurfaceHorizontalOffset, mSurfaceVerticalOffset, mSurfaceWidth, mSurfaceHeight);    // now we're scaling the framebuffer up to size
    
    hMVPMatrix = GLES20.glGetUniformLocation(hFXProgram, "uMVPMatrix");/* projection and camera */
    
    /* load vertex positions */
    
    GLES20.glVertexAttribPointer(hPosition, 3, GLES20.GL_FLOAT, false, 12, quadVertexBuffer);
    GLES20.glEnableVertexAttribArray(hPosition);
    
    /* load texture mapping */

    GLES20.glVertexAttribPointer(hTexture, 2, GLES20.GL_FLOAT, false, 8, textureOutputBuffer);
    GLES20.glEnableVertexAttribArray(hTexture);
    
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mRenderTexture[0]);
    
    GLES20.glUniform1i(hBaseMap, 0);
    
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    
    GLES20.glUniformMatrix4fv(hMVPMatrix, 1, false, mProjMatrix, 0);  /* projection and camera */
    
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
  }
  
  private void renderBattleBackground() // "high res" render
  {
    hMVPMatrix = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");/* projection and camera */
    
    GLES20.glUseProgram(mProgram);
    
    /* load vertex positions */
    
    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 12, quadVertexBuffer);
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    
    /* load texture mapping */

    GLES20.glVertexAttribPointer(mTextureHandle, 2, GLES20.GL_FLOAT, false, 8, textureVertexBuffer);
    GLES20.glEnableVertexAttribArray(mTextureHandle);
    
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[0]);
    GLES20.glUniform1i(mBg3TextureLoc, 0);
    
    GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[1]);
    GLES20.glUniform1i(mBg4TextureLoc, 1);
    
    GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId[2]);
    GLES20.glUniform1i(mPaletteLoc, 2);
    
    updateShaderVariables(); // be mindful of which active program this applies to!!
    
    /* apply model view projection transformation */
    
    GLES20.glUniformMatrix4fv(hMVPMatrix, 1, false, mProjMatrix, 0);  /* projection and camera */
    
    /* draw the triangles */
    
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
  }
  
  private void renderEnemy()
  {
    hMVPMatrix = GLES20.glGetUniformLocation(mBattleSpriteProgramId, "uMVPMatrix");/* projection and camera */
    
    GLES20.glUseProgram(mBattleSpriteProgramId);
    
    /* load vertex positions */
    
    GLES20.glVertexAttribPointer(mEnemyPositionHandle, 3, GLES20.GL_FLOAT, false, 12, enemyVertexBuffer);
    GLES20.glEnableVertexAttribArray(mEnemyPositionHandle);
    
    /* load texture mapping */

    GLES20.glVertexAttribPointer(mEnemyTextureHandle, 2, GLES20.GL_FLOAT, false, 8, enemyTextureVertexBuffer);
    GLES20.glEnableVertexAttribArray(mEnemyTextureHandle);
    
    GLES20.glActiveTexture(GLES20.GL_TEXTURE3);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBattleSpriteId[0]);
    GLES20.glUniform1i(mEnemyTextureLoc, 3);
    
    /* apply model view projection transformation */
    
    GLES20.glUniformMatrix4fv(hMVPMatrix, 1, false, mProjMatrix, 0);  /* projection and camera */
    
    /* draw the triangles */
    
    GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
  }
  
  private void checkGlError(String op)
  {
    /* from developer.android.com */
    int error;
    while((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
      Log.e(TAG, op + ": glError " + error);
      throw new RuntimeException(op + ": glError " + error);
    }
  }
  
  private int createProgram(String vertexSource, String fragmentSource)
  {
    // courtesy of android.developer.com
    int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
    if(vertexShader == 0) {
      return 0;
    }

    int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
    if(pixelShader == 0) {
      return 0;
    }

    int program = GLES20.glCreateProgram();
    if(program != 0) {
      GLES20.glAttachShader(program, vertexShader);
      checkGlError("glAttachShader");
      GLES20.glAttachShader(program, pixelShader);
      checkGlError("glAttachShader");
      GLES20.glLinkProgram(program);
      int[] linkStatus = new int[1];
      GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
      if(linkStatus[0] != GLES20.GL_TRUE) {
        Log.e(TAG, "Could not link program: ");
        Log.e(TAG, GLES20.glGetProgramInfoLog(program));
        GLES20.glDeleteProgram(program);
        program = 0;
      }
    }
    return program;
  }
  
  private int loadShader(int shaderType, String source)
  {
    
//  int loadShader(int type, String code) {
//    int shader = GLES20.glCreateShader(type);
//    GLES20.glShaderSource(shader, code);
//    GLES20.glCompileShader(shader);
//    return shader;
//  }
    
    int shader = GLES20.glCreateShader(shaderType);
    if(shader != 0) {
      GLES20.glShaderSource(shader, source);
      GLES20.glCompileShader(shader);
      int[] compiled = new int[1];
      GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
      if(compiled[0] == 0) {
        Log.e(TAG, "Could not compile shader " + shaderType + ":");
        Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
        GLES20.glDeleteShader(shader);
        shader = 0;
      }
    }
    return shader;
  }
  
  private String readTextFile(final int resourceId)
  {
    /* method lifted from learnopengles.com */
    final InputStream inputStream = context.getResources().openRawResource(resourceId);
    final InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
    final BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
 
    String nextLine;
    final StringBuilder body = new StringBuilder();
     
    try
    {
      while ((nextLine = bufferedReader.readLine()) != null)
      {
        body.append(nextLine);
        body.append('\n');
      }
    }
    catch (IOException e)
    {
      return null;
    }
 
    return body.toString();
  }
  
  private void queryGl(GL10 gl10)
  {
    //String extensions = GLES20.glGetString(GLES20.GL_EXTENSIONS);
    //Log.i("GLInfo", extensions);
    int[] params = new int[64];
    
    GLES20.glGetIntegerv(GLES20.GL_ALIASED_LINE_WIDTH_RANGE, params, 0);
    Log.i("GLInfo", String.format("GLES20.GL_ALIASED_LINE_WIDTH_RANGE: %d - %d", params[0], params[1]));
  }
}




Java Source Code List

net.georgewhiteside.android.abstractart.AbstractArt.java
net.georgewhiteside.android.abstractart.BattleBackground.java
net.georgewhiteside.android.abstractart.BattleGroup.java
net.georgewhiteside.android.abstractart.Cache.java
net.georgewhiteside.android.abstractart.Distortion.java
net.georgewhiteside.android.abstractart.Enemy.java
net.georgewhiteside.android.abstractart.FPSCounter.java
net.georgewhiteside.android.abstractart.GLOffscreenSurface.java
net.georgewhiteside.android.abstractart.ImageLoader.java
net.georgewhiteside.android.abstractart.Layer.java
net.georgewhiteside.android.abstractart.Renderer.java
net.georgewhiteside.android.abstractart.RomUtil.java
net.georgewhiteside.android.abstractart.ServiceDialog.java
net.georgewhiteside.android.abstractart.Settings.java
net.georgewhiteside.android.abstractart.ShaderFactory.java
net.georgewhiteside.android.abstractart.Translation.java
net.georgewhiteside.android.abstractart.UniformGridView.java
net.georgewhiteside.android.abstractart.Wallpaper.java
net.georgewhiteside.android.abstractart.settings.BackgroundSelector.java
net.georgewhiteside.android.abstractart.settings.ClearCachePreference.java
net.georgewhiteside.android.abstractart.settings.CreateImageCachePreference.java
net.georgewhiteside.android.abstractart.settings.FrameRatePreference.java
net.georgewhiteside.android.abstractart.settings.ThumbnailAdapter.java
net.georgewhiteside.utility.Dimension.java
net.starmen.pkhack.HackModule.java
org.jf.GLWallpaper.GLWallpaperService.java
sheetrock.panda.changelog.ChangeLog.java