package com.af.experiments.FxCameraApp.shaders;
import android.content.res.Resources;
import com.af.experiments.FxCameraApp.Utils.OpenGlUtils;
import com.af.experiments.FxCameraApp.renderer.GLES20FramebufferObject;
import java.util.HashMap;
import static android.opengl.GLES20.*;
public class GlShader {
public static final String DEFAULT_ATTRIB_POSITION = "aPosition";
public static final String DEFAULT_ATTRIB_TEXTURE_COORDINATE = "aTextureCoord";
public static final String DEFAULT_UNIFORM_SAMPLER = "sTexture";
protected String mShaderName = "default";
public String getName() {
return mShaderName;
}
protected static final String DEFAULT_VERTEX_SHADER =
"attribute vec4 aPosition;\n" +
"attribute vec4 aTextureCoord;\n" +
"varying highp vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = aPosition;\n" +
"vTextureCoord = aTextureCoord.xy;\n" +
"}\n";
protected static final String DEFAULT_FRAGMENT_SHADER =
"precision mediump float;\n" +
"varying highp vec2 vTextureCoord;\n" +
"uniform lowp sampler2D sTexture;\n" +
"void main() {\n" +
"gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}\n";
private static final float[] VERTICES_DATA = new float[] {
// X, Y, Z, U, V
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f
};
private static final int FLOAT_SIZE_BYTES = 4;
protected static final int VERTICES_DATA_POS_SIZE = 3;
protected static final int VERTICES_DATA_UV_SIZE = 2;
protected static final int VERTICES_DATA_STRIDE_BYTES = (VERTICES_DATA_POS_SIZE + VERTICES_DATA_UV_SIZE) * FLOAT_SIZE_BYTES;
protected static final int VERTICES_DATA_POS_OFFSET = 0 * FLOAT_SIZE_BYTES;
protected static final int VERTICES_DATA_UV_OFFSET = VERTICES_DATA_POS_OFFSET + VERTICES_DATA_POS_SIZE * FLOAT_SIZE_BYTES;
private final String mVertexShaderSource;
private final String mFragmentShaderSource;
private int mProgram;
private int mVertexShader;
private int mFragmentShader;
private int mVertexBufferName;
private final HashMap<String, Integer> mHandleMap = new HashMap<String, Integer>();
public GlShader() {
this(DEFAULT_VERTEX_SHADER, DEFAULT_FRAGMENT_SHADER);
}
public GlShader(final Resources res, final int vertexShaderSourceResId, final int fragmentShaderSourceResId) {
this(res.getString(vertexShaderSourceResId), res.getString(fragmentShaderSourceResId));
}
public GlShader(final String vertexShaderSource, final String fragmentShaderSource) {
mVertexShaderSource = vertexShaderSource;
mFragmentShaderSource = fragmentShaderSource;
}
public void setup() {
release();
mVertexShader = OpenGlUtils.loadShader(mVertexShaderSource, GL_VERTEX_SHADER);
mFragmentShader = OpenGlUtils.loadShader(mFragmentShaderSource, GL_FRAGMENT_SHADER);
mProgram = OpenGlUtils.createProgram(mVertexShader, mFragmentShader);
mVertexBufferName = OpenGlUtils.createBuffer(VERTICES_DATA);
}
public void setFrameSize(final int width, final int height) {
}
public void release() {
glDeleteProgram(mProgram);
mProgram = 0;
glDeleteShader(mVertexShader);
mVertexShader = 0;
glDeleteShader(mFragmentShader);
mFragmentShader = 0;
glDeleteBuffers(1, new int[]{ mVertexBufferName }, 0);
mVertexBufferName = 0;
mHandleMap.clear();
}
public void draw(final int texName, final GLES20FramebufferObject fbo) {
useProgram();
glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferName);
glEnableVertexAttribArray(getHandle("aPosition"));
glVertexAttribPointer(getHandle("aPosition"), VERTICES_DATA_POS_SIZE, GL_FLOAT, false, VERTICES_DATA_STRIDE_BYTES, VERTICES_DATA_POS_OFFSET);
glEnableVertexAttribArray(getHandle("aTextureCoord"));
glVertexAttribPointer(getHandle("aTextureCoord"), VERTICES_DATA_UV_SIZE, GL_FLOAT, false, VERTICES_DATA_STRIDE_BYTES, VERTICES_DATA_UV_OFFSET);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texName);
glUniform1i(getHandle("sTexture"), 0);
onDraw();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(getHandle("aPosition"));
glDisableVertexAttribArray(getHandle("aTextureCoord"));
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
protected void onDraw() {}
protected final void useProgram() {
glUseProgram(mProgram);
}
protected final int getVertexBufferName() {
return mVertexBufferName;
}
protected final int getHandle(final String name) {
final Integer value = mHandleMap.get(name);
if (value != null) {
return value.intValue();
}
int location = glGetAttribLocation(mProgram, name);
if (location == -1) {
location = glGetUniformLocation(mProgram, name);
}
if (location == -1) {
throw new IllegalStateException("Could not get attrib or uniform location for " + name);
}
mHandleMap.put(name, Integer.valueOf(location));
return location;
}
protected final int[] getHandles(final String...names) {
if (names == null) {
return null;
}
final int[] results = new int[names.length];
int count = 0;
for (final String name : names) {
results[count] = getHandle(name);
count++;
}
return results;
}
}