色の変更
前回までのサンプルでは、北海道のポリライン情報に対して色情報を固定の状態で描画を行いました。オーソドックスな方法の場合、ポリラインなどに対して色情報を与えるには、頂点ごとに色を指定して描画を行いますが、地図エンジンではスタイルの切り替えを行うため、この方法は採用していません。代わりにシェーダに対して色を指定する方法で行います。変更点は以下になります。
public class Shader {
public static byte ID_MAX = 0;
public static final byte ID_VuColor= ID_MAX++;
protected int[] mShaderParameter = null;
/**
* 頂点シェーダプログラム
*/
private final String VSHADER_SOURCE =
"precision highp float;" +
"attribute vec4 a_Position;\n" +
"uniform mat4 u_ViewMatrix;\n" +
"uniform mat4 u_ProjMatrix;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
" gl_Position = u_ProjMatrix * u_ViewMatrix * a_Position;\n" +
" gl_PointSize = 16.0;" +
"}\n";
/**
* フラグメントシェーダプログラム
*/
private final String FSHADER_SOURCE =
"precision highp float;" +
"uniform vec4 u_Color;" +
"void main() {\n" +
// " gl_FragColor = vec4(1.0,1.0,1.0,1.0);\n" +
" gl_FragColor = u_Color;\n" +
"}\n";
/**
* コンストラクタ
*/
public Shader() {
mShaderParameter = new int[ID_MAX];
}
/**
* シェーダープログラムを読み込みコンパイルします。
* @return
*/
public int initShaders() {
int program = createProgram();
GLES20.glUseProgram(program);
return program;
}
/**
* プログラムオブジェクトを作成します。
* @return
*/
public int createProgram() {
// シェーダオブジェクトを作成する
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, this.VSHADER_SOURCE);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, this.FSHADER_SOURCE);
// プログラムオブジェクトを作成する
int program = GLES20.glCreateProgram();
if (program == 0) {
throw new RuntimeException("failed to create program");
}
// シェーダオブジェクトを設定する
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
// プログラムオブジェクトをリンクする
GLES20.glLinkProgram(program);
// リンク結果をチェックする
int[] linked = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linked, 0);
if (linked[0] != GLES20.GL_TRUE) {
String error = GLES20.glGetProgramInfoLog(program);
throw new RuntimeException("failed to link program: " + error);
}
// 値のパイプを設定
setShaderParamaterId(ID_VuColor, GLES20.glGetUniformLocation(program, "u_Color"));
return program;
}
/**
* シェーダを読み込みます。
* @param type
* @param source
* @return
*/
public int loadShader(int type, String source) {
// シェーダオブジェクトを作成する
int shader = GLES20.glCreateShader(type);
if (shader == 0) {
throw new RuntimeException("unable to create shader");
}
// シェーダのプログラムを設定する
GLES20.glShaderSource(shader, source);
// シェーダをコンパイルする
GLES20.glCompileShader(shader);
// コンパイル結果を検査する
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] != GLES20.GL_TRUE) {
String error = GLES20.glGetShaderInfoLog(shader);
throw new RuntimeException("failed to compile shader: " + error);
}
return shader;
}
/**
* パイプ配列を設定する
* @param id
* @param value
*/
public void setShaderParamaterId(byte id, int value) {
mShaderParameter[id] = value;
}
/**
* 指定のパイプを返す
* @param id
* @return
*/
public int getShaderParameterId(byte id) {
return mShaderParameter[id];
}
}
※追加・変更箇所は太字にしています。
省略
@Override
public void onDrawFrame(GL10 arg0) {
synchronized (mFrontModelViewMatrix) {
mFrontModelViewMatrix.copy(mBackModelViewMatrix);
mFrontProjectionMatrix.copy(mBackProjectionMatrix);
}
//行列をセット
GLES20.glUniformMatrix4fv(muViewMatrix, 1, false, mBackModelViewMatrix.matrix, 0);
GLES20.glUniformMatrix4fv(muProjMatrix, 1, false, mBackProjectionMatrix.matrix, 0);
//背景色を設定します。
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); //海色を指定
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
//線を描画
drawLine(mAPosition,2.0f,0.0f,0.0f,0.0f,1.0f);
}
/**
* ポリラインを描画する
* @param pos
*/
public void drawLine(int pos,float width,float r,float g,float b,float a) {
//線の色を設定します
GLES20.glUniform4f(mShader.getShaderParameterId(Shader.ID_VuColor),r,g,b,a);
//線幅を設定します
GLES20.glLineWidth(width);
//頂点バッファを設定します
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexId);
GLES20.glVertexAttribPointer(pos, 3, GLES20.GL_FLOAT, false, FSIZE*3, 0);
//描画
GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, mNumVertices);
}
省略
※追加・変更箇所は太字にしています。
下記図5のように表示されたでしょうか。見やすいように背景色の変更も行っています。
フラグメントシェーダ部分の「gl_FragColor」に対して、GL20MyRender内から「GLES20.glUniform4f(mShader.getShaderParameterId(Shader.ID_VuColor),r,g,b,a);」で色を渡しています。前回までのサンプルは、シェーダ内で色を固定にしていましたが、今回のサンプルのようにシェーダに対して外からインプットできるようにすることで、その時々のスタイルにあわせた色に変更が可能です。基礎的な方法ではありますが、いろいろと応用ができますので参考にしてください。
シェーダを応用すると、より効率的な方法で描画することが可能になります。ぜひいろいろトライしてみてください。それでは、つぎにシェーダを少し応用して破線を描いてみたいと思います。

