您的位置:首页 > 移动开发 > Android开发

Opengles2.0 for android入门笔记(一)

2016-11-16 19:57 393 查看
oepngles2.0 for android的教程少的可怜,有的居然还是opengles 1.0版本的。鄙人刚学opengles,理论也是一知半解,其实android已经帮我们封装了一些内容了,so我直接从最基础的用法开始记录了。

1.oepngles2.0绘图基本流程

图形是绘制在GlSurfaceView中的,也就是画布。而具体绘制什么是由GLSurfaceView.Renderer的实现类绘制的,也就是画笔,简称为render。render在onDrawFrame函数中绘制每一帧图像,具体到每一个像素应该具体绘制什么颜色则由传说中的着色器语言和opengl接口协作完成。

2.最基础的使用,绘制一个矩形。opengles没有接口可以画一个矩形,神马?大安卓居然没有封装?画第一个矩形真是件艰巨的任务。那就老老实实开始画吧,等等,在manifest中加这句话:先,然后:

a.创建画布和画笔呗,也就是GlSurfaceView和GLSurfaceView.Renderer的实现类

public class MainActivity extends AppCompatActivity {
private String TAG = MainActivity.class.getSimpleName();
private GLSurfaceView glSurfaceView;
TraingleRender glRender;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout mainLayout = (FrameLayout) findViewById(R.id.activity_mainLayout);

glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setEGLContextClientVersion(2);
glRender = new TraingleRender(this);
//设置背景透明
glSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

glSurfaceView.setRenderer(glRender);
mainLayout.addView(glSurfaceView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

}

protected void onResume() {
super.onResume();
glSurfaceView.onResume();
}

@Override
protected void onPause() {
super.onPause();
glSurfaceView.onPause();

}
}


TraingleRender类内容如下:

public class TraingleRender implements GLSurfaceView.Renderer {
private String TAG = TraingleRender.class.getSimpleName();
private int traingleProgramId;
private int traingleVerticesId;
private int traingleColorId;

Context context;
Triangle triangle;

public TraingleRender(Context context){
this.context = context;
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
triangle = new Triangle(context);
initRender();
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
glViewport(0,0,width,height);
}

@Override
public void onDrawFrame(GL10 gl) {
triangle.draw(traingleProgramId,traingleVerticesId,traingleColorId);

}
public void initRender(){
String verticesShader = OpenglHelper.readShaderTextFromRaw(context,R.raw.traingle_vertex_shader);
String fragmentShader = OpenglHelper.readShaderTextFromRaw(context,R.raw.traingle_fragment_shader);
traingleProgramId = OpenglHelper.initProgramFromShaderSrc(verticesShader,fragmentShader);
traingleVerticesId = GLES20.glGetAttribLocation(traingleProgramId,"a_Position");
traingleColorId = GLES20.glGetUniformLocation(traingleProgramId,"u_Color");

}

}


b.编译着色器语言。麻蛋,画个三角形还要介个?还好可以写到static函数里重用。在res下创建raw文件夹,在raw下创建traingle_vertex_shader.glsl和traingle_fragment_shader.glsl文件,两个文件内容如下:

traingle_vertex_shader.glsl:

attribute vec4 a_Position;
void main()
{
gl_Position = a_Position;
}


traingle_fragment_shader.glsl:

precision mediump float;
uniform vec4 u_Color;
void main() {
gl_FragColor = u_Color;
}


然后用用我们的Util编译,此处叫OpenglHelper,内容如下:

public class OpenglHelper {
private static String TAG = OpenglHelper.class.getSimpleName();

public static String readShaderTextFromRaw(Context context, int resourceId) {

StringBuilder body = new StringBuilder();
try {
InputStream inputStream =
context.getResources().openRawResource(resourceId);
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String nextLine;
while ((nextLine = bufferedReader.readLine()) != null) {
body.append(nextLine);
body.append('\n');
}
} catch (IOException e) {
throw new RuntimeException(
"Could not open resource: " + resourceId, e);
} catch (Resources.NotFoundException nfe) {
throw new RuntimeException("Resource not found: " + resourceId, nfe);
}
return body.toString();

}

private static int compileShader(int type, String shaderCode) {
final int shaderId = glCreateShader(type);
if (shaderId == 0) {
Log.w(TAG, "Could not create new shader.");
return 0;
}
glShaderSource(shaderId, shaderCode);
glCompileShader(shaderId);
final int[] compileStatus = new int[1];
glGetShaderiv(shaderId, GL_COMPILE_STATUS, compileStatus, 0);

if (compileStatus[0] == 0) {
// If it failed, delete the shader object.
glDeleteShader(shaderId);
Log.w(TAG, "Compilation of shader failed.");
return 0;
}
return shaderId;

}

public static int initProgramFromShaderSrc(String vertexShaderSrc,
String fragmentShaderSrc) {
int vertShader = compileShader(GL_VERTEX_SHADER, vertexShaderSrc);
int fragShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);

if (vertShader == 0 || fragShader == 0)
return 0;

int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertShader);
checkGLError("glAttchShader(vert)");

GLES20.glAttachShader(program, fragShader);
checkGLError("glAttchShader(frag)");

GLES20.glLinkProgram(program);
int[] glStatusVar = {GLES20.GL_FALSE};
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, glStatusVar,
0);
if (glStatusVar[0] == GLES20.GL_FALSE) {
Log.e(
TAG,
"Could NOT link program : "
+ GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}

return program;
}

public static void checkGLError(String op) {
for (int error = GLES20.glGetError(); error != 0; error = GLES20
.glGetError())
Log.e(
TAG,
"After operation " + op + " got glError 0x"
+ Integer.toHexString(error));
}

public static Buffer fillFloatBuffer(float[] array) {
// Convert to floats because OpenGL doesnt work on doubles, and manually
// casting each input value would take too much time.
ByteBuffer bb = ByteBuffer.allocateDirect(4 * array.length); // each float takes 4 bytes
bb.order(ByteOrder.LITTLE_ENDIAN);
for (float d : array)
bb.putFloat(d);
bb.rewind();

return bb;

}

public static int loadTexture(Context context, int resourceId) {
final int[] textureObjectIds = new int[1];
glGenTextures(1, textureObjectIds, 0);
if (textureObjectIds[0] == 0) {
Log.w(TAG, "Could not generate a new OpenGL texture object.");
return 0;
}
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
final Bitmap bitmap = BitmapFactory.decodeResource(
context.getResources(), resourceId, options);
if (bitmap == null) {
Log.w(TAG, "Resource ID " + resourceId + " could not be decoded.");
glDeleteTextures(1, textureObjectIds, 0);
return 0;
}
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
//        glGenerateMipmap(GL_TEXTURE_2D);
//        glBindTexture(GL_TEXTURE_2D, 0);
return textureObjectIds[0];

}

}


c.终于可以画东西了,创建我们的Traingle.java,内容如下:

public class Triangle {
private Context context;
private float vertices[] = {0.0f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f};
private Buffer verticesBuffer;

public Triangle(Context context) {
this.context = context;
verticesBuffer = array2Buffer(vertices);
}

public void draw(int traingleProgramId, int traingleVerticesId, int traingleColorId) {
verticesBuffer.position(0);
glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

GLES20.glUseProgram(traingleProgramId);
GLES20.glVertexAttribPointer(traingleVerticesId, 2, GLES20.GL_FLOAT,
false, 0, verticesBuffer);
GLES20.glEnableVertexAttribArray(traingleVerticesId);
GLES20.glUniform4f(traingleColorId, 0.8f, 0.5f, 1.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);

}

public static Buffer array2Buffer(float[] array) {
// Convert to floats because OpenGL doesn't work on doubles, and manually
// casting each input value would take too much time.
// Each float takes 4 bytes
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * array.length);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
for (double d : array)
byteBuffer.putFloat((float) d);
byteBuffer.rewind();

return byteBuffer;

}

}


TraingleDemo下载链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: