目录
OpenGL的坐标系
顶点着色器,片元着色器
vertex_shader.glsl
attribute vec4 av_Position;
void main(){
gl_Position = av_Position;
}
注: attribute 只能在vertex中使用
fragment_shader.glsl
precision mediump float;
uniform vec4 af_Potion;
void main(){
gl_FragColor = af_Potion;
}
注: uniform 用于在application中向vertex和fragment中传递值。
ShaderUtil.java
package com.jianji.delogo.Test.MediaCodec;
import android.content.Context;
import android.opengl.GLES20;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ShaderUtil {
private static final String TAG = "ShaderUtil";
/**
* 读取shader
*
* @param context
* @param rawId
* @return
*/
public static String readRawTxt(Context context, int rawId) {
InputStream inputStream = context.getResources().openRawResource(rawId);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer sb = new StringBuffer();
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* 加载shader
*
* @param shaderType
* @param source
* @return
*/
private static int loadShader(int shaderType, String source) {
//创建shader
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
//关联source
GLES20.glShaderSource(shader, source);
//编译
GLES20.glCompileShader(shader);
//获取编译状态
int[] compile = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compile, 0);
if (compile[0] != GLES20.GL_TRUE) {
//失败
Log.e(TAG, "loadShader: shader compile error");
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
/**
* 生成程序
*
* @param vertexSource
* @param fragmentSource
* @return
*/
public static int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (fragmentShader == 0) {
return 0;
}
//创建
int program = GLES20.glCreateProgram();
if (program != 0) {
//附加着色器
GLES20.glAttachShader(program, vertexShader);
GLES20.glAttachShader(program, fragmentShader);
//连接
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, "createProgram: link program error");
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
}
GLTestView.java
package com.jianji.delogo.Test.MediaCodec;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import com.jianji.delogo.R;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class GLTestView extends GLSurfaceView implements GLSurfaceView.Renderer {
private Context context;
//绘制坐标范围
float[] vertexData = {
-1f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f
};
//为坐标分配本地内存地址,不受jvm的影响
FloatBuffer vertexBuffer;
public GLTestView(Context context) {
this(context, null);
}
public GLTestView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
//设置OpenGL的版本
setEGLContextClientVersion(2);
setRenderer(this);
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
.order(ByteOrder.nativeOrder())//对齐,加快处理速度
.asFloatBuffer()
.put(vertexData);
//指向0的位置
vertexBuffer.position(0);
}
private int program;
private int avPosition;
private int afColor;
/**
* Called when the surface is created or recreated.
*/
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
String vertexSource = ShaderUtil.readRawTxt(context, R.raw.vertex_shader);
String fragmentSource = ShaderUtil.readRawTxt(context,R.raw.fragment_shader);
program = ShaderUtil.createProgram(vertexSource,fragmentSource);
if (program > 0) {
avPosition = GLES20.glGetAttribLocation(program,"av_Position");
afColor = GLES20.glGetUniformLocation(program,"af_Color");
}
}
/**
* Called when the surface changed size.
*/
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//设置大小位置
GLES20.glViewport(0, 0, width, height);
}
/**
* Called to draw the current frame.
*/
@Override
public void onDrawFrame(GL10 gl) {
//清屏,清理掉颜色的缓冲区
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
//设置清屏的颜色,这里是float颜色的取值范围的[0,1]
GLES20.glClearColor(1.0f, 0f, 0f, 1.0f);
//使用program
GLES20.glUseProgram(program);
//设置颜色,和颜色的色值
GLES20.glUniform4f(afColor,1f,1f,0f,1f);
//设置为可用的状态
GLES20.glEnableVertexAttribArray(avPosition);
//size 指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
//stride 指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
GLES20.glVertexAttribPointer(avPosition,2,GLES20.GL_FLOAT,false,8, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0,3);
}
}