Last active
August 29, 2015 14:05
-
-
Save ErikHellman/d4c04005ec4401e3213a to your computer and use it in GitHub Desktop.
Simple renderer for a pixel shader on Android
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class VisualizationRenderer implements GLSurfaceView.Renderer { | |
private static final int FLOAT_SIZE_BYTES = Float.SIZE / Byte.SIZE; | |
private final FloatBuffer mRectData; | |
private final Context mContext; | |
private String mVertexShader; | |
private String mFragmentShader; | |
public VisualizationRenderer(Context context) { | |
mContext = context; | |
float[] rectData = new float[]{ | |
-1f, -1f, | |
-1f, 1f, | |
1f, -1f, | |
1f, 1f, | |
}; | |
mRectData = ByteBuffer.allocateDirect(rectData.length * FLOAT_SIZE_BYTES) | |
.order(ByteOrder.nativeOrder()).asFloatBuffer(); | |
mRectData.put(rectData).position(0); | |
mVertexShader = readShader(R.raw.vertex_shader, context); | |
mFragmentShader = readShader(R.raw.fragment_shader, context); | |
} | |
@Override | |
public void onSurfaceCreated(GL10 gl, EGLConfig config) { | |
int program = createProgram(mVertexShader, mFragmentShader); | |
if (program == 0) { | |
Log.e(TAG, "createProgram failed!"); | |
return; | |
} | |
int maPositionHandle = GLES20.glGetAttribLocation(program, "aPosition"); | |
checkGlError("glGetAttribLocation aPosition"); | |
if (maPositionHandle == -1) { | |
throw new RuntimeException("Could not get attrib location for aPosition"); | |
} | |
GLES20.glUseProgram(program); | |
checkGlError("glUseProgram mProgram"); | |
GLES20.glEnableVertexAttribArray(maPositionHandle); | |
checkGlError("glEnableVertexAttribArray maPositionHandle"); | |
mRectData.position(0); | |
GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT, false, 0, mRectData); | |
checkGlError("glVertexAttribPointer maPosition"); | |
} | |
@Override | |
public void onSurfaceChanged(GL10 gl, int width, int height) { | |
GLES20.glViewport(0, 0, width, height); | |
checkGlError("glViewPort"); | |
} | |
@Override | |
public void onDrawFrame(GL10 gl) { | |
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); | |
checkGlError("glClear"); | |
GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f); | |
checkGlError("glClearColor"); | |
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); | |
checkGlError("glDrawArrays"); | |
} | |
private int loadShader(int shaderType, String source) { | |
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 int createProgram(String vertexSource, String fragmentSource) { | |
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 static String readShader(int resource, Context context) { | |
Resources resources = context.getResources(); | |
InputStream inputStream = resources.openRawResource(resource); | |
InputStreamReader inputStreamReader = new InputStreamReader(inputStream); | |
BufferedReader bufferedReader = new BufferedReader(inputStreamReader); | |
char[] buffer = new char[32]; | |
int charsRead; | |
StringBuilder stringBuilder = new StringBuilder(); | |
try { | |
while ((charsRead = bufferedReader.read(buffer)) != -1) { | |
stringBuilder.append(buffer, 0, charsRead); | |
} | |
} catch (IOException e) { | |
Log.e(TAG, "Error reading resource " + resource, e); | |
} | |
return stringBuilder.toString(); | |
} | |
private void checkGlError(String op) { | |
int error; | |
boolean hasError = false; | |
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { | |
Log.e(TAG, op + ": glError " + error); | |
hasError = true; | |
} | |
if (hasError) { | |
throw new RuntimeException(op + ": glError " + error); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment